目录
通讯录中所涉及到的动态内存管理相关知识在:
C语言动态内存管理(malloc, calloc,realloc)详解-CSDN博客
柔性数组:
结构体等自定义类型相关知识:
结构体、枚举以及联合类型在内存中的存储与大小计算-CSDN博客
还有之前写过的一个简易的三子棋游戏:
该通讯录功能为增、删、查、改以及展示目前存放的所有联系人信息,更多功能以及优化等待博主后续的努力
该代码分三个模块:主函数(test_16.c)、具体功能的实现(contact.c)、以及函数的声明(contact.h)
在开头引用contact.h头文件,函数内涵所用到的所有函数以及结构体声明
#include "contact.h"
- void menu()
- {
- printf("***************************************\n");
- printf("**** 1.add 2.del **********\n");
- printf("**** 3.search 4.modify **********\n");
- printf("**** 5.show 0.exit **********\n");
- printf("***************************************\n");
- }
- enum Option //列举出通讯录功能
- {
- EXIT,
- ADD,
- DEL,
- SEARCH,
- MODIFY,
- SHOW,
- };
使用do...while循环以及switch来实现功能的反复使用,其中的结构体和函数声明在自身创的头文件中,再开头以及引用
- int main()
- {
- int input = 0;
- Contact con;//结构体
- InitContact(&con);//初始化通讯录
- do
- {
- menu();
- printf("请输入你的选择:>");
- scanf("%d", &input);
- switch (input)
- {
- case ADD:
- AddContact(&con);
- break;
- case DEL:
- DelContact(&con);
- break;
- case SEARCH:
- SearchContact(&con);
- break;
- case MODIFY:
- ModifyContact(&con);
- break;
- case SHOW:
- ShowContact(&con);
- break;
- case EXIT:
- DestroyContact(&con);//销毁空间
- printf("退出\n");
- break;
- default:
- printf("输入错误,请重新输入\n");
- break;
- }
- } while (input);
- return 0;
- }
头文件中包括库函数、各功能函数、结构体等声明,以供在其他模块更好的使用
- #pragma once
- #include
- #include
- #include
- #include
- #define NAME_MAX 20
- #define SEX_MAX 5
- #define TELE_MAX 12
- #define ADDR_MAX 30
- #define MAX 100
- #define DEFAULT_SZ 3
- #define DEFAULT_INC 2
-
-
-
- //类型的声明
- typedef struct PeoInfo
- {
- char name[NAME_MAX];
- int age;
- char sex[SEX_MAX];
- char tele[TELE_MAX];
- char addr[ADDR_MAX];
- }PeoInfo;
- //静态
- //typedef struct Contact
- //{
- // PeoInfo data[MAX];//存放数据
- // int sz;//记录当前通讯录中存在的人的信息个数
- //}Contact;
-
- //动态
- typedef struct Contact
- {
- PeoInfo* data;//存放数据
- int sz;//记录当前通讯录中存在的人的信息个数
- int capacity;//记录的是通讯录的当前容量
- }Contact;
-
- //初始化通讯录
- void InitContact(Contact* pc);
-
- //增加联系人
- void AddContact(Contact* pc);
-
- //显示所有联系人
- void ShowContact(Contact* pc);
-
- //删除指定联系人
- void DelContact(Contact* pc);
-
- //查找指定联系人
- void SearchContact(Contact* pc);
-
- //修改指定联系人
- void ModifyContact(Contact* pc);
-
- //销毁通讯录
- void DestroyContact(Contact* pc);
- void InitContact(Contact* pc)
- {
- assert(pc);
- pc->sz = 0; //初始通讯录个人信息为0
- pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
- pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
- if (pc->data == NULL)
- {
- perror("calloc");//如果没有开辟成功返回报错信息
- return;
- }
- memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
- }
在增加联系人前,需要检查通讯录的容量是否够用,这里单独分装成一个函数,来实现容量的检查以及扩展
- void CheckCapacity(Contact* pc) //检查容量大小
- {
- if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
- {
- PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
- if (ptr != NULL)
- {
- pc->data = ptr;//开辟成功则把空间赋给data
- pc->capacity += DEFAULT_INC;//让容量自增2个
- printf("增容成功\n");
- }
- else
- {
- perror("AddContact->realloc");//开辟失败返回报错信息
- return;
- }
- }
- }
- void AddContact(Contact* pc)//增加联系人
- {
- assert(pc);
- CheckCapacity(pc);//查看容量,容量不够则增加
- //增加信息
- printf("请输入名字:");
- scanf("%s", pc->data[pc->sz].name);
- printf("请输入年龄:");
- scanf("%d", &pc->data[pc->sz].age);
- printf("请输入性别:");
- scanf("%s", pc->data[pc->sz].sex);
- printf("请输入电话:");
- scanf("%s", pc->data[pc->sz].tele);
- printf("请输入地址:");
- scanf("%s", pc->data[pc->sz].addr);
-
- pc->sz++;
- printf("增加成功\n");
- }
- void ShowContact(Contact* pc)//展示所有联系人信息
- {
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无需打印\n");
- return;
- }
- int i = 0;
- //名字 年龄 性别 电话 地址
- printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- for (i = 0; i < pc->sz; i++)
- {
- //打印每个人信息
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
- }
- }
删除联系人需要对通讯录进行查找,所有这里我们也时再次分装一个函数用来查找联系人,后续联系人信息的修改以及查询某个联系人同样需要此函数
- int FindByName(Contact* pc, char name[])
- {
- assert(pc);
- int i = 0;
- for (i = 0; i < pc->sz; i++)//进入循环逐个查找
- {
- if (strcmp(pc->data[i].name, name) == 0)
- {
- return i;
- }
- }
- return -1;//找不到
- }
开始删除
- void DelContact(Contact* pc)//删除指定联系人
- {
- char name[NAME_MAX];
- assert(pc);
- if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
- {
- printf("通讯录为空,无法删除\n");
- return;
- }
- //找到联系人
- printf("输入删除人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要删除得到人不存在\n");
- return;
- }
- //删除这个人
- int i = 0;
- for (i = ret; i < pc->sz-1; i++)
- {
- pc->data[i] = pc->data[i + 1];
- }
- pc->sz--;
- printf("删除成功\n");
- }
这里也用了查找函数
- void SearchContact(Contact* pc)//查询联系人
- {
- assert(pc);
- char name[NAME_MAX];
- printf("输入查找人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要查找的人不存在\n");
- return;
- }
- //显示出来
- printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
- }
- void ModifyContact(Contact* pc)修改指定联系人
- {
- assert(pc);
- char name[NAME_MAX];
- printf("输入要修改人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要修改的人不存在\n");
- return;
- }
- //修改
- printf("请输入名字:");
- scanf("%s", pc->data[ret].name);
- printf("请输入年龄:");
- scanf("%d", &pc->data[ret].age);
- printf("请输入性别:");
- scanf("%s", pc->data[ret].sex);
- printf("请输入电话:");
- scanf("%s", pc->data[ret].tele);
- printf("请输入地址:");
- scanf("%s", pc->data[ret].addr);
- }
开辟的内存使用后需要进行释放
- void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
- {
- free(pc->data);
- pc->data = NULL;
- pc->capacity = 0;
- pc->sz = 0;
- }
- #define _CRT_SECURE_NO_WARNINGS
- #include "contact.h"
- //测试通讯录的基本功能
- void menu()
- {
- printf("***************************************\n");
- printf("**** 1.add 2.del **********\n");
- printf("**** 3.search 4.modify **********\n");
- printf("**** 5.show 0.exit **********\n");
- printf("***************************************\n");
- }
- enum Option //列举出通讯录功能
- {
- EXIT,
- ADD,
- DEL,
- SEARCH,
- MODIFY,
- SHOW,
- };
- int main()
- {
- int input = 0;
- Contact con;//结构体
- InitContact(&con);//初始化通讯录
- do
- {
- menu();
- printf("请输入你的选择:>");
- scanf("%d", &input);
- switch (input)
- {
- case ADD:
- AddContact(&con);
- break;
- case DEL:
- DelContact(&con);
- break;
- case SEARCH:
- SearchContact(&con);
- break;
- case MODIFY:
- ModifyContact(&con);
- break;
- case SHOW:
- ShowContact(&con);
- break;
- case EXIT:
- DestroyContact(&con);//销毁空间
- printf("退出\n");
- break;
- default:
- printf("输入错误,请重新输入\n");
- break;
- }
- } while (input);
- return 0;
- }
- #pragma once
- #include
- #include
- #include
- #include
- #define NAME_MAX 20
- #define SEX_MAX 5
- #define TELE_MAX 12
- #define ADDR_MAX 30
- #define MAX 100
- #define DEFAULT_SZ 3
- #define DEFAULT_INC 2
-
-
-
- //类型的声明
- typedef struct PeoInfo
- {
- char name[NAME_MAX];
- int age;
- char sex[SEX_MAX];
- char tele[TELE_MAX];
- char addr[ADDR_MAX];
- }PeoInfo;
- //静态
- //typedef struct Contact
- //{
- // PeoInfo data[MAX];//存放数据
- // int sz;//记录当前通讯录中存在的人的信息个数
- //}Contact;
-
- //动态
- typedef struct Contact
- {
- PeoInfo* data;//存放数据
- int sz;//记录当前通讯录中存在的人的信息个数
- int capacity;//记录的是通讯录的当前容量
- }Contact;
-
- //初始化通讯录
- void InitContact(Contact* pc);
-
- //增加联系人
- void AddContact(Contact* pc);
-
- //显示所有联系人
- void ShowContact(Contact* pc);
-
- //删除指定联系人
- void DelContact(Contact* pc);
-
- //查找指定联系人
- void SearchContact(Contact* pc);
-
- //修改指定联系人
- void ModifyContact(Contact* pc);
-
- //销毁通讯录
- void DestroyContact(Contact* pc);
- #define _CRT_SECURE_NO_WARNINGS
- #include "contact.h"
- //静态
- //void InitContact(Contact* pc)
- //{
- // assert(pc);
- // pc->sz = 0;
- // memset(pc->data, 0, sizeof(pc->data));
- //}
-
- //动态
- void InitContact(Contact* pc)
- {
- assert(pc);
- pc->sz = 0; //初始通讯录个人信息为0
- pc->capacity = DEFAULT_SZ; // 通讯录初始容量为3
- pc->data = calloc(pc->capacity, sizeof(PeoInfo));//为存放数据开辟内存
- if (pc->data == NULL)
- {
- perror("calloc");//如果没有开辟成功返回报错信息
- return;
- }
- memset(pc->data, 0, sizeof(pc->data));//开辟成功,把数据初始化为0
- }
-
- //静态版本
- //void AddContact(Contact* pc)
- //{
- // assert(pc);
- // if (pc->sz == MAX)
- // {
- // printf("通讯录已满,无法增加\n");
- // return;
- // }
- // //增加信息
- // printf("请输入名字:");
- // scanf("%s", pc->data[pc->sz].name);
- // printf("请输入年龄:");
- // scanf("%d", &pc->data[pc->sz].age);
- // printf("请输入性别:");
- // scanf("%s", pc->data[pc->sz].sex);
- // printf("请输入电话:");
- // scanf("%s", pc->data[pc->sz].tele);
- // printf("请输入地址:");
- // scanf("%s", pc->data[pc->sz].addr);
- //
- // pc->sz++;
- // printf("增加成功\n");
- //}
-
-
- void CheckCapacity(Contact* pc) //检查容量大小
- {
- if (pc->sz == pc->capacity)//增加的当前人的数量与容量相等
- {
- PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_INC) * sizeof(PeoInfo));//给data重新开辟空间
- if (ptr != NULL)
- {
- pc->data = ptr;//开辟成功则把空间赋给data
- pc->capacity += DEFAULT_INC;//让容量自增2个
- printf("增容成功\n");
- }
- else
- {
- perror("AddContact->realloc");//开辟失败返回报错信息
- return;
- }
- }
- }
- void DestroyContact(Contact* pc)//开辟的内存使用后需要进行释放
- {
- free(pc->data);
- pc->data = NULL;
- pc->capacity = 0;
- pc->sz = 0;
- }
- void AddContact(Contact* pc)//增加联系人
- {
- assert(pc);
- CheckCapacity(pc);//查看容量,容量不够则增加
- //增加信息
- printf("请输入名字:");
- scanf("%s", pc->data[pc->sz].name);
- printf("请输入年龄:");
- scanf("%d", &pc->data[pc->sz].age);
- printf("请输入性别:");
- scanf("%s", pc->data[pc->sz].sex);
- printf("请输入电话:");
- scanf("%s", pc->data[pc->sz].tele);
- printf("请输入地址:");
- scanf("%s", pc->data[pc->sz].addr);
-
- pc->sz++;
- printf("增加成功\n");
- }
-
-
-
-
- void ShowContact(Contact* pc)//展示所有联系人信息
- {
- assert(pc);
- if (pc->sz == 0)
- {
- printf("通讯录为空,无需打印\n");
- return;
- }
- int i = 0;
- //名字 年龄 性别 电话 地址
- printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- for (i = 0; i < pc->sz; i++)
- {
- //打印每个人信息
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
- }
- }
-
-
- int FindByName(Contact* pc, char name[])
- {
- assert(pc);
- int i = 0;
- for (i = 0; i < pc->sz; i++)//进入循环逐个查找
- {
- if (strcmp(pc->data[i].name, name) == 0)
- {
- return i;
- }
- }
- return -1;//找不到
- }
- void DelContact(Contact* pc)//删除指定联系人
- {
- char name[NAME_MAX];
- assert(pc);
- if (pc->sz == 0)//如果当前通讯录并没有增加任何联系人,则返回
- {
- printf("通讯录为空,无法删除\n");
- return;
- }
- //找到联系人
- printf("输入删除人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要删除得到人不存在\n");
- return;
- }
- //删除这个人
- int i = 0;
- for (i = ret; i < pc->sz-1; i++)
- {
- pc->data[i] = pc->data[i + 1];
- }
- pc->sz--;
- printf("删除成功\n");
- }
-
-
- void SearchContact(Contact* pc)//查询指定联系人
- {
- assert(pc);
- char name[NAME_MAX];
- printf("输入查找人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要查找的人不存在\n");
- return;
- }
- //显示出来
- printf("%-20s%-5s%-5s%-12s%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- printf("%-20s%-5d%-5s%-12s%-30s\n",
- pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tele, pc->data[ret].addr);
- }
-
-
- void ModifyContact(Contact* pc)修改指定联系人
- {
- assert(pc);
- char name[NAME_MAX];
- printf("输入要修改人的名字:");
- scanf("%s", name);
- //找到名字为name的人
- int ret = FindByName(pc, name);
- if (ret == -1)
- {
- printf("要修改的人不存在\n");
- return;
- }
- //修改
- printf("请输入名字:");
- scanf("%s", pc->data[ret].name);
- printf("请输入年龄:");
- scanf("%d", &pc->data[ret].age);
- printf("请输入性别:");
- scanf("%s", pc->data[ret].sex);
- printf("请输入电话:");
- scanf("%s", pc->data[ret].tele);
- printf("请输入地址:");
- scanf("%s", pc->data[ret].addr);
- }

3. 查找联系人


