• 【C版本】静态通讯录与动态通讯录的实现,以及各自所存在的缺陷对比。(含所有原码)


    通讯录


    静态版本通讯录

    前期思路

    与之前的扫雷以及三子棋的实现方式是一样的,创建两个源文件,一个用来测试,一个用来存放函数定义,再创建一个头文件,用来存放函数声明。接下来是着手实现通讯录。
    首先要有一个大概的框架,并且要明确即将实现的通讯录的功能,最基本的即增删查改,然后对这些功能进行进一步的细化实现,并且我们知道,人的信息是一个比较复杂的对象,不可能用一句话就概括,所以就用到了之前学过的结构体,一个结构体用来存放联系人,另一个用来存放联系人对应的的基本信息。
    最后我们要知道一点,就是一口吃不成一个大胖子,功能实现的过程是一步步来的。

    在这里插入图片描述

    具体实现

    1、框架

    首先创建一个用来存放联系人以及记录联系人个数的结构体,然后把联系人的信息也存放在这个结构体中,如下:

    //联系人信息
    struct message
    {
    	//姓名
    	char name[NAME];
    	//性别
    	char sex[SEX];
    	//电话
    	char tele[TELE];
    	//住址
    	char addr[ADDR];
    	//年龄
    	int age;
    };
    //通讯录
    struct contact
    {
    	//存放联系人的数组,数组里存放的元素类型是结构体类型,即存放联系人的信息。
    	struct message data[MAX];
    	//记录联系人的个数
    	int sz;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这里我们可以用define来定义一个常量,这样后续修改起来也比较容易,不要把程序写死。

    #define NAME 20//姓名
    #define SEX 5//性别
    #define TELE 12//电话
    #define ADDR 30//住址
    #define MAX 100//联系人最大个数
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后在.c的测试文件里书写菜单栏。

    (个人建议:像这种,不算是特别复杂的对象,就可以提前制定一个框架,也就是菜单栏,但是后面学到数据结构的时候,建议最后再添加,因为菜单栏的存在,会使一些调试比较麻烦。)

    一个基本的框架,满足上面提到的一些功能,实现起来也比较容易,用一个简单的do while即可,如下:

    #include"contact_.h"
    //菜单栏
    void menu()
    {
    	printf("--------------------------------------------------------------\n");
    	printf("---------   1、增加联系人       2、删除指定联系人    ---------\n");
    	printf("---------   3、修改联系人信息   4、查找联系人        ---------\n");
    	printf("---------   5、排序联系人       6、显示已有联系人    ---------\n");
    	printf("---------   0、退出             7、清空联系人        ---------\n");
    	printf("--------------------------------------------------------------\n");
    }
    
    int main()
    {
    	int input = 0;
    	//创建通讯录
    	struct contact con;
    	//初始化通讯录
    	Init_contact(&con);
    	do
    	{
    		menu();
    		printf("请选择:->");
    		scanf("%d", &input);
    		system("cls");
    		switch (input)
    		{
    		case 1:
    			//增加联系人
    			Add_contact(&con);
    			break;
    		case 2:
    			//删除联系人
    			Show_contact(&con);
    			Dele_contact(&con);
    			break;
    		case 3:
    			//修改联系人信息
    			Show_contact(&con);
    			revise_contact(&con);
    			break;
    		case 4:
    			//查找联系人信息
    			Find_contact(&con);
    			break;
    		case 5:
    			//排序联系人信息
    			Show_contact(&con);
    			Sort_contact(&con);
    			break;
    		case 6:
    			//显示联系人
    			system("cls");
    			Show_contact(&con);
    			printf("\n");
    			break;
    		case 7:
    			//清空联系人
    			Clear(&con);
    			break;
    		case 0:
    			break;
    		default:
    			printf("输入错误!\n");
    			break;
    		}
    
    	} while (input);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    2、初始化通讯录

    扫雷游戏一样,首先先把通讯录初始化,然后再存放信息。实现起来也很简单。

    //初始化通讯录
    void Init_contact(struct contact* p)
    {
    	assert(p);
    	p->sz = 0;//sz是记录联系人个数的变量
    	memset(p->data, 0, MAX * sizeof(struct message));
    	//p指向的data数组(存放联系人的)里,把MAX个联系人信息都置为0
    	//memset是一个内存函数,修改存储在内存的数据
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、增加联系人

    增加一个联系人,即增加姓名、性别、电话等信息,把这些信息输入在结构体数组中对应得结构体成员即可,如下:

    //增加联系人
    void Add_contact(struct contact* p)
    {
    	assert(p);
    	if (p->sz == MAX)
    		printf("联系人已满!!!\n");
    	printf("请输入姓名:->");
    	scanf("%s", p->data[p->sz].name);
    	printf("请输入性别:->");
    	scanf("%s", p->data[p->sz].sex);
    	printf("请输入电话:->");
    	scanf("%s", p->data[p->sz].tele);
    	printf("请输入住址:->");
    	scanf("%s", p->data[p->sz].addr);
    	printf("请输入年龄:->");
    	scanf("%d", &(p->data[p->sz].age));
    	system("cls");
    	//清屏
    	printf("增加成功!\n");
    	printf("\n");
    	p->sz++;//每增加一个,sz也跟着++
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    说白了这块知识点就是结构体成员的访问,只不过这里访问了两次

    4、显示已有联系人

    //显示联系人
    void Show_contact(const struct contact* p)
    {
    	assert(p);
    	int i = 0;
    	//为了显示出来更加有美感,先打印一行基本信息
    	printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5s\n", "姓名", "性别", "电话", "住址", "年龄");
    	//循环打印即可,sz记录目前联系人个数
    	for (i = 0; i < p->sz; i++)
    	{
    	     // 一一对应即可
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5d\n", p->data[i].name,
    			p->data[i].sex,
    			p->data[i].tele,
    			p->data[i].addr,
    			p->data[i].age);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    实现完成如下;
    在这里插入图片描述

    5、查找联系人

    查找联系人的实现也很简单,定义一个函数,遍历整个data数组,如果不存在返回-1,打印不存在,存在就返回1,打印该联系人信息。如下:

    //这里遍历整个数组,如果不存在,则返回-1,存在返回1
    int find_name(const struct contact* p, char arr[])
    {
    	assert(p);
    	int i = 0;
    	for (i = 0; i < p->sz; i++)
    	{
    		if (0 == strcmp(p->data[i].name, arr))
    			return i;
    	}
    	return -1;
    }
    //查找联系人信息
    void Find_contact(const struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要查找联系人的姓名:->");
    	scanf("%s", del_name);
    	system("cls");
    
    	//查找该联系人
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    		printf("查无此人!\n");
    	//返回值为1,打印出该联系人信息即可
    	else
    	{
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5s\n", "姓名", "性别", "电话", "住址", "年龄");
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5d\n", p->data[ret].name,
    			p->data[ret].sex,
    			p->data[ret].tele,
    			p->data[ret].addr,
    			p->data[ret].age);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    6、删除指定联系人

    实现删除的功能也很简单,由于数组在内存中是连续存放的,只需要后面的覆盖即可,原理如下:
    在这里插入图片描述
    具体用代码实现如下:

    //删除联系人
    void Dele_contact(struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要删除联系人的姓名:->");
    	scanf("%s", del_name);
    	//查找该联系人
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    		printf("查无此人!\n");
    	else
    	{
    		int j = 0;
    		for (j = ret; j < p->sz - 1; j++)
    		{
    			p->data[j] = p->data[j + 1];//后面的覆盖前面的
    		}
    		p->sz--;
    		system("cls");
    
    		printf("删除成功!\n");
    		printf("\n");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    7、排序联系人

    这里我又新增了一步,就是可以实现按姓名、住址、年龄、性别排序,用qsort即可实现,不懂的可以去翻看我前面的指针进阶文章,里面有介绍。具体实现如下:

    //排序菜单
    void menu_sort()
    {
    	printf("******   1、姓名   ******\n");
    	printf("******   2、住址   ******\n");
    	printf("******   3、年龄   ******\n");
    	printf("******   4、性别   ******\n");
    	printf("******   0、退出   ******\n");
    }
    
    //姓名排序
    int cmp_name(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->name, ((struct message*)e2)->name);
    }
    //住址排序
    int cmp_addr(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->addr, ((struct message*)e2)->addr);
    }
    //年龄排序
    int cmp_age(const void* e1, const void* e2)
    {
    	return ((struct message*)e1)->age - ((struct message*)e2)->age;
    }
    //性别排序
    int cmp_sex(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->sex, ((struct message*)e2)->sex);
    }
    //排序联系人
    void Sort_contact(struct contact* p)
    {
    	int s = 0;
    	do
    	{
    		//排序菜单
    		menu_sort();
    		printf("请选择排序类型:->");
    		scanf("%d", &s);
    		system("cls");
    		switch (s)
    		{
    		case 1:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_name);
    			printf("排序成功!\n");
    			break;
    		case 2:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_addr);
    			printf("排序成功!\n");
    			break;
    		case 3:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_age);
    			printf("排序成功!\n");
    			break;
    		case 4:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_sex);
    			printf("排序成功!\n");
    			break;
    		case 0:
    			printf("退出排序\n");
    			break;
    		default:
    			printf("输入有误!\n");
    			break;
    		}
    
    	} while (s);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    8、修改联系人信息

    修改联系人信息,首先找到这个联系人,然后再进行修改,这里我是可以把信息有选择性的修改,实现起来也很简单

    //修改菜单栏
    void menu_()
    {
    	printf("***********************************\n");
    	printf("******   1、修改联系人姓名   ******\n");
    	printf("******   2、修改联系人电话   ******\n");
    	printf("******   3、修改联系人年龄   ******\n");
    	printf("******   4、修改联系人住址   ******\n");
    	printf("******   5、修改联系人性别   ******\n");
    	printf("******   0、返回主菜单       ******\n");
    
    }
    //修改联系人信息
    void revise_contact(struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要修改信息的联系人的姓名:->");
    	scanf("%s", del_name);
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    	{
    		printf("查无此人!\n");
    		printf("\n");
    	}
    	else
    	{
    		int in_put = 0;
    		do
    		{
    			menu_();
    			scanf("%d", &in_put);
    			switch (in_put)
    			{
    			case 1:
    				printf("请输入修改后的姓名:->");
    				scanf("%s", p->data[ret].name);
    				system("cls");
    
    				printf("姓名修改成功!\n");
    				break;
    			case 2:
    				printf("请输入修改后的电话:->");
    				scanf("%s", p->data[ret].tele);
    				system("cls");
    
    				printf("电话修改成功!\n");
    				break;
    			case 3:
    				printf("请输入修改后的年龄:->");
    				scanf("%d", &(p->data[ret].age));
    				system("cls");
    
    				printf("年龄修改成功!\n");
    				break;
    			case 4:
    				printf("请输入修改后的住址:->");
    				scanf("%s", p->data[ret].addr);
    				system("cls");
    
    				printf("住址修改成功!\n");
    				break;
    			case 5:
    				printf("请输入修改后的性别:->");
    				scanf("%s", p->data[ret].sex);
    				system("cls");
    
    				printf("性别修改成功!\n");
    				break;
    			case 0:
    				printf("取消修改!\n");
    				break;
    			default:
    				printf("输入错误!\n");
    				break;
    			}
    		} while (in_put);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    9、清空联系人

    这一步是最容易实现的一步,只需要置空sz即可,到这里也算是苦尽甘来。

    //清空联系人
    void Clear(struct contact* p)
    {
    	p->sz = 0;
    	printf("清空成功!\n");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    至此。一个功能齐全的通讯录实现完毕。

    静态版本通讯录存在的缺陷

    我们看到,上面的版本我们定义了数组大小为100,也就是能存放100人的信息,data空间是已经开辟了的,假如我们要存放第101个人的信息呢?这不就存不下了,有的铁子可能说,那我们可以定义为1000呀,你总不能有这么多联系人用来存放吧。
    确实如此,但是后面的空间不就浪费了。那有什么办法可以实现按照我们的需求来开辟合适的空间呢?答案是有的,就是后面的动态内存版本。


    动态版本通讯录(静态版本的部分功能发生改动)

    动态版本的通讯录是在静态版本上进行的一次优化,即实现按照需求开辟空间。和之前版本有所不同,不用一个结构体数组来存放联系人,而是用了一个结构体指针。如下:

    #define NAME 20
    #define SEX 5
    #define TELE 12
    #define ADDR 30
    
    #define DEFAULT_SZ 3//初始容量
    #define INC_SZ 2//扩容
    //联系人信息
    struct message
    {
    	//姓名
    	char name[NAME];
    	//性别
    	char sex[SEX];
    	//电话
    	char tele[TELE];
    	//住址
    	char addr[ADDR];
    	//年龄
    	int age;
    };
    //通讯录
    struct contact
    {
    	struct message* data;//结构体指针
    	int sz;//个数
    	int capacity;//通讯录容量
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    由于是动态版本的,所以在初始化、增加联系人、以及最后的退出里,有了一定的修改,别的只要不涉及增加空间的操作,都与静态版本相同。这里就不一一再写了。

    初始化

    //初始化通讯录
    void Init_contact(struct contact* p)
    {
    	assert(p);
    	//开辟空间
    	p->data =(struct message*) malloc(DEFAULT_SZ * sizeof(struct message));
    	//假如开辟失败,报错
    	if (p->data == NULL)
    	{
    		printf("%s\n", strerror(errno));
    		return;
    	}
    	p->sz = 0;
    	p->capacity = DEFAULT_SZ;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里的capacity是当前通讯录的容量,sz是记录当前联系人的数量,当数量==容量时,就要进行扩容。
    所以这里又增加了一个用来判断是否扩容的函数,这个函数算是动态版本通讯录的核心函数了

    //是否判断增容
    int check_capacity(struct contact*p)
    {
    	//当联系人个数 == 通讯录容量时,增容INC_SZ个内存空间
    	if (p->sz == p->capacity)
    	{
    		struct message* ptr = (struct message*)realloc(p->data, (p->capacity + INC_SZ) * sizeof(struct message));
    		if (ptr == NULL)//判断是否增容失败
    		{
    			printf("%s\n", strerror(errno));
    			return 0;
    		}
    		else
    		{
    			p->data = ptr;//增容成功,data就指向这块新开辟的空间
    			p->capacity += INC_SZ;//容量+=INC_SZ
    			//printf("增容成功!\n");
    			return 1;
    		}
    	}
    	//不需要增容
    	else
    		return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    增加联系人

    这里的增加联系人,就要在增加之前进行判断,空间是否需要扩容,如下:
    check_capacity时上面写的用来判断知否增容的函数。

    //增加联系人
    void Add_contact(struct contact* p)
    {
    	assert(p);
    	if (0 == check_capacity(p))
    	{
    		printf("%s\n", strerror(errno));
    		return;
    	}
    	printf("请输入姓名:->");
    	scanf("%s", p->data[p->sz].name);
    
    	printf("请输入性别:->");
    	scanf("%s", p->data[p->sz].sex);
    
    	printf("请输入电话:->");
    	scanf("%s", p->data[p->sz].tele);
    
    	printf("请输入住址:->");
    	scanf("%s", p->data[p->sz].addr);
    
    	printf("请输入年龄:->");
    	scanf("%d", &(p->data[p->sz].age));
    	system("cls");
    
    	printf("增加成功!\n");
    	printf("\n");
    	p->sz++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    退出程序(释放空间)

    malloc这些动态内存管理函数,都是与free成对出现的,这里的释放空间就是需要在程序退出的时候,进行释放,否则造成内存泄漏问题。这里free后置空即可。

    //释放空间
    void Destory_contact(struct contact* p)
    {
    	free(p->data);
    	p->data=NULL;
    	p->sz = 0;
    	p->capacity = 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    至此,动态版本通讯录实现完毕,就是在静态版本的基础上进行了修改,主要涉及到了增容问题,处理好即可。

    动态版本通讯录存在的缺陷

    唯一的缺陷就在于不能把信息保存下来,也就是说,当下次打开程序的时候,上一次写的都没了,也就是说,这是一个“一次性”的通讯录。当然,后面还会有进一步的改动,实现真正意义上的通讯录,即可以把每次的信息保存下来,后续会书写。

    动态通讯录原码

    头文件

    #pragma once
    #include
    #include
    #include
    #include
    #include
    #include
    
    #define NAME 20
    #define SEX 5
    #define TELE 12
    #define ADDR 30
    
    #define DEFAULT_SZ 3//初始容量
    #define INC_SZ 2//扩容
    
    //联系人信息
    struct message
    {
    	//姓名
    	char name[NAME];
    	//性别
    	char sex[SEX];
    	//电话
    	char tele[TELE];
    	//住址
    	char addr[ADDR];
    	//年龄
    	int age;
    };
    //通讯录
    struct contact
    {
    	struct message* data;
    	int sz;//个数
    	int capacity;//通讯录容量
    };
    //初始化通讯录
    void Init_contact(struct contact* p);
    //动态增加联系人
    void Add_contact(struct contact* p);
    //显示联系人
    void Show_contact(const struct contact* p);
    //删除联系人
    void Dele_contact(struct contact* p);
    //修改联系人信息
    void revise_contact(struct contact* p);
    //查找联系人信息
    void Find_contact(const struct contact* p);
    //排序联系人
    void Sort_contact(struct contact* p);
    //清空联系人
    void Clean(struct contact* p);
    //释放空间
    void Destory_contact(struct contact* p);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    .c测试源文件

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"contact_dynamic.h"
    
    void menu()
    {
    	printf("--------------------------------------------------------------\n");
    	printf("---------   1、增加联系人       2、删除指定联系人    ---------\n");
    	printf("---------   3、修改联系人信息   4、查找联系人        ---------\n");
    	printf("---------   5、排序联系人       6、显示已有联系人    ---------\n");
    	printf("---------   0、退出             7、清空联系人        ---------\n");
    	printf("--------------------------------------------------------------\n");
    }
    
    int main()
    {
    	int input = 0;
    	//创建通讯录
    	struct contact con;
    	//初始化通讯录
    	Init_contact(&con);
    	do
    	{
    		menu();
    		printf("请选择:->");
    		scanf("%d", &input);
    		system("cls");
    		switch (input)
    		{
    		case 1:
    			//增加联系人
    			Add_contact(&con);
    			break;
    		case 2:
    			//删除联系人
    			Show_contact(&con);
    			Dele_contact(&con);
    			break;
    		case 3:
    			//修改联系人信息
    			Show_contact(&con);
    			revise_contact(&con);
    			break;
    		case 4:
    			//查找联系人信息
    			Find_contact(&con);
    			break;
    		case 5:
    			//排序联系人信息
    			Show_contact(&con);
    			Sort_contact(&con);
    			break;
    		case 6:
    			//显示联系人
    			system("cls");
    			Show_contact(&con);
    			printf("\n");
    			break;
    		case 7:
    			//清空联系人
    			Clean(&con);
    			break;
    		case 0:
    			//释放空间
    			Destory_contact(&con);
    			break;
    		default:
    			printf("输入错误!\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    .c存放函数定义的源文件

    #include"contact_dynamic.h"
    
    //初始化通讯录
    void Init_contact(struct contact* p)
    {
    	assert(p);
    	//开辟空间
    	p->data =(struct message*) malloc(DEFAULT_SZ * sizeof(struct message));
    	//假如开辟失败,报错
    	if (p->data == NULL)
    	{
    		printf("%s\n", strerror(errno));
    		return;
    	}
    	p->sz = 0;
    	p->capacity = DEFAULT_SZ;
    
    }
    //是否判断增容
    int check_capacity(struct contact*p)
    {
    	//当联系人个数 == 通讯录容量时,增容INC_SZ个内存空间
    	if (p->sz == p->capacity)
    	{
    		struct message* ptr = (struct message*)realloc(p->data, (p->capacity + INC_SZ) * sizeof(struct message));
    		if (ptr == NULL)//判断是否增容失败
    		{
    			printf("%s\n", strerror(errno));
    			return 0;
    		}
    		else
    		{
    			p->data = ptr;//增容成功,data就指向这块新开辟的空间
    			p->capacity += INC_SZ;//容量+=INC_SZ
    			//printf("增容成功!\n");
    			return 1;
    		}
    	}
    	//不需要增容
    	else
    		return 1;
    }
    
    //增加联系人
    void Add_contact(struct contact* p)
    {
    	assert(p);
    	if (0 == check_capacity(p))
    	{
    		printf("%s\n", strerror(errno));
    		return;
    	}
    	printf("请输入姓名:->");
    	scanf("%s", p->data[p->sz].name);
    
    	printf("请输入性别:->");
    	scanf("%s", p->data[p->sz].sex);
    
    	printf("请输入电话:->");
    	scanf("%s", p->data[p->sz].tele);
    
    	printf("请输入住址:->");
    	scanf("%s", p->data[p->sz].addr);
    
    	printf("请输入年龄:->");
    	scanf("%d", &(p->data[p->sz].age));
    	system("cls");
    
    	printf("增加成功!\n");
    	printf("\n");
    	p->sz++;
    }
    //显示联系人
    void Show_contact(const struct contact* p)
    {
    	assert(p);
    	int i = 0;
    	printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5s\n", "姓名", "性别", "电话", "住址", "年龄");
    	for (i = 0; i < p->sz; i++)
    	{
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5d\n", p->data[i].name,
    			p->data[i].sex,
    			p->data[i].tele,
    			p->data[i].addr,
    			p->data[i].age);
    	}
    }
    int find_name(const struct contact* p, char arr[])
    {
    	assert(p);
    	int i = 0;
    	for (i = 0; i < p->sz; i++)
    	{
    		if (0 == strcmp(p->data[i].name, arr))
    			return i;
    	}
    	return -1;
    }
    //删除联系人
    void Dele_contact(struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要删除联系人的姓名:->");
    	scanf("%s", del_name);
    	//查找该联系人
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    		printf("查无此人!\n");
    	else
    	{
    		int j = 0;
    		for (j = ret; j < p->sz - 1; j++)
    		{
    			p->data[j] = p->data[j + 1];
    		}
    		p->sz--;
    		system("cls");
    
    		printf("删除成功!\n");
    		printf("\n");
    	}
    }
    //修改菜单栏
    void menu_()
    {
    	printf("***********************************\n");
    	printf("******   1、修改联系人姓名   ******\n");
    	printf("******   2、修改联系人电话   ******\n");
    	printf("******   3、修改联系人年龄   ******\n");
    	printf("******   4、修改联系人住址   ******\n");
    	printf("******   5、修改联系人性别   ******\n");
    	printf("******   0、返回主菜单       ******\n");
    
    }
    //修改联系人信息
    void revise_contact(struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要修改信息的联系人的姓名:->");
    	scanf("%s", del_name);
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    	{
    		printf("查无此人!\n");
    		printf("\n");
    	}
    	else
    	{
    		int in_put = 0;
    		do
    		{
    			menu_();
    			scanf("%d", &in_put);
    			switch (in_put)
    			{
    			case 1:
    				printf("请输入修改后的姓名:->");
    				scanf("%s", p->data[ret].name);
    				system("cls");
    
    				printf("姓名修改成功!\n");
    				break;
    			case 2:
    				printf("请输入修改后的电话:->");
    				scanf("%s", p->data[ret].tele);
    				system("cls");
    
    				printf("电话修改成功!\n");
    				break;
    			case 3:
    				printf("请输入修改后的年龄:->");
    				scanf("%d", &(p->data[ret].age));
    				system("cls");
    
    				printf("年龄修改成功!\n");
    				break;
    			case 4:
    				printf("请输入修改后的住址:->");
    				scanf("%s", p->data[ret].addr);
    				system("cls");
    
    				printf("住址修改成功!\n");
    				break;
    			case 5:
    				printf("请输入修改后的性别:->");
    				scanf("%s", p->data[ret].sex);
    				system("cls");
    
    				printf("性别修改成功!\n");
    				break;
    			case 0:
    				printf("取消修改!\n");
    				break;
    			default:
    				printf("输入错误!\n");
    				break;
    			}
    		} while (in_put);
    	}
    }
    //查找联系人信息
    void Find_contact(const struct contact* p)
    {
    	assert(p);
    	char del_name[NAME];
    	printf("请输入要查找联系人的姓名:->");
    	scanf("%s", del_name);
    	system("cls");
    
    	//查找该联系人
    	int ret = find_name(p, del_name);
    	if (ret == -1)
    		printf("查无此人!\n");
    	else
    	{
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5s\n", "姓名", "性别", "电话", "住址", "年龄");
    		printf("%-20s\t%-5s\t%-12s\t%-20s\t%-5d\n", p->data[ret].name,
    			p->data[ret].sex,
    			p->data[ret].tele,
    			p->data[ret].addr,
    			p->data[ret].age);
    	}
    }
    //排序菜单
    void menu_sort()
    {
    	printf("******   1、姓名   ******\n");
    	printf("******   2、住址   ******\n");
    	printf("******   3、年龄   ******\n");
    	printf("******   4、性别   ******\n");
    	printf("******   0、退出   ******\n");
    }
    
    //姓名排序
    int cmp_name(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->name, ((struct message*)e2)->name);
    }
    //住址排序
    int cmp_addr(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->addr, ((struct message*)e2)->addr);
    }
    //年龄排序
    int cmp_age(const void* e1, const void* e2)
    {
    	return ((struct message*)e1)->age - ((struct message*)e2)->age;
    }
    //性别排序
    int cmp_sex(const void* e1, const void* e2)
    {
    	return strcmp(((struct message*)e1)->sex, ((struct message*)e2)->sex);
    }
    //排序联系人
    void Sort_contact(struct contact* p)
    {
    	int s = 0;
    	do
    	{
    		//排序菜单
    		menu_sort();
    		printf("请选择排序类型:->");
    		scanf("%d", &s);
    		system("cls");
    		switch (s)
    		{
    		case 1:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_name);
    			printf("排序成功!\n");
    			break;
    		case 2:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_addr);
    			printf("排序成功!\n");
    			break;
    		case 3:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_age);
    			printf("排序成功!\n");
    			break;
    		case 4:
    			qsort(p->data, p->sz, sizeof(struct message), cmp_sex);
    			printf("排序成功!\n");
    			break;
    		case 0:
    			printf("退出排序\n");
    			break;
    		default:
    			printf("输入有误!\n");
    			break;
    		}
    
    	} while (s);
    }
    
    //清空联系人
    void Clean(struct contact* p)
    {
    	p->sz = 0;
    	printf("清空成功!\n");
    }
    //释放空间
    void Destory_contact(struct contact* p)
    {
    	free(p->data);
    	p->data=NULL;
    	p->sz = 0;
    	p->capacity = 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311

    end
    生活原本沉闷,但跑起来就会有风!

  • 相关阅读:
    Roguelike 游戏中的计算哲学
    【寒武纪(3)】媒体处理系统的系统控制、视频输入和后处理子系统
    ZZNUOJ_C语言1123:最佳校友(附完整源码)
    网络安全工程师日常工作有哪些?初学者怎么适应
    无心剑中译伊玛·拉扎罗斯《新巨人·自由女神》
    windows安装pytorch
    深入理解 python 虚拟机:令人拍案叫绝的字节码设计
    pandas 将一行拆分为多行,将多行合并为一行
    DAMA-第三章(数据治理)
    Stm32_标准库_GPIOA初始化
  • 原文地址:https://blog.csdn.net/qq_60192898/article/details/127865873