1、通讯录文档方案:
2、通讯录模块化
当我们写代码,代码量大的时候,我们要尽量将其模块化,写一部分调试一部分,防止最后代码bug过多。
3、测试模块的框架
代码:
//自定义菜单的实现 void menu() { //暂停,按任意键继续 system("pause"); //在每次重新打印菜单的时候清屏 system("cls"); printf("**********************************************\n"); printf("******** 1. add 2.del ********\n"); printf("******** 3.search 4.madify ********\n"); printf("******** 5.show 6.sort ********\n"); printf("******** 0.exit ********\n"); printf("**********************************************\n"); } int main() { //设置背景色和文字颜色 system("color 81"); int input = 0; //重复使用通讯录,并可通过菜单选择功能 do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 0: printf("退出通讯录\n"); break; default: printf("选择错误\n"); } } while (input); return 0; }
4、现在我们对通讯录的函数实现和函数声明进行讲解并将其组装测试
(1)通讯录的函数声明——contact.h
(2)通讯录的函数实现——contact.c
代码1:contact.h
//常用的库函数头文件 #include<stdlib.h> #include<stdio.h> #include<string.h> #include<assert.h> //常量被重复使用(或对其更改)——使用define #define MAX 100 #define NAME_MAX 20 #define SEX_MAX 5 #define ADDR_MAX 30 #define TELE_MAX 12 //类型的声明一般放在头文件中 //人的信息 typedef struct PeoInfo { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char addr[ADDR_MAX];//地址 char tele[TELE_MAX];//电话 }PeoInfo; //通讯录(要知道已经存放了几个人才好添加,查看,修改等) typedef struct Contact { PeoInfo data[MAX];//存入人的信息 int sz;//当前已存放的信息的个数 }Contact; //初始化通讯录 void InitContact(Contact* pc); //添加通讯录的信息 void AddContact(Contact* pc); //显示通讯录的信息 void ShowContact(const Contact* pc); //删除指定联系人 void DelContact(Contact* pc); //查看指定联系人的信息 void SearchContact(const Contact* pc); //修改指定联系人 void MadifyContact(Contact* pc); //使用冒泡排序的思想模拟qsort函数排序 void BubbleSortContact(void* pc,size_t sz, size_t width, int(*Cmp)(const void* e1,const void* e2));
代码2:contact.c
#include"contact.h" //初始化通讯录 void InitContact(Contact* pc) { assert(pc);//断言指针的有效性 pc->sz = 0;//初始化通讯录信息的个数为0 memset(pc->data, 0, sizeof(pc->data));//清零,初始化通讯录信息为0 } //添加通讯录的信息 void AddContact(Contact* pc) { assert(pc);//断言指针的有效性 if (MAX == pc->sz) { 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].addr); printf("请输入电话:>"); scanf("%s", pc->data[pc->sz].tele); pc->sz++;//添加一个人信息,信息个数+1 printf("添加成功\n"); } //显示通讯录的信息 void ShowContact(const Contact* pc)//只是显示通讯录,不改变信息,使用const使代码更健壮 { assert(pc);//断言指针的有效性 //打印表头 printf("%-20s\t%-3s\t%-5s\t%-30s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); //打印通讯录的信息 int i = 0; for (i = 0; i < pc->sz; i++) { printf("%-20s\t%-3d\t%-5s\t%-30s\t%-12s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele); } } //查找(删除、查看、修改都使用到了查找,所以封装成一个函数) int FindByName(const Contact* pc,const char name[]) { assert(pc);//断言指针的有效性 //遍历通讯录已有的信息,找到返回该位置的下标,没找到返回-1 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) { //断言指针的有效性 assert(pc); //判断通讯录是否存在信息,不存在直接提示后退出 if (0 == pc->sz) { printf("通讯录为空,无法删除\n"); return; } //删除 //①找到要删除的人,找不到则提示并退出 char name[NAME_MAX]; printf("请输入要删除的人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if(-1 == pos) { printf("要删除的人不存在\n"); return; } //②删除 int i = 0; for (i = pos; i < pc->sz - 1; i++) { pc->data[i] = pc->data[i + 1];//后面的信息覆盖前面的信息,即删除 } pc->sz--;//删除一个人信息,信息个数-1 printf("删除成功\n"); } //查看指定联系人的信息 void SearchContact(const Contact* pc) { assert(pc);//断言指针的有效性 //查找要查看的联系人,找不到则提示并退出 char name[NAME_MAX]; printf("请输入要查找的人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if (-1 == pos) { printf("要查找的人不存在\n"); return; } //打印消息 printf("%-20s\t%-3s\t%-5s\t%-30s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); printf("%-20s\t%-3d\t%-5s\t%-30s\t%-12s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].addr, pc->data[pos].tele); printf("查看成功\n"); } //修改指定联系人 void MadifyContact(Contact* pc) { //断言指针的有效性 assert(pc); //查找要修改的人,找不到则提示并退出 char name[NAME_MAX]; printf("请输入要修改的人的名字:>"); scanf("%s", name); int pos = FindByName(pc, name); if (-1 == pos) { 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].addr); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("修改成功\n"); } //实现对任意类型数据的交换 void Swap(char* buf1, char* buf2, size_t width) { //断言指针的有效性 assert(buf1 && buf2); //一个字节一个字节的交换 size_t i = 0; for (i = 0; i < width; i++) { char tmp = *buf1; *buf1 = *buf2; *buf2 = tmp; buf1++; buf2++; } } //使用冒泡排序的思想模拟qsort函数排序 void BubbleSortContact(void* base, size_t sz,size_t width,int(*Cmp)(const void* e1, const void* e2)) { //断言指针的有效性 assert(base && Cmp); //判断通讯录是否存在信息,不存在直接提示后退出 if (0 == sz) { printf("通讯录为空,无法排序\n"); return; } //趟数 size_t i = 0; for (i = 0; i < sz - 1; i++) { //一趟冒泡排序的过程 size_t j = 0; for (j = 0; j < sz - 1 - i; j++) { //调用cmp指向的比较函数 if (Cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) { //交换 //元素类型不知道,我们一个字节一个字节的交换,所以传参时也要传width Swap((char*)base + j * width, (char*)base + (j + 1) * width, width); } } } }
代码3:test.c——组装,测试
#include"contact.h" //自定义菜单的实现 void menu() { //暂停,按任意键继续 system("pause"); //在每次重新打印菜单的时候清屏 system("cls"); printf("**********************************************\n"); printf("******** 1. add 2.del ********\n"); printf("******** 3.search 4.madify ********\n"); printf("******** 5.show 6.sort ********\n"); printf("******** 0.exit ********\n"); printf("**********************************************\n"); } //比较结构体,复杂对象,我们要按照具体的方式比较 //如:按照联系人的年龄来排序 int Cmp(const void* e1, const void* e2) { return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age; } int main() { //设置背景色和文字颜色 system("color 81"); int input = 0; //创建通讯录 Contact con; //初始化通讯录(可以自己选择初始化什么内容) InitContact(&con); //重复使用通讯录,并可通过菜单选择功能 do { //打印菜单 menu(); printf("请选择:>"); scanf("%d", &input); //选择功能 switch (input) { case 1: //添加联系人 AddContact(&con); break; case 2: //删除指定联系人 DelContact(&con); break; case 3: //查看指定联系人的信息 SearchContact(&con); break; case 4: //修改指定联系人 MadifyContact(&con); break; case 5: //显示所有联系人 ShowContact(&con); break; case 6: //使用冒泡排序模拟qsort函数,可以排序任意类型 BubbleSortContact(con.data,con.sz,sizeof(con.data[0]), Cmp); break; case 0: printf("退出通讯录\n"); break; default: printf("选择错误\n"); } } while (input); return 0; }
这个通讯录就完成了,有不完善的是作者现在水平还不到,后期有机会会继续将其完善。