目录
- 一、通讯录设计思路
- 1. 伪代码设计思路
- 2. 代码设计思路
- 二、代码实现
- 三、程序运行演示
- 四、整体分析
一、通讯录设计思路
1. 伪代码设计思路
通讯录可以用来存储 100 个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。
提供方法:
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 以名字排序所有联系人
2. 代码设计思路
通过对上述伪代码的分析,我们使用结构体 info_person 来表示个人信息。
// 个人信息结构声明
typedef struct info_person
{char name[20]; // 姓名char sex[5]; // 性别size_t age; // 年龄char phone[12]; // 电话char address[40]; // 住址
}info_person;
接着再使用一个结构体 ContacksList 来表示通讯录,该通讯录包含一个结构体 info_person 数组,大小为 100,用来存储 100 个人的信息。此外还应该包含一个 size_t 类型的成员 size 用来表示当前存储个人信息的数量,这也方便了上述伪代码中要求的方法设计。
// 常量声明
#define SIZE_INFO 100// 通讯录结构声明
typedef struct ContacksList
{info_person infos[SIZE_INFO];size_t size;
}ContacksList;
下面就是使用有意义的函数名来表示上述方法。
// 方法// 1. 添加联系人信息
void AddContack(ContacksList* cl);// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl, char* name);// 3. 查找指定联系人信息
void FindContack(const ContacksList* cl, char* name);// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl, char* name);// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl);// 6. 清空所有联系人
void ClearContack(ContacksList* cl);// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl);
以上就是头文件 ContacksList.h 包含的基本内容,剩下的就是方法的实现和代码的测试。
二、代码实现
整体代码分成三个文件:头文件 ContacksList.h,方法定义文件 ContacksList.c,测试文件 test.c。由于头文件在前面已经给出,下面就只给出剩下两个文件。
方法定义文件 ContacksList.c
// 头文件
#include "ContacksList.h"
#include <assert.h>
#include <string.h>// 方法// 1. 添加联系人信息
void AddContack(ContacksList* cl)
{assert(cl);// 通讯录已满if (CAPACITY == cl->size){printf("通讯录已满,添加失败!\n");return;}// 添加// // 输入联系人的相关信息info_person tmp;printf("请输入联系人的信息->");printf("姓名: ");scanf("%s", tmp.name);printf("性别: ");scanf("%s", tmp.sex);printf("年龄: ");scanf("%zd", &tmp.age);printf("电话: ");scanf("%s", tmp.phone);printf("地址: ");scanf("%s", tmp.address);// 拷贝cl->infos[cl->size] = tmp;// 人数 +1++cl->size;printf("添加成功!\n");
}// 2. 删除指定联系人信息
void DeleteContack(ContacksList* cl)
{assert(cl);// 删除//// 查找指定联系人char name[20];printf("请输入删除人的姓名: ");scanf("%s", name);int i = FindContack(cl, name);// 找到了if (-1 != i){// 把该位置往后的联系人往前移while (i < cl->size - 1){// 前移cl->infos[i] = cl->infos[i + 1];// 下一个++i;}// 联系人 -1--cl->size;printf("删除成功!\n");}else{printf("删除失败!\n");}
}// 3. 查找指定联系人信息
int FindContack(const ContacksList* cl, char* name)
{assert(cl);// 通讯录为空if (0 == cl->size)return -1;// 输入查找人的姓名char tmp[20] = { 0 };if (NULL == name){name = tmp;printf("请输入查找人的姓名: ");scanf("%s", name);}// 查找int i;for (i = 0; i < cl->size; ++i){// 找到if (strcmp(cl->infos[i].name, name) == 0){return i;}}// 没找到return -1;
}// 4. 修改指定联系人信息
void ModifyContack(ContacksList* cl)
{assert(cl);// 查找指定联系人char name[20];printf("请输入修改人的姓名: ");scanf("%s", name);int i = FindContack(cl, name);// 找到了if (-1 != i){// 输入联系人修改后的相关信息info_person tmp;printf("请输入联系人的信息->");printf("姓名: ");scanf("%s", tmp.name);printf("性别: ");scanf("%s", tmp.sex);printf("年龄: ");scanf("%zd", &tmp.age);printf("电话: ");scanf("%s", tmp.phone);printf("地址: ");scanf("%s", tmp.address);// 修改cl->infos[i] = tmp;printf("修改成功!\n");}else{printf("修改失败!\n");}
}// 5. 显示所有联系人信息
void PrintContack(const ContacksList* cl)
{assert(cl);// 标题行printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");// 输出int i;for (i = 0; i < cl->size; ++i){printf("%-10s%-8s%-8zd%-15s%-10s\n", cl->infos[i].name, cl->infos[i].sex, cl->infos[i].age, cl->infos[i].phone, cl->infos[i].address);}
}// 6. 清空所有联系人
void ClearContack(ContacksList* cl)
{assert(cl);// 清空cl->size = 0;
}// 7. 以名字排序所有联系人
void SortByName(ContacksList* cl)
{assert(cl);// 冒泡排序int i;for (i = 0; i < cl->size - 1; ++i){int j;for (j = 0; j < cl->size - 1 - i; ++j){// 相邻比较if (strcmp(cl->infos[j].name, cl->infos[j + 1].name) > 0){// 交换info_person tmp = cl->infos[j];cl->infos[j] = cl->infos[j + 1];cl->infos[j + 1] = tmp;}}}printf("按名字身升序排序成功!\n");
}
测试文件 test.c
// 头文件
#include "ContacksList.h"// 菜单
void menu()
{printf("****************************************************\n");printf("***********1. Add 2. Delete *************\n");printf("***********3. Find 4. Modify *************\n");printf("***********5. Print 6. Clear *************\n");printf("***********7. Sort 0. Exit *************\n");printf("****************************************************\n");
}int main()
{// 创建通讯录ContacksList cl = { {0}, 0 };// 选择操作int select = 0;int i = 0;do{// 菜单menu();// 选择printf("请选择: ");scanf("%d", &select);switch (select){case 1:AddContack(&cl);break;case 2:DeleteContack(&cl);break;case 3:i = FindContack(&cl, NULL);printf("%-10s%-8s%-8s%-15s%-10s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s%-8s%-8zd%-15s%-10s\n", cl.infos[i].name, cl.infos[i].sex, cl.infos[i].age, cl.infos[i].phone, cl.infos[i].address);break;case 4:ModifyContack(&cl);break;case 5:PrintContack(&cl);break;case 6:ClearContack(&cl);break;case 7:SortByName(&cl);break;case 0:printf("退出通讯录!\n");break;default:printf("选择错误,请重新选择!\n");break;}} while (select);return 0;
}
三、程序运行演示
四、整体分析
该通讯录是一个静态通讯录,容量是固定的,当数据超出容量时不够存储,当数据少于容量时造成空间的浪费。后面作者会把该通讯录升级为动态通讯录,当容量不够的时候会进行增容。
在方法实现中,删除指定联系人函数 DeleteContack() 和修改指定联系人函数 ModifyContack() 都需要先找到指定的联系人,所以可以稍微修改一下查找指定联系人函数 FindContack(),然后再前面两个函数中调用该函数,这样就减少了代码的冗余。删除操作需要判断通讯录是否为空,插入操作需要判断通讯录是否已满。
当然读者可以自行根据需要进行修改,这里只提供一个大概思路和基础功能的实现。