目录
创建项目环境
对于这个通讯录的实现,我们可以像写三子棋一样,怎样去思考,那首先就要创建项目环境
这次也要去分模块去写
首先我们先要思考一下,通讯录有什么什么功能,它需要保存每个人的信息,对于这些信息我们还要进行增加,删除,查找,修改的操作,当然我们使用的手机通讯录也会按照字母的大小来排序。
开始我们自己创建的头文件依旧可以把我们的库函数,自定义类型等等,都写到这里面,在其他的源文件中引用" contact.h "。
创建结构体
首先我们要存放一个人的信息,这里创建一个结构体就可以存放人的名字,性别,年龄等。
这里用tpyedef重命名,以后PeoInfo就是这个结构体
test.c文件
开始的文件就打印一个菜单,写上之后要用到switch语句
可以根据我们的菜单来写
创建通讯录
下面这个Contact就是我们创建的通讯录,可以存放1000个人的信息,sz记录个数。
刚才的代码也可以用define来定义一下,方便我们的之后修改这个值。
之后就可以在test.c文件中使用
当然我们也可以用到上一篇提到的枚举,这样就可以和菜单匹配
下面的switch也可以改写成这样
当然也可以把枚举拿到头文件中
增加联系人
再增加联系人之前,我们并没有把Contact结构体中的成员初始化,所以下一步要把通讯录初始化。
使用memset就可以把整个数组初始化为0
之后就可以写增加函数了,也需要在头文件中声明一下
打印通讯录
上一步我们写了添加联系人的函数,之后我们写打印通讯录的函数来测试一下添加的联系人的信息有没有传进去。
经测试,输入的信息都传入了通讯录中
删除指定联系人
当我们想要删除指定的联系人的时候,首先要判断通讯录中是否还有数据。然后要找到我们想要删除的人,之后的查找联系人和更改联系人也要找到联系人,所以这里可以写一个函数帮助我们查找,找到之后就可以删除。
查找联系人
当我们要实现查找时,前面的很多代码都可以套用,比如通讯录为空的时候,通讯录中找不到的时候,以及找到了打印的时候,这些代码前面也写过。
更改联系人
这里不过多说什么,代码在前面已经写过了,灵活运用就可以
排列通讯录
排序联系人的时候,就可以用到之前指针篇章的qsort函数,也是非常的方便,只是这里是结构体排序,参数1:传入待排序的起始位置,既然要排序就指向联系人的第一个;参数2:元素个数,也就是通讯录中有几个人;参数3:一个元素的字节,也就是整个人的字节大小;参数4:排序的函数地址。
在写排序函数的时候和排列整型数组不同,这里把e1和e2强制类型转换成结构体指针,这里就不需要解引用了,指针就直接用->,在我们日常使用的通讯录中,一般都是联系人的首字母来比较,所以这里就直接拿name来比较了,name是一个字符串,用strcmp来比较。
完善通讯录
到这里通讯录基本就已经完成了,最后就看看有什么可以优化的地方,比如:查找和打印的功能不需要修改,但我们也不希望目标结构体改变,所以加上const来修饰;另一点就是,结构体传参的时候,使用传址调用(上一篇也讲到为什么结构体要传址而不是传值),既然传址就要用到指针,在函数调用的时候还是断言一下的好。
代码
所有代码如下
contact.h文件
#pragma once #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> //类型的声明 #define MAX 1000 #define NAME_MAX 20 #define SEX_MAX 5 #define TELE_MAX 12 #define ADDR_MAX 30 enum Option { EXIT,//0 ADD,//1 DEL,//2 SEARCH,//3 MODIFY,//4 SORT,//5 PRINT//6 }; typedef struct PeoInfo { //存放一个人的信息 char name[NAME_MAX]; char sex[SEX_MAX]; int age; char tele[TELE_MAX]; char addr[ADDR_MAX]; }PeoInfo; typedef struct Contact { PeoInfo data[MAX];//存放1000个人的信息 int sz;//记录通讯录中已经保存的信息个数 }Contact; //函数的声明 //初始化通讯录 void InitContact(Contact* pc); //增加联系人 void AddContact(Contact* pc); //打印通讯录 void PrintContact(const Contact* pc); //删除指定联系人 void DelContact(Contact* pc); //查找联系人 void SearchContact(const Contact* pc); //更改联系人 void ModifyContact(Contact* pc); //排列联系人 void SortContact(Contact* pc);
const.c文件
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" void InitContact(Contact* pc) { assert(pc); pc->sz = 0; memset(pc->data, 0, sizeof(pc->data)); } 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 PrintContact(const Contact* pc) { assert(pc); printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址"); int i = 0; 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); } } //查找函数,找到返回下标,找不到返回-1 int FindByName(const Contact* pc, char name[]) { assert(pc); int i = 0; for (i = 0; i < pc->sz; i++) { if (0 == strcmp(pc->data[i].name, name)) return i; } return -1; } void DelContact(Contact* pc) { assert(pc); if (pc->sz == 0) { printf("通讯录已空,无法删除\n"); return; } //1. 找到指定联系人 char name[NAME_MAX] = { 0 }; printf("请输入要删除人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要删除的人不存在\n"); return; } //删除 int j = 0; for (j = pos; j < pc->sz - 1; j++) { pc->data[j] = pc->data[j + 1]; } pc->sz--; printf("删除成功\n"); } void SearchContact(const Contact* pc) { assert(pc); if (pc->sz == 0) { printf("通讯录已空,无法查找\n"); return; } //1. 找到指定联系人 char name[NAME_MAX] = { 0 }; printf("请输入要查找人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要查找的人不存在\n"); return; } //找到了,打印 printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址"); printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } void ModifyContact(Contact* pc) { assert(pc); if (pc->sz == 0) { printf("通讯录已空,无法更改\n"); return; } //1. 找到指定联系人 char name[NAME_MAX] = { 0 }; printf("请输入要更改人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if (pos == -1) { printf("要更改的人不存在\n"); return; } //更改信息 printf("请输入名字:>"); scanf("%s", pc->data[pos].name); printf("请输入年龄:>"); scanf("%d", &(pc->data[pos].age)); printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("更改成功\n"); } int cmp_name(const void* e1, const void* e2) { assert(e1 && e2); return strcmp(((PeoInfo*)e1)->name, (((PeoInfo*)e2)->name)); } void SortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name); printf("排序成功\n"); }
test.c文件
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" void menu() { printf("********************************\n"); printf("***** 1.add 2.del ******\n"); printf("***** 3.search 4.modify ******\n"); printf("***** 5.sort 6.print ******\n"); printf("***** 0.exit ******\n"); printf("********************************\n"); } void test() { 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 SORT: SortContact(&con); break; case PRINT: PrintContact(&con); break; case 0: printf("退出通讯录\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while(input); } int main() { test(); return 0; }
结语
通讯录就写完了,所谓结束也是开始,之后也会分享更多干货的,敬请期待!!!