目录
设计思路
1. 通讯录存放的信息
这个通讯录保存的信息包括:名字,年龄,性别,电话,住址。
2. 通讯录的功能
1. 通讯录可以存放100个人的信息。
2. 增加联系人
3. 删除联系人
4. 修改联系人
5. 查询联系人
6. 显示所有人
3. 文件规划
我们准备三个文件完成这个项目。
test.c —— 负责测试
contact.h —— 负责函数和类型声明
contact.c —— 负责函数实现
4. 设计思路
1. 通讯录保存的信息有很多,我们可以设计一个结构体来存放这些信息。
2. 通讯录要存放100个人的信息,那我们可以创建一个存放这个结构体的数组。
代码实现
1. 设计存放信息的结构体
1. 我们先设计存放信息的结构体,因为这个结构体可能有多个文件会用到,所以我们统一放在头文件。
2. 名字,性别,电话,住址都是字符串所以用char数组,年龄用int。
3. 为了方便使用,用typedef重命名一下。
//通讯录保存的个人信息 typedef struct Info { char name[10]; //名字 char sex[5]; //性别 int age; //年龄 char tele[12]; //电话 char addr[20]; //住址 }Info;
4. 不同人有不同的个人信息,我们要把这些信息管理起来,所以我们要创建一个存放结构体的数组。
5. 我们还需要创建一个变量去记录数组元素的数量,以便于我们对数组信息的掌控。
6. 为了方便后续传参,我们再设计一个结构体把这两个变量作为结构体的成员。
//将Cont类型变量作为通讯录的基本单位 typedef struct Cont { Info data[100]; //存放个人信息结构体的数组 int cout; //记录数组元素个数 }Cont;
2. 菜单实现
1. 设计一个菜单,利用do while 和 switch case配合,根据不同的功能选择不同的数字。
//菜单 void menu() { printf("-----------------------------\n"); printf("--- 0.退出 --- 1.增加 -------\n"); printf("-----------------------------\n"); printf("--- 2.删除 --- 3.修改 -------\n"); printf("-----------------------------\n"); printf("--- 4.查询 --- 5.显示 -------\n"); printf("-----------------------------\n"); } int main() { int input; do { menu(); printf("请输入要执行的操作->"); scanf("%d", &input); switch (input) { case 0: printf("退出成功\n"); break; case 1: //增加 break; case 2: //删除 break; case 3: //修改 break; case 4: //查询 break; case 5: //显示 break; default: printf("输入无效\n"); break; } } while (input); return 0; }
3. 初始化通讯录
1. 初始化通讯录。利用memset将存放结构体的数组置0,计数也置为0。
void InitCont(Cont* cont) { //将数组置为0 memset(cont, 0, sizeof(cont->data)); //将计数置为0 cont->cout = 0; return; }
4. 增加联系人
1. 先判断是否满了,满了就不能增加了。
2. 如果没满,输入信息,将计数作为数组下标存放,计数加1。
void AddInfo(Cont* cont) { if (cont->cout == DATA_MAX) { printf("通讯录已满,不能新增\n"); return; } //利用计数作为数组下标 printf("姓名:"); scanf("%s", cont->data[cont->cout].name); printf("性别:"); scanf("%s", cont->data[cont->cout].sex); printf("年龄:"); scanf("%d", &(cont->data[cont->cout].age)); printf("电话:"); scanf("%s", cont->data[cont->cout].tele); printf("住址:"); scanf("%s", cont->data[cont->cout].addr); //增加一个元素,计数+1 cont->cout++; }
5. 显示所有联系人
1. 不用修改数据所以参数可以加const。
2. 根据计数得到元素个数然后遍历打印信息。
3. %10s 表示输出宽度为10并且右对齐,%-10s 加个负号表示左对齐。
void ShowInfo(const Cont* cont) { printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\n", "名字", "性别", "年龄", "电话", "住址"); for (int i = 0; i < cont->cout; i++) { printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\n", cont->data[i].name, cont->data[i].sex, cont->data[i].age, cont->data[i].tele, cont->data[i].addr); } }
6. 删除联系人
1. 在实现删除之前我们先写一个另外的函数,这个函数是根据输入的姓名,返回它所对应的数组下标。
2. 将最后一个元素覆盖到要删除的地方,然后计数减减。
void DelInfo(Cont* cont) { printf("输入你要删除的名字->"); char name[10]; scanf("%s", name); //根据名字返回下标 int index = FindByName(cont, name); //找不到 if (index == -1) { printf("没有这个人\n"); return; } //找到了 //将最后一个元素覆盖到要删除的地方,然后计数减减 cont->data[index] = cont->data[cont->cout - 1]; cont->cout--; }
7. 查询联系人
1. 查询不会修改数据所以参数可以加const。
2. 复用前面写的FindByName函数,通过名字返回下标,根据下标打印数据。
void SeleInfo(const Cont* cont) { printf("输入你要查询的名字->"); char name[10]; scanf("%s", name); int index = FindByName(cont, name); if (index == -1) { printf("没有这个人\n"); return; } printf("%-10s\t%-5s\t%-4s\t%-12s\t%-20s\n", "名字", "性别", "年龄", "电话", "住址"); printf("%-10s\t%-5s\t%-4d\t%-12s\t%-20s\n", cont->data[index].name, cont->data[index].sex, cont->data[index].age, cont->data[index].tele, cont->data[index].addr); }
7. 修改联系人
1. 输入名字找到下标。
2. 利用scanf修改信息。
void ModInfo(Cont* cont) { printf("输入你要修改的名字->"); char name[10]; scanf("%s", name); int index = FindByName(cont, name); if (index == -1) { printf("没有这个人\n"); return; } //利用scanf修改信息 printf("姓名:"); scanf("%s", cont->data[index].name); printf("性别:"); scanf("%s", cont->data[index].sex); printf("年龄:"); scanf("%d", &(cont->data[index].age)); printf("电话:"); scanf("%s", cont->data[index].tele); printf("住址:"); scanf("%s", cont->data[index].addr); }
代码仓库
完整代码