当前位置: 首页 > news >正文

通讯录小练习:柔性数组和文件操作实现

目录

一.程序功能

二.定义关键类型的头文件与枚举的应用

三.封装柔性数组的增容函数与缩容函数

四.添加联系人功能模块

五 .联系人信息打印模块

六. 查找指定联系人的模块

七.删除指定联系人模块

八.修改指定联系人信息模块

九.排序模块

九.文件操作模块

十.通讯录初始化模块

十一.代码总览

contact.h头文件

contactfunction.h头文件

通讯录基本功能模块源文件 

文件操作模块源文件

排序模块源文件: 

主函数测试模块源文件: 


一.程序功能

实现一个通讯录;
通讯录可以用来存储联系人的信息包括:姓名、性别、年龄、电话、住址
提供方法:
1.添加联系人信息
2.删除指定联系人信息
3.查找指定联系人信息
4.修改指定联系人信息
5.显示所有联系人信息
6.清空所有联系人
7.根据姓名 或 性别或 年龄 或 电话 或 住址 排序所有联系人

二.定义关键类型的头文件与枚举的应用

将存储联系人信息的结构体中各成员数组的大小封装为枚举常量,提高代码的可维护性

PeoIfo是存储联系人信息的结构体

listIfo是含有PeoIfo结构体柔性数组的结构体,通过一个listIfo结构体就可以维护整个通讯录列表,listIfo结构体中的Peonum成员用于维护柔性数组Conlist的高地址边界。

由于测试主程序要用到 switch语句,所以这里把菜单选项对应的数字定义为枚举常量来增强代码的可读性

contact .h
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <memory.h>
#include <errno.h>
#include <stdlib.h>


enum listchoice          /*定义一系列枚举常量 代替宏来表示菜单的选项数字*/
{
	Add = 1,
	Del,
	Search,
	Modify,
	show,
	reset,
	sort,
	Exit = 0
};
enum PeoDataSize         /*定义一系列枚举常量 代替宏来表示各个信息的字节数*/
{
	NameSize = 20,
	SexSize = 20,
	AgeSize = 20,
	TelSize = 20,
	AddrSize = 20,
};


typedef struct PeoIfo    //存储联系人信息的结构体
{
	char Name[NameSize];
	char Sex[SexSize];
	char Age[AgeSize];
	char Tel[TelSize];
	char Addr[AddrSize];
}PeoIfo;


typedef struct listIfo 
{
	int Peonum;          //记录联系人个数
	PeoIfo Conlist[];    //使用柔性数组
}listIfo;

 

在主程序中可以通过这样一段代码创建IistIfo结构体, 初始状态下,柔性数组Conlist的元素个数为0,后续柔性数组的大小可以通过realloc进行调整。

主函数测试模块总览:

​
int main()
{
	listIfo* plist = (listIfo*)malloc(sizeof(listIfo)); //创建柔性数组结构体
	if (NULL == plist)
	{
		perror("malloc:");
		return 1;
	}
	plist->Peonum = 0;
	plist=ReadFile(plist);                              //从文件中读取联系人信息


	int input = 0;
	do
	{
		menu();
		if(scanf("%d", &input));                        //选择执行的功能
		switch (input)                               
		{
		case Add:
			plist=ADD(plist);
			break;
		case Del:
			plist=DEL(plist);
			break;
		case Search:
			PrintNum(Search_byname(plist), plist);
			break;
		case Modify:
			MODIF(plist);
			break;
		case show:
			Show(plist);
			break;
		case reset:
			plist = InitList(plist);
			break;
		case sort:
			bubble_sort(plist->Conlist, plist->Peonum, sizeof(PeoIfo), sort_choice());
			break;
		case Exit:
			Writefile(plist);            //销毁通讯录前先将联系人信息保存到文件中
			free(plist);                 //退出程序销毁结构体
			plist = NULL;
			break;
		default:
			printf(" invalue input,please retry\n");
			break;
		}
	} while (input);

	return 0;
}

​

三.封装柔性数组的增容函数与缩容函数

由于增容和缩容的功能在很多地方都可能会被使用,因此将它们封装成函数是十分有必要的,可以很大程度上提高代码的简洁性和可维护性。

listIfo* IncreSize (listIfo*ListInfo)     //扩容函数
{
	listIfo* tem = (listIfo *)realloc(ListInfo, (sizeof(listIfo) + sizeof(PeoIfo)*(size_t)((ListInfo->Peonum)+1)));
	if (tem == NULL)                      //空间调整失败则返回原指针
	{
		perror("reallocInc:");
		return ListInfo;
	}
	return tem;
}
listIfo* DecreSize(listIfo* ListInfo)     //缩容函数
{
	if (ListInfo->Peonum == 0)
	{
		return ListInfo;
	}
	listIfo* tem = (listIfo*)realloc(ListInfo, (sizeof(listIfo) + sizeof(PeoIfo) * ListInfo->Peonum-1));
	if (tem == NULL)                      //空间调整失败则返回原指针
	{
		perror("reallocInc:");
		return ListInfo;
	}
	return tem;
}

使用realloc函数注意判断空间动态调整是否成功

两个函数都要返回新调整后的空间的地址

四.添加联系人功能模块

listIfo* ADD(listIfo* ListInfo)
{
	ListInfo = IncreSize(ListInfo);       调用增容函数使柔性数组增加一个元素
	memset((ListInfo->Conlist) + (ListInfo->Peonum), 0, sizeof(PeoIfo));
	int ret = 0;
	printf("请输入姓名:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Name);
	printf("请输入性别:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Sex);
	printf("请输入年龄:>");
    ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Age);
	printf("请输入电话:>");
    ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Tel);
	printf("请输入地址:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Addr);
	ListInfo->Peonum++;                   联系人信息填完后记得令人数自增
	printf("ADD success\n");
	return ListInfo;
}

五 .联系人信息打印模块

void Show(listIfo* ListInfo)
{
	int i = 0;
	printf("%-10s  %-4s  %-3s %-10s %-10s \n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < ListInfo->Peonum; i++)
	{
		printf("%-10s  ", ListInfo->Conlist[i].Name);
		printf("%-4s  ", ListInfo->Conlist[i].Sex);
		printf("%-3s  ", ListInfo->Conlist[i].Age);
		printf("%-10s ", ListInfo->Conlist[i].Tel);
		printf("%-10s ", ListInfo->Conlist[i].Addr);
		printf("\n");
	}
}

六. 查找指定联系人的模块

int Search_byname(listIfo* ListIfo)
{
    int i = 0;
    char name[NameSize] = { 0 };
    printf("输入联系人姓名:>");
    int ret=scanf("%s", name);
    for (i = 0; i < ListIfo->Peonum; i++)
    {
        if (strcmp(name, ListIfo->Conlist[i].Name) == 0)
        {
            return i;
        }
    }
    printf("联系人不存在\n");
    return -1;
}

Search_byname函数返回柔性数组对应元素的下标

Search_byname函数同样在很多其他模块可能被调用

打印单个联系人信息的函数

void PrintNum(int i, listIfo* ListIfo)
{
	printf("%-10s  ", ListIfo->Conlist[i].Name);
	printf("%-4s  ", ListIfo->Conlist[i].Sex);
	printf("%-3s  ", ListIfo->Conlist[i].Age);
	printf("%-10s ", ListIfo->Conlist[i].Tel);
	printf("%-10s ", ListIfo->Conlist[i].Addr);
	printf("\n");
}

Search_byname 和 PrintNum函数一起使用可以完成查找指定联系人信息的功能

七.删除指定联系人模块

listIfo* DEL(listIfo* ListIfo)
{
	int ret = Search_byname(ListIfo);
	if (ret != -1)
	{
		memmove((ListIfo->Conlist) + ret, (ListIfo->Conlist) + ret + 1,
			sizeof(PeoIfo) * (long long)((ListIfo->Peonum) - ret - 1));
		
		ListIfo = DecreSize(ListIfo);   //调用缩容函数
		ListIfo->Peonum--;
		printf("DELATE success\n");
	}
	return ListIfo;
}

八.修改指定联系人信息模块

void MODIF(listIfo* ListIfo)
{
	int ret = Search_byname(ListIfo);     调用查找函数
	if (ret != -1)
	{
		printf("请输入姓名:>");
		int i=scanf("%s", (ListIfo->Conlist[ret]).Name);
		printf("请输入性别:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Sex);
		printf("请输入年龄:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Age);
		printf("请输入电话:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Tel);
		printf("请输入地址:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Addr);
		printf("modify success\n");
	}
}

九.排序模块

排序模块函数比较多,因此单独为其创建了一个源文件。 

这里我们使用模拟qsort的冒泡排序函数来实现通讯录排序功能。

首先是一系列比较函数:

int cmpbyname(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Name, ((PeoIfo*)e2)->Name);
}
int cmpbysex(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Sex, ((PeoIfo*)e2)->Sex);
}
int cmpbyage(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Age, ((PeoIfo*)e2)->Age);
}
int cmpbytel(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Tel, ((PeoIfo*)e2)->Tel);
}
int cmpbyaddr(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Addr, ((PeoIfo*)e2)->Addr);
}

然后设计一个函数可以让用户自行选择根据何种信息排序,该函数的返回值是一个函数指针类型为:int (*)(void * , void *),为了代码的简洁性,我们使用函数指针数组构建转移表

#define ChoiceNum 5
static void sortmenu(void)
{
	printf("***********************************\n");
	printf("*****       1.sort by name     ****\n");
	printf("*****       2.sort by sex      ****\n");
	printf("*****       3.sort by Age      ****\n");
	printf("*****       4.sort by Tel      ****\n");
	printf("*****       5.sort by addr     ****\n");
	printf("***********************************\n");
}
int (*sort_choice(void))(void*, void*)
{
	int input = 0;
	int (*Funarr[ChoiceNum])(void*, void*) = { cmpbyname,
                                               cmpbysex,
                                               cmpbyage,
                                               cmpbytel,
                                               cmpbyaddr };  转移表
	
    sortmenu();
	int ret = scanf("%d", &input);
	while (input<0 || input >ChoiceNum - 1)
	{
		printf("invalued input,please retry\n");
		sortmenu();
	}
	return *(Funarr+input - 1);                返回对应的比较函数
}

多功能bubble_sort模块

static void swap(void* e1, void* e2,int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tem = *((char*)e1 + i);
		*((char*)e1 + i) = *((char*)e2 + i);
		*((char*)e2 + i) = tem;
	}
}

void* bubble_sort(void* base, long long num, int width, int(*cmp)(void*, void*))
{
	int i = 0;
	long long j = 0;
	int flag = 0;
	for (i = 0; i < num-1; i++)
	{
		flag = 1;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				flag = 0;
				swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
			}
		}
		if (flag)
		{
			break;
		}
	}
	printf("sorted success\n");
	return base;
}

在主函数中以如下形式调用bubble_sort便可完成根据任意联系人信息进行排序的功能

bubble_sort(plist->Conlist, plist->Peonum, sizeof(PeoIfo), sort_choice());

九.文件操作模块

运行程序并创建了含柔性数组成员的结构体后,需要将文件中的联系人信息读入柔性数组中。我们采用二进制读写来完成通讯录的文件操作。

文件读取模块:

listIfo* ReadFile(listIfo* ListIfo)
{
	FILE* pfile = fopen("text.txt", "rb");     打开文件并检验是否发生错误
	if (NULL == pfile) 
	{
		perror("fopen:");
		return ListIfo;
	}

	ListIfo = IncreSize(ListIfo);              读取文件前先为0个元素的柔性数组增容
	while (fread(((ListIfo->Conlist) + (ListIfo->Peonum)), sizeof(PeoIfo), 1, pfile))
	{
		ListIfo->Peonum++;
		ListIfo = IncreSize(ListIfo);          每读取一个联系人增容一次
	}
	if (ferror(pfile))                         检验读取是否成功
	{
		printf("reading error occurred\n");
	}
	else if (feof(pfile))
	{
		printf("readfile success\n");
	}
	fclose(pfile);
	pfile = NULL;
	return ListIfo;                            关闭文件并 返回调整后的柔性数组结构体的地址
}

 

程序结束前需要将柔性数组中存储的信息以二进制数据的形式写入文件中。

文件写入模块:

void Writefile(listIfo* ListIfo)
{
	FILE* pfile = fopen("text.txt", "wb");
	if (NULL == pfile)
	{
		perror("fopen:");
		return ;
	}
	int i = 0;
	for (i = 0; i < ListIfo->Peonum; i++)      将每个联系人信息写入文件中
	{
		if (!fwrite(((ListIfo->Conlist) + i), sizeof(PeoIfo), 1, pfile))
		{
			perror("fwrite:");
			return;
		}
	}
	printf("contact successfully saved\n");
	fclose(pfile);
	pfile = NULL;
	return;
}

十.通讯录初始化模块

listIfo * InitList(listIfo* ListIfo)
{
	listIfo* tem = NULL;
	tem = (listIfo*)realloc(ListIfo, sizeof(listIfo)); 将柔性数组调整为0个元素
	if (tem == NULL)
	{
		perror("realloc and init failed:");
		return ListIfo;
	}
	tem->Peonum = 0;
	printf("Init success\n");
	return tem;
}

十一.代码总览

contact.h头文件

#pragma once
//contact .h
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <memory.h>
#include <errno.h>
#include <stdlib.h>


enum listchoice          /*定义一系列枚举常量 代替宏来表示菜单的选项数字*/
{
	Add = 1,
	Del,
	Search,
	Modify,
	show,
	reset,
	sort,
	Exit = 0
};
enum PeoDataSize         /*定义一系列枚举常量 代替宏来表示各个信息的字节数*/
{
	NameSize = 20,
	SexSize = 20,
	AgeSize = 20,
	TelSize = 20,
	AddrSize = 20,
};


typedef struct PeoIfo    //存储联系人信息的结构体
{
	char Name[NameSize];
	char Sex[SexSize];
	char Age[AgeSize];
	char Tel[TelSize];
	char Addr[AddrSize];
}PeoIfo;


typedef struct listIfo 
{
	int Peonum;          //存储的联系人数
	PeoIfo Conlist[];    //使用柔性数组
}listIfo;

contactfunction.h头文件

#include "contact.h"
#pragma once
void menu(void);
listIfo* ADD(listIfo* ListInfo);
void Show(listIfo* ListIfo);
listIfo* InitList(listIfo* ListIfo);
int Search_byname(listIfo* ListIfo);
void PrintNum(int i, listIfo* ListIfo);
listIfo* DEL(listIfo* ListIfo);
void MODIF(listIfo* ListIfo);
void* bubble_sort(void* base, long long num, int width, int(*cmp)(void*, void*));
listIfo* DecreSize(listIfo* ListInfo);
listIfo* IncreSize(listIfo* ListInfo);
int (*sort_choice(void))(void*, void*);
listIfo* ReadFile(listIfo* ListIfo);
void Writefile(listIfo* ListIfo);

通讯录基本功能模块源文件 

#include  "contact.h"
#include  "contactfunction.h"

//封装菜单函数
void menu(void)
{
	printf("*********************************\n");
	printf("******   1.Add contact      *****\n");
	printf("******                      *****\n");
	printf("******   2.del contact      *****\n");
	printf("******                      *****\n");
	printf("******   3.search contact   *****\n");
	printf("******                      *****\n");
	printf("******   4.modify contact   *****\n");
	printf("******                      *****\n");
	printf("******   5.show list        *****\n");
	printf("******                      *****\n");
	printf("******   6.reset list       *****\n");
	printf("******                      *****\n");
	printf("******   7.sort             *****\n");
	printf("******                      *****\n");
	printf("******   0.exit             *****\n");
	printf("*********************************\n");
	printf("---------please choose-----------\n");
}

listIfo* IncreSize (listIfo*ListInfo)     //扩容函数
{
	listIfo* tem = (listIfo *)realloc(ListInfo, (sizeof(listIfo) + sizeof(PeoIfo)*(size_t)((ListInfo->Peonum)+1)));
	if (tem == NULL)                      //空间调整失败则返回原指针
	{
		perror("reallocInc:");
		return ListInfo;
	}
	return tem;
}
listIfo* DecreSize(listIfo* ListInfo)     //缩容函数
{
	if (ListInfo->Peonum == 0)
	{
		return ListInfo;
	}
	listIfo* tem = (listIfo*)realloc(ListInfo, (sizeof(listIfo) + sizeof(PeoIfo) * ListInfo->Peonum-1));
	if (tem == NULL)                      //空间调整失败则返回原指针
	{
		perror("reallocInc:");
		return ListInfo;
	}
	return tem;
}
//void InitListNUM(listIfo* ListIfo)
//{
//	memset((ListIfo->Conlist)+(ListIfo->Peonum), 0, sizeof(PeoIfo));
//	memset(ListIfo->Conlist[ListIfo->Peonum].Sex, 0, SexSize);
//	memset(ListIfo->Conlist[ListIfo->Peonum].Age, 0, AgeSize);
//	memset(ListIfo->Conlist[ListIfo->Peonum].Tel, 0, TelSize);
//	memset(ListIfo->Conlist[ListIfo->Peonum].Addr, 0, AddrSize);
//}


listIfo* ADD(listIfo* ListInfo)
{
	ListInfo = IncreSize(ListInfo);
	memset((ListInfo->Conlist) + (ListInfo->Peonum), 0, sizeof(PeoIfo));
	int ret = 0;
	printf("请输入姓名:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Name);
	printf("请输入性别:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Sex);
	printf("请输入年龄:>");
    ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Age);
	printf("请输入电话:>");
    ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Tel);
	printf("请输入地址:>");
	ret = scanf("%s", (ListInfo->Conlist[ListInfo->Peonum]).Addr);
	ListInfo->Peonum++;
	printf("ADD success\n");
	return ListInfo;
}
listIfo * InitList(listIfo* ListIfo)
{
	listIfo* tem = NULL;
	tem = (listIfo*)realloc(ListIfo, sizeof(listIfo));
	if (tem == NULL)
	{
		perror("realloc and init failed:");
		return ListIfo;
	}
	tem->Peonum = 0;
	printf("Init success\n");
	return tem;
}

void Show(listIfo* ListInfo)
{
	int i = 0;
	printf("%-10s  %-4s  %-3s %-10s %-10s \n", "姓名", "性别", "年龄", "电话", "地址");
	for (i = 0; i < ListInfo->Peonum; i++)
	{
		printf("%-10s  ", ListInfo->Conlist[i].Name);
		printf("%-4s  ", ListInfo->Conlist[i].Sex);
		printf("%-3s  ", ListInfo->Conlist[i].Age);
		printf("%-10s ", ListInfo->Conlist[i].Tel);
		printf("%-10s ", ListInfo->Conlist[i].Addr);
		printf("\n");
	}
}



int Search_byname(listIfo* ListIfo)
{
	int i = 0;
	char name[NameSize] = { 0 };
	printf("输入联系人姓名:>");
	int ret=scanf("%s", name);
	for (i = 0; i < ListIfo->Peonum; i++)
	{
		if (strcmp(name, ListIfo->Conlist[i].Name) == 0)
		{
			return i;
		}
	}
	printf("联系人不存在\n");
	return -1;
}

void PrintNum(int i, listIfo* ListIfo)
{
	printf("%-10s  ", ListIfo->Conlist[i].Name);
	printf("%-4s  ", ListIfo->Conlist[i].Sex);
	printf("%-3s  ", ListIfo->Conlist[i].Age);
	printf("%-10s ", ListIfo->Conlist[i].Tel);
	printf("%-10s ", ListIfo->Conlist[i].Addr);
	printf("\n");
}

listIfo* DEL(listIfo* ListIfo)
{
	int ret = Search_byname(ListIfo);
	if (ret != -1)
	{
		memmove((ListIfo->Conlist) + ret, (ListIfo->Conlist) + ret + 1,
			sizeof(PeoIfo) * (long long)((ListIfo->Peonum) - ret - 1));
		
		ListIfo = DecreSize(ListIfo);   //调用缩容函数
		ListIfo->Peonum--;
		printf("DELATE success\n");
	}
	return ListIfo;
}


void MODIF(listIfo* ListIfo)
{
	int ret = Search_byname(ListIfo);
	if (ret != -1)
	{
		printf("请输入姓名:>");
		int i=scanf("%s", (ListIfo->Conlist[ret]).Name);
		printf("请输入性别:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Sex);
		printf("请输入年龄:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Age);
		printf("请输入电话:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Tel);
		printf("请输入地址:>");
		i = scanf("%s", (ListIfo->Conlist[ret]).Addr);
		printf("modify success\n");
	}
}

文件操作模块源文件

#include "contactfunction.h"
#include "contact.h"

//文件的读写我们采用二进制读写

listIfo* ReadFile(listIfo* ListIfo)
{
	FILE* pfile = fopen("text.txt", "rb");
	if (NULL == pfile)
	{
		perror("fopen:");
		return ListIfo;
	}

	ListIfo = IncreSize(ListIfo);
	while (fread(((ListIfo->Conlist) + (ListIfo->Peonum)), sizeof(PeoIfo), 1, pfile))
	{
		ListIfo->Peonum++;
		ListIfo = IncreSize(ListIfo);
	}
	if (ferror(pfile))
	{
		printf("reading error occurred\n");
	}
	else if (feof(pfile))
	{
		printf("readfile success\n");
	}
	fclose(pfile);
	pfile = NULL;
	return ListIfo;
}

void Writefile(listIfo* ListIfo)
{
	FILE* pfile = fopen("text.txt", "wb");
	if (NULL == pfile)
	{
		perror("fopen:");
		return ;
	}
	int i = 0;
	for (i = 0; i < ListIfo->Peonum; i++)
	{
		if (!fwrite(((ListIfo->Conlist) + i), sizeof(PeoIfo), 1, pfile))
		{
			perror("fwrite:");
			return;
		}
	}
	printf("contact successfully saved\n");
	fclose(pfile);
	pfile = NULL;
	return;
}

排序模块源文件: 

#include "contact.h"
#include "contactfunction.h"
#define ChoiceNum 5


static void sortmenu(void)
{
	printf("***********************************\n");
	printf("*****       1.sort by name     ****\n");
	printf("*****       2.sort by sex      ****\n");
	printf("*****       3.sort by Age      ****\n");
	printf("*****       4.sort by Tel      ****\n");
	printf("*****       5.sort by addr     ****\n");
	printf("***********************************\n");
}


int cmpbyname(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Name, ((PeoIfo*)e2)->Name);
}
int cmpbysex(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Sex, ((PeoIfo*)e2)->Sex);
}
int cmpbyage(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Age, ((PeoIfo*)e2)->Age);
}
int cmpbytel(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Tel, ((PeoIfo*)e2)->Tel);
}
int cmpbyaddr(void* e1, void* e2)
{
	return strcmp(((PeoIfo*)e1)->Addr, ((PeoIfo*)e2)->Addr);
}


int (*sort_choice(void))(void*, void*)
{
	int input = 0;
	int (*Funarr[ChoiceNum])(void*, void*) = { cmpbyname ,cmpbysex,cmpbyage,cmpbytel,cmpbyaddr };
	sortmenu();
	int ret = scanf("%d", &input);
	while (input<0 || input >ChoiceNum - 1)
	{
		printf("invalued input,please retry\n");
		sortmenu();
	}
	return *(Funarr+input - 1);
}


static void swap(void* e1, void* e2,int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tem = *((char*)e1 + i);
		*((char*)e1 + i) = *((char*)e2 + i);
		*((char*)e2 + i) = tem;
	}
}

void* bubble_sort(void* base, long long num, int width, int(*cmp)(void*, void*))
{
	int i = 0;
	long long j = 0;
	int flag = 0;
	for (i = 0; i < num-1; i++)
	{
		flag = 1;
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				flag = 0;
				swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
			}
		}
		if (flag)
		{
			break;
		}
	}
	printf("sorted success\n");
	return base;
}

主函数测试模块源文件: 

#include "contact.h"
#include "contactfunction.h"


int main()
{
	listIfo* plist = (listIfo*)malloc(sizeof(listIfo)); //创建柔性数组结构体
	if (NULL == plist)
	{
		perror("malloc:");
		return 1;
	}
	plist->Peonum = 0;
	plist=ReadFile(plist);


	int input = 0;
	do
	{
		menu();
		if(scanf("%d", &input));
		switch (input)
		{
		case Add:
			plist=ADD(plist);
			break;
		case Del:
			plist=DEL(plist);
			break;
		case Search:
			PrintNum(Search_byname(plist), plist);
			break;
		case Modify:
			MODIF(plist);
			break;
		case show:
			Show(plist);
			break;
		case reset:
			plist = InitList(plist);
			break;
		case sort:
			bubble_sort(plist->Conlist, plist->Peonum, sizeof(PeoIfo), sort_choice());
			break;
		case Exit:
			Writefile(plist);
			free(plist);                 //退出程序销毁结构体
			plist = NULL;
			break;
		default:
			printf(" invalue input,please retry\n");
			break;
		}
	} while (input);

	return 0;
}

 

 

 

 

 

相关文章:

  • 十三.动态内存管理
  • 【8】SCI易中期刊推荐——图像处理领域(中科院4区)
  • 计算机视觉未来发展与走向
  • 【每日一道智力题】之猴子搬香蕉
  • 集成学习、Bagging集成原理、随机森林构造过程、随机森林api与案例、boosting集成原理、梯度提升决策树(GBDT)、XGBoost与泰勒展开式
  • 第一层:封装
  • 【BP靶场portswigger-客户端14】点击劫持-5个实验(全)
  • 【PaaS】分享一家最近发现的宝藏Paas厂家
  • C语言—基于realloc函数实现的通讯录
  • 【云原生】k8s 一键部署(ansible)
  • Java使用Zxing二维码生成
  • C++程序卡死、UI界面卡顿问题的原因分析与总结
  • 【C语言进阶】使用“动态内存文件处理”实现进阶版通讯录
  • 我们怎样才能过好这一生?
  • C 语言目标文件
  • [NodeJS] 关于Buffer
  • 11111111
  • Android 控件背景颜色处理
  • ERLANG 网工修炼笔记 ---- UDP
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • js操作时间(持续更新)
  • linux安装openssl、swoole等扩展的具体步骤
  • Python爬虫--- 1.3 BS4库的解析器
  • scala基础语法(二)
  • scrapy学习之路4(itemloder的使用)
  • SegmentFault 2015 Top Rank
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • SSH 免密登录
  • TCP拥塞控制
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Yeoman_Bower_Grunt
  • 对超线程几个不同角度的解释
  • 构建工具 - 收藏集 - 掘金
  • 关于 Cirru Editor 存储格式
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 简析gRPC client 连接管理
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 实战|智能家居行业移动应用性能分析
  • 我感觉这是史上最牛的防sql注入方法类
  • 延迟脚本的方式
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​ArcGIS Pro 如何批量删除字段
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • $L^p$ 调和函数恒为零
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (ZT)出版业改革:该死的死,该生的生
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (黑马C++)L06 重载与继承
  • (顺序)容器的好伴侣 --- 容器适配器
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)