一 首言

学校布置的小作业希望对你有帮助,完整代码在文章结尾为方便阅读代码基本都有注释。代码是在满足老师要求下,尽量减少功能和代码方便同学理解的思想上完成的 (完成7个功能,功能性代码只有不到170行),所以各位看官多多包涵。

二 功能介绍

1 将所以联系人信息保存至文件中,程序接收到关闭指令后,自动保存数据至文件中再执行关闭

2 将文件中所以联系人信息读入程序,程序运行第一步自动将上次程序结束时的数据读入数组中,上次使用时保存的联系人及信息均存在。

3 新建联系人

4 按名字查找联系人

5 按名字删除联系人

6 按名字排序

7 将所以联系人打印至屏幕

结构介绍

下面是图解

首先创建了一个通讯录框架(结构体),里面可存姓名,性别,电话,地址。

再创建了一个通讯录文件夹(结构体),里面有一个数组,数组类型是通讯录框架(结构体)这样我们要将联系人数据保存,只要给数组中的元素通讯录框架(结构体)赋值相应内容即可及一个sz变量,用于提示我们通讯录数组实际存了几个人,及我们新建时应存入数组那个下标,程序刚开始sz为0数据从0下标依次存储,也方便访问,每次存储完成sz++.

使用

创建一个通讯录文件夹变量即可struct binbin,这样我们就创建了一个能存100个联系人的通讯录。

三 代码详解

主函数

int main(){int i = 0;//循环选择变量struct binbin mm;//创建通讯录init(&mm);//初始化通讯录do{printf("* * * *通 讯 录* * * *\n");printf("* * * * 1: 新建2: 排序* * * *\n");printf("* * *3: 查找4: 全显示 * * \n");printf("* * * * 5: 修改6: 删除* * * *\n");printf("* * * *0: 退出* * * *\n");printf("\n请输入需要的功能: \n");scanf("%d", &i);switch (i){case 1:add(&mm);//新建break;case 2:qos(&mm);//排序(按首字母)break;case 3:find(&mm);//查找break;case 4:show(&mm);//全显示break;case 5:modif(&mm);//修改break;case 6:del(&mm);//删除break;case 0: //退出程序seve(&mm);//把数据保存到文件夹中printf("已退出\n");break;default:printf("输入错误\n");break;}} while (i);//当i等于0结束循环return 0;}

主函数不解释,了直接看代码注释吧。只是有个打印提示操作和调用其他函数而已

程序初始化

不初始化会导致 sz 为随机数,导致出现大家都不想看到的事情发生。为避免咱赋0即可,因为咱存储从0下标开始

再将调用读取文件中数据函数将文件中数据导入到程序中

建议:建议读完1/2/3/4/5/6/7功能再回来读读1/2点

1.文件保存

直接看代码吧

void seve(struct binbin* mm)//用fprintf将数组在数据写入文件{int i = 0;//循环辅助变量FILE* pp = fopen("txun.txt", "w");//以"w"写的方式打开txun.txt文件,这是相对路径保存至工程文件下for (i = 0; i sz; i++)//把联系人信息循环写入文件中{fprintf(pp, "%-20s %-15s %-40s %-6s\n", mm->binge[i].name, mm->binge[i].gender,mm->binge[i].phone, mm->binge[i].site);//i是数组下标从,i从0开始直至通讯录最后一//个联系人下标结束}fclose(pp);//关闭文件pp = NULL;//不用了将指针置空(一个良好的习惯)}//结束

首先以”w”写的方式打开文件txun.txt(工程文件目录下查找这个文件名,没有会自动创建),并赋给pp

fprintf用法:和 printf 基本一致,只是多了一个文件指针变量(如上述代码中的文件指针pp),其余两个参数和printf一致,先写入变量类型,在写入变量名。

功能不同 如下是实际使用对比

2 读取文件中数据

直接看代码吧

void seveop(struct binbin* mm)//导入文件{int i = 0;FILE* pp = fopen("txun.txt", "r");//以"r"读取方式打开文件"txun.txt"if (NULL == pp)//如果文件打开失败会返回NULL{perror("fopen()");//如果打开失败perror打印错误return;//错误了就直接返回主函数}//fscanf把文件内容读入数组while (fscanf(pp, "%s%s%s%s", mm->binge[i].name, mm->binge[i].gender,mm->binge[i].phone, mm->binge[i].site) != EOF)//把联系人信息循环写入通讯录数组中{//文件内容是以EOF结束的,当等于EOF时结束录入i++;//数组下标加一mm->sz++;//通讯录人数加一}fclose(pp);//关闭文件pp = NULL;}

首先以”r”只读的方式打开文件txun.txt(工程文件目录下查找这个文件名,没有不会自动创建),并赋给pp

fscanf用法:scanf 基本一致,只是多了一个文件指针变量(如上述代码中的文件指针pp),其余两个参数和printf一致,先写入变量类型,在写入变量名。

功能不同 如下是实际使用对比

3 新建联系人

直接上代码

int add(struct binbin* mm)//新建增加成员{if (mm->sz == 100)//条件达成说明数组已经满了{printf("新建失败内存已满\n");return 0;}printf("正在新建请输入信息:\n");//下面的代码都是想新建联系人的结构体输入数据printf("请输入名字:\n");scanf("%s", mm->binge[mm->sz].name);//以sz为下标写入数据printf("请输入性别:\n");scanf("%s", mm->binge[mm->sz].gender);printf("请输入电话:\n");scanf("%s", mm->binge[mm->sz].phone);printf("请输入地址:\n");scanf("%s", mm->binge[mm->sz].site);mm->sz++;//增加了联系人,实际人数指示也得加一printf("联系人新建成功\n");return 0;}

首先咱新建前得先判断如果sz已经等于100了说明咱的数组已经满了,不能再新建了,直接返回结束新建函数。

如果没满,就可以往通讯录数组写入数据了,如上述代码向每个数据一一输入,输入完成sz++,下次新建直接存入新下标即可

四 按名字查找联系人

代码如下图

int find(const struct binbin* mm)//查找成员{int n = 0;//循环辅助char str[20] = { 0 };//定义一个大小为20的字符串strprintf("请输入要查找的的联系人姓名: \n");scanf("%s", str);while (n sz)//循环查找输入的联系人{//strcmp判断两字符串不同则返回大于0或小于0,相同则返回0if (strcmp(mm->binge[n].name, *str)== 0)//如果联系人中名字和输入的相同strcmp返回0,则进入if语句{printf("找到了联系人信息如下\n");//打印找到的联系人信息printf("\n联系人%d\n", n + 1);//打印找到的联系人信息printf("%-20s", mm->binge[n].name);//打印找到的联系人信息printf("%-15s", mm->binge[n].gender);//打印找到的联系人信息printf("%-40s", mm->binge[n].phone);//打印找到的联系人信息printf("%-6s\n\n", mm->binge[n].site);//打印找到的联系人信息return n; //把找到的联系人返回}n++;//每次不对n++}printf("没有此联系人\n\n\n");//出来了说明找完了都没找到return -1;//返回-1,因为数组下标没有-1,所以返回后其他函数能分辨是否找到}

先定义一个字符串,再将咱要找的联系人名字输入到该字符串中。用while遍历联系人过程中一一对比通讯录中联系人名字和输入名字是否相同。如果相同则打印被找到的联系人所以信息并返回其下标,如果while遍历完通讯录都没找到该联系人则打印 ”没有此联系人“ ,并返回-1,由于数组没有-1下标所以可以用于判断是否找到

注释:上述代码while (n sz),mm->sz是通讯录中实际人数,但数组下标从0开始所以n sz才能遍历完成

5 按名字删除联系人

代码如图

int del(struct binbin* mm)//删除{int n = 0;int tt = 0;n = find(mm);//删除先查找,没有就不用删if (n == -1)//没找着会返回-1{printf("删除失败\n");return 0;//没找到直接返回结束函数}printf("是否要删除联系人%s\n", mm->binge[n].name);printf("确认输入1取消输入2=>");//选择scanf("%d", &tt);if(tt == 1){mm->binge[n] = mm->binge[mm->sz - 1];//把最后一个联系人信息换到被删的这个数组下标mm->sz--;//把实际人数减减,就等于删除了printf("已删除完成\n");return 0;}printf("已取消\n");//选择了取消的情况return 0;//选择了取消的情况}

删除前需要先查找联系人所以先调用查找函数,查找函数查找完后返回该联系人下标,如没找到 if 判断接收返回值的变量 n 为 -1 时会直接返回结束函数

接收到要删除的联系人下标后,给用户一个选择确认删除则。将数组中最后一个元素的所以信息直接赋值到要删除的联系人下标(覆盖掉),再将 sz–即可。(咱覆盖之后数组中最后一个元素数据就可以删除了sz–即可)

取消删除就直接返回结束即可

6 按名字排序

直接上代码

void qos(struct binbin* mm)//选择排序{struct address ch;int i, j;int size = mm->sz;for ( i = 0; i < size - 1; i++)//循环每次找出最小的放到i下标{int samll = i;for ( j = i + 1; j 1,等于返回0,小于返回binge[j].name, mm->binge[i].name) binge[i];//交换i 下标与samll下标数据mm->binge[i] = mm->binge[samll];mm->binge[samll] = ch;}printf("排序完成\n");}

如上述代码,就是一个选择排序而已,对比的是联系人名字,每次循环找出最小的名字放到并将他和 i 下标交换。

7 将所有联系人信息打印至屏幕

直接上代码

void show(const struct binbin* mm)//全显示{int i ,b;printf("联系人如下\n");//向屏幕输出printf("%-20s","名字");printf("%-15s","性别");printf("%-40s","电话");printf("%-6s\n","地址"); b = mm->sz; i = 0;assert(mm);while (i binge[i].name);printf("%-15s", mm->binge[i].gender);printf("%-40s", mm->binge[i].phone);printf("%-6s\n", mm->binge[i].site);i++;}}

先打印一下数据表头,方便看下方数据是啥,然后直接while遍历整个通讯录并将所以联系人信息打印至屏幕即可。

四 所以代码

复制进编译器即可,VC6.0 / vs均可运行。建议分成 头文件,功能性代码,主函数三个模块。

//1 头文件#include#include#include#includestruct address//通讯录框架{char name[20];//名字char gender[6];//性别char phone[15];//电话char site[40];//地址};struct binbin//通讯录文件夹{//要想存200人就把100改为200,这是数组大小开大点用不完也没事struct address binge[100];//通讯录框架(这个通讯录最大能存100人)int sz;//实际存储人数指示};void init(struct binbin* mm);//初始化通讯录int add(struct binbin* mm); //新建void show(const struct binbin* mm);//全显示int find(const struct binbin* mm);//查找输入int modif( struct binbin* mm);//修改int del(struct binbin* mm);//删除void qos(struct binbin* mm);//排序void seve(struct binbin* mm);//把数据保存到文件夹中void seveop(struct binbin* mm);//初始化把数据从文件中拿出来// 2 功能性代码void seveop(struct binbin* mm)//导入文件{int i = 0;FILE* pp = fopen("txun.txt", "r");//以"r"读取方式打开文件"txun.txt"if (NULL == pp)//如果文件打开失败会返回NULL{perror("fopen()");//如果打开失败perror打印错误return;//错误了就直接返回主函数}//fscanf把文件内容读入数组while (fscanf(pp, "%s%s%s%s", mm->binge[i].name, mm->binge[i].gender,mm->binge[i].phone, mm->binge[i].site) != EOF)//把联系人信息循环写入通讯录数组中{//文件内容是以EOF结束的,当等于EOF时结束录入i++;//数组下标加一mm->sz++;//通讯录人数加一}fclose(pp);//关闭文件pp = NULL;}void init(struct binbin* mm)//初始化通讯录(程序执行的第一步){mm->sz = 0;//刚开始联系人没有seveop(mm);//这一行是数据导入(可删除,同时seveop函数也要删除)}int add(struct binbin* mm)//新建增加成员{if (mm->sz == 100)//条件达成说明数组已经满了{printf("新建失败内存已满\n");return 0;}printf("正在新建请输入信息:\n");//下面的代码都是想新建联系人的结构体输入数据printf("请输入名字:\n");scanf("%s", mm->binge[mm->sz].name);printf("请输入性别:\n");scanf("%s", mm->binge[mm->sz].gender);printf("请输入电话:\n");scanf("%s", mm->binge[mm->sz].phone);printf("请输入地址:\n");scanf("%s", mm->binge[mm->sz].site);mm->sz++;//怎加了联系人,实际人数指示也得加一printf("联系人新建成功\n");return 0;}void show(const struct binbin* mm)//全显示{int i ,b;printf("联系人如下\n");//向屏幕输出printf("%-20s","名字");printf("%-15s","性别");printf("%-40s","电话");printf("%-6s\n","地址"); b = mm->sz; i = 0;assert(mm);while (i binge[i].name);printf("%-15s", mm->binge[i].gender);printf("%-40s", mm->binge[i].phone);printf("%-6s\n", mm->binge[i].site);i++;}}int find(const struct binbin* mm)//查找成员{int n = 0;//循环辅助char str[20] = { 0 };//定义一个大小为20的字符串strprintf("请输入要查找的的联系人姓名: \n");scanf("%s", str);while (n sz)//循环查找输入的联系人{//strcmp判断两字符串不同则返回大于0或小于0,相同则返回0if (strcmp(mm->binge[n].name, *str)== 0)//如果联系人中名字和输入的相同strcmp返回0,则进入if语句{printf("找到了联系人信息如下\n");//打印找到的联系人信息printf("\n联系人%d\n", n + 1);//打印找到的联系人信息printf("%-20s", mm->binge[n].name);//打印找到的联系人信息printf("%-15s", mm->binge[n].gender);//打印找到的联系人信息printf("%-40s", mm->binge[n].phone);//打印找到的联系人信息printf("%-6s\n\n", mm->binge[n].site);//打印找到的联系人信息return n; //把找到的联系人返回}n++;//每次不对n++}printf("没有此联系人\n\n\n");//出来了说明找完了都没找到return -1;//返回-1,因为数组下标没有-1,所以返回后其他函数能分辨是否找到}int modif( struct binbin* mm)//修改{int n = 0;n = find(mm);//修改先查找,没有就不用改if (n == -1)//没找着会返回-1{printf("修改失败\n");return 0;//没找到直接返回结束函数}printf("请重新输入联系人信息:\n");//重新输入被修改联系人信息printf("请输入名字:");scanf("%s", mm->binge[n].name);//重新输入被修改联系人信息printf("请输入性别:");scanf("%s", mm->binge[n].gender);//重新输入被修改联系人信息printf("请输入电话:");scanf("%s", mm->binge[n].phone);//重新输入被修改联系人信息printf("请输入地址:");scanf("%s", mm->binge[n].site);printf("联系人修改成功");return 0;}int del(struct binbin* mm)//删除{int n = 0;int tt = 0;n = find(mm);//删除先查找,没有就不用删if (n == -1)//没找着会返回-1{printf("删除失败\n");return 0;//没找到直接返回结束函数}printf("是否要删除联系人%s\n", mm->binge[n].name);printf("确认输入1取消输入2=>");//选择scanf("%d", &tt);if(tt == 1){mm->binge[n] = mm->binge[mm->sz - 1];//把最后一个联系人信息换到被删的这个数组下标mm->sz--;//把实际人数减减,就等于删除了printf("已删除完成\n");return 0;}printf("已取消\n");//选择了取消的情况return 0;//选择了取消的情况}void qos(struct binbin* mm)//选择排序{struct address ch;int i, j;int size = mm->sz;for ( i = 0; i < size - 1; i++)//循环每次找出最小的放到i下标{int samll = i;for ( j = i + 1; j 1,等于返回0,小于返回binge[j].name, mm->binge[i].name) binge[i];//交换i 下标与samll下标数据mm->binge[i] = mm->binge[samll];mm->binge[samll] = ch;}printf("排序完成\n");}void seve(struct binbin* mm)//fprintf写入{int i = 0;FILE* pp = fopen("txun.txt", "w");//写的方式打开txun.txt文件,这是相对路径保存至工程文件下for (i = 0; i sz; i++)//把联系人信息循环写入文件中{fprintf(pp, "%-20s %-15s %-40s %-6s\n", mm->binge[i].name, mm->binge[i].gender,mm->binge[i].phone, mm->binge[i].site);}fclose(pp);//关闭文件pp = NULL;}//结束//主函数//#include"t_x_l.h"//双引号是自己创建的头文件,t_x_l.h包含了通讯录所用的函数int main(){int i = 0;//循环选择变量struct binbin mm;//创建通讯录init(&mm);//初始化通讯录do{printf("* * * *通 讯 录* * * *\n");printf("* * * * 1: 新建2: 排序* * * *\n");printf("* * *3: 查找4: 全显示 * * \n");printf("* * * * 5: 修改6: 删除* * * *\n");printf("* * * *0: 退出* * * *\n");printf("\n请输入需要的功能: \n");scanf("%d", &i);switch (i){case 1:add(&mm);//新建break;case 2:qos(&mm);//排序(按首字母)break;case 3:find(&mm);//查找break;case 4:show(&mm);//全显示break;case 5:modif(&mm);//修改break;case 6:del(&mm);//删除break;case 0: //退出程序seve(&mm);//把数据保存到文件夹中printf("已退出\n");break;default:printf("输入错误\n");break;}} while (i);//当i等于0结束循环return 0;}