C-Week7
参考教程:黑马程序员——01 通讯录管理系统-系统功能介绍及展示_bilibili 注意这个项目其实是想让我用链表实现的,但我没仔细看要求(说实话,一个通讯录要预先分配数十到数百倍于真实使用的空间的内存,想想就恐怖 XP
1. 项目功能介绍
对于一个简单的通讯录管理系统,其主要功能有:
- 添加联系人:向通讯录中添加新联系人,固定需要添加的信息有:姓名、性别、年龄、联系电话和家庭住址。要求最多支持添加1000个联系人。
- 显示联系人:显示通讯录中所有联系人的信息
- 删除联系人:按照姓名删除指定的联系人
- 查找联系人:按照姓名查看指定联系人信息
- 修改联系人:按照姓名重新修改指定联系人
- 清空联系人:清空通讯录中所有联系人信息
- 退出通讯录:退出当前使用的通讯录
该通讯录应该进行具备一定的人机交互特征(命令行下),具体有:
-
初始的功能菜单:列出以上功能,并用数字代号提示各个功能。用户可以输入代号来访问对应的功能。可以对菜单做一些装饰性元素
-
不重启切换功能:要求切换功能时保持当前程序运行,而不是让用户一遍遍重启程序。菜单不要重复输出
-
添加联系人:以问答式方式引导用户输入需要添加的信息。性别一栏可以提供选项,
如果要考虑DEI,也可以让用户自己输入自己的性别。所有信息添加完成后,需要明确提示用户“添加成功”。 -
显示联系人:要求格式化输出。建议在一行内输出且只输出一个联系人的信息。如果没有任何联系人信息,应输出“当前记录为空”之类的提示信息
-
删除联系人:以问答式方式确认需要删除的联系人。删除成功后需要说明。如果删除了不存在的联系人,程序也需要提示“查无此人”。
-
查找联系人:以问答式方式确认需要查询的联系人。如果查询了不存在的联系人,程序需要提示“查无此人”。
-
修改联系人:实质上相当于调用“添加联系人”功能。修改成功后需要提示
-
清空联系人:清空后需要提示。更好的做法是在删除前加上确认信息,防止误删
-
退出通讯录:建议输出退出语,比如“欢迎下次使用”
2. 分功能开发
2.1 添加联系人
-
数据方面
我们使用结构体来存储单个联系人信息,因为我们要存储的信息的类型明显不同,并且应该归属于同一个条目下。
对于联系人信息结构体的集合,我们使用数组存储。
-
算法方面
使用最经典的
scanf输入单个结构体的成员的数据。提示语用printf输出。单个信息输入完毕后,在
main函数中对计数器i++,标示数组元素个数以供索引不得不说,Clang 的代码诊断对于中文疑似不太友好啊,一直输出
warning。
void add_person(info arr[], int i) { //input name printf("请输入姓名:\n"); scanf("%s", arr[i].name); //input gender printf("请输入性别:\n"); scanf("%s", arr[i].gender); //input age printf("请输入年龄:\n"); scanf("%d", &arr[i].age); //input phone number printf("请输入联系电话:\n"); scanf("%s", arr[i].phone); //input location printf("请输入家庭住址:\n"); scanf("%s", arr[i].location);}
2.2 显示联系人
void list_person(info arr[], int i) { if (i == 0) { printf("当前记录为空\n"); } else { for (int cnt = 0; cnt < i; cnt++) { printf("姓名:%s \ 性别:%s \ 年龄:%d \ 联系电话:%s \ 家庭住址:%s\n", arr[cnt].name, arr[cnt].gender, arr[cnt].age, arr[cnt].phone, arr[cnt].location); } }}实机演示:


2.3 删除联系人
初始版本仅仅令计数器i--,但在后续测试中发现只考虑到最后一个联系人数据的删除。
为了让任意一个元素均可以被删除,我们可以移动数组内元素,用后续元素把目标元素给覆盖掉,再令计数器i--,防止数组越界
由于我们需要改变实参i的数值,因此传入i的指针。
void delete_person(info arr[], int* i) { bool check = 0; if (*i == 0) { printf("当前通讯录为空\n"); } else { printf("请输入将要删除的联系人的姓名:\n"); char goal[MAX_CHARACTER_LENGTH]; scanf("%s", goal); for (int j = 0; j < *i; j++) { if (!strcmp(goal, arr[j].name)) { for (int ds = 0; ds < *i - j; ds++) { arr[j + ds] = arr[j + (ds + 1)]; } (*i)--; check = 1; printf("删除成功!\n"); break; } } if (!check){ printf("查无此人\n"); } }}实机演示:


2.4 查找联系人
void find_person(info arr[], int i) { printf("请输入将要查询的联系人的姓名:\n"); char goal[MAX_CHARACTER_LENGTH]; scanf("%s", goal); for (int j = 0; j < i; j++) { if (!strcmp(goal, arr[j].name)) { printf("姓名:%s \性别:%s \年龄:%d \联系电话:%s \家庭住址:%s\n", arr[j].name, arr[j].gender, arr[j].age, arr[j].phone, arr[j].location); } else { printf("查无此人\n"); } }}

2.5 修改联系人
找到目标联系人后调用add_person把原来的联系人覆盖掉就行
void edit_person(info arr[], int i) { bool check = 0; if (i == 0) { printf("当前通讯录为空\n"); } else { printf("请输入将要修改的联系人的姓名:\n"); char goal[MAX_CHARACTER_LENGTH]; scanf("%s", goal); for (int j = 0; j < i; j++) { if (!strcmp(goal, arr[j].name)) { add_person(arr, j); check = 1; break; } } if (!check) { printf("查无此人\n"); } }}实机演示:

2.6 清空联系人
void empty_person(int* i) { printf("确定要清空通讯录吗?\n" "输入'y'确定,输入'n'取消\n"); char check = getchar(); if (check == 'y' || check == 'Y') { *i = 0; printf("已清空!\n"); } else { printf("已取消操作\n"); }}

2.7 主界面(退出通讯录)
int main(void) { int status; int i = 0; do { printf("*****通讯录*****\n"); printf("*请输入对应代码*\n" "* 1.添加联系人 *\n" "* 2.显示联系人 *\n" "* 3.删除联系人 *\n" "* 4.查找联系人 *\n" "* 5.修改联系人 *\n" "* 6.清空联系人 *\n" "* 0.退出通讯录 *\n" "****************\n"); while (scanf("%d", &status) != 1) { printf("无法识别功能代码,请重新输入:\n"); while (getchar() != '\n'); } switch (status) { case 1: add_person(data, i); i++; break; case 2: list_person(data, i); break; case 3: delete_person(data, &i); break; case 4: find_person(data, i); break; case 5: edit_person(data, i); break; case 6: empty_person(&i); break; case 0: printf("欢迎下次使用!\n"); break; default: printf("功能不存在。请重试!\n"); } system("pause"); system("cls"); } while (status != 0); return 0;}
3.人机交互优化
在主界面中,对于非数字输入,我们将拒绝该输入并要求用户重新输入:
while (scanf("%d", &status) != 1) { printf("无法识别功能代码,请重新输入:\n"); while (getchar() != '\n');//将新数据传入缓冲区,让scanf函数读取}程序首先检查scanf返回的成功匹配参数的数据个数。当用户输入一个以数字开头的数据时,scanf返回1,程序进入功能代码匹配环节;当用户输入一个以其他字符开头的数据时,scanf返回0,进入该循环。
对于不存在的功能代码,提示“功能不存在”:
default: printf("功能不存在。请重试!\n");
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!