1.进阶通讯录特点(下)
①基本的增删查改功能;
②通讯录的空间不固定,大小可以调整;
③通过C语言文件操作来储存通讯录信息到硬盘上;
2.实现步骤
基本实现步骤同上、中两篇 【[C语言]通讯录实现(中) - CSDN App】http://t.csdnimg.cn/K5tqO
【【C语言】通讯录实现(上) - CSDN App】http://t.csdnimg.cn/ZrZQk
此外还有文件加载、写入、关闭等实现如下:
(1)保存增加的联系人数据到文件中
void SaveContact(Contact* pc)//保存联系人到文件中 { FILE* pf = fopen("contact.dat", "wb");//打开文件 if (pf == NULL)//判断指针是否为空 { perror("SaveContact"); return; } //写数据 int i = 0; for (i = 0; i < pc->sz; i++) { fwrite(pc->data+i, sizeof(PeoInfo), 1, pf);//一回写一个大小为PeoInfo的文件 //从pc->data+i的位置开始读写到文件中 } //关闭文件 fclose(pf); pf = NULL; }
运行后得到一个contact.dat的文件用记事本打开如图:
因为fopen函数的打开方式为“wb”,二进制写入模式所以打开该文件是一堆乱码
如上图所示生成了contact.dat文件
(2)加载保存的联系人数据
void LoadContact(Contact* pc)//加载已保存的联系人数据 { //打开文件 FILE* pf = fopen("contact.dat", "rb"); //以二进制形式读文件 PeoInfo tmp = { 0 };//创建一个变量来存放读到的数据 while (fread(&tmp, sizeof(PeoInfo), 1, pf))//while循环一直读到文件末尾没有数据为止 { if (CheckCapacity(pc) == 0) //要先检查当前通讯录容量是否够存放保存的联系人 { printf("无法加载联系人哦~\n"); //CheckCapacity为0时表示无法增容可能没办法开辟空间 return; } pc->data[pc->sz] = tmp; //将保存的联系人写入当前通讯录 pc->sz++; //写入一个sz通讯录联系人数量加一和增加联系人函数一样 } printf("已保存的联系人加载成功啦~\n"); return; }
3.完整C语言通讯录代码
(1)contact.h
#pragma once //定义的的头文件contact.h #include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #define MAX 100 #define MAX_NAME 20 #define MAX_SEX 5 #define MAX_TELE 12 #define MAX_ADDR 30 #define DEFAULT_SZ 3 #define INT_SZ 2 enum OPTION//用枚举来定义变量 { EXIT,//0 ADD,//1 DEL,//2... SEARCH, MODIFY, SHOW, SORT }; //声明类型 typedef struct PeoInfo //创建一个结构体来储存联系人相关信息 { char name[MAX_NAME]; char sex[MAX_SEX]; char tele[MAX_TELE]; char addr[MAX_ADDR]; int age; }PeoInfo; //通讯录 typedef struct Contact { PeoInfo* data;//创建一个PeoInfo指针来指向存放数据的空间 int sz;//用来记录联系人的个数 int capacity;//记录通讯录当前最大容量 }Contact; //函数声明 void InitContact(Contact* pc); void AddContact(Contact* pc); void ShowContact(const Contact* pc); void DelContact(Contact* pc); void SearchContact(const Contact* pc); void DestroyContact(Contact* pc); void SaveContact(Contact* pc); void LoadContact(Contact* pc);//加载已保存的联系人数据
(2)test.c
#define _CRT_SECURE_NO_WARNINGS 1 //test.c文件--流程 #include"contact.h" void menu()//菜单 { printf("*******Contact******\n"); printf("*** 1.ADD 2.DEL ***\n"); printf("***** 3.SEARCH *****\n"); printf("***** 4.MODIFY *****\n"); printf("** 5.SHOE 6.SORT **\n"); printf("****** 0.EXIT ******\n"); } int main()//主函数 { int sec = 1; Contact con; InitContact(&con);//初始化通讯录 LoadContact(&con); while (sec) { menu(); scanf("%d", &sec); switch (sec)//选择不同的功能 { case EXIT://退出 SaveContact(&con); DestroyContact(&con); printf("您已退出\n"); break; case ADD://加 AddContact(&con); break; case DEL://删 DelContact(&con); break; case SEARCH://查 SearchContact(&con); break; case MODIFY://改 break; case SHOW://显示 ShowContact(&con); break; case SORT://分类 break; default: printf("选择错误,请重新输入\n"); } printf("\n"); } return 0; }
(3)contact.c
#define _CRT_SECURE_NO_WARNINGS 1 //contact函数实现contact.c源文件 #include"contact.h" int CheckCapacity(Contact* pc); void LoadContact(Contact* pc)//加载已保存的联系人数据 { //打开文件 FILE* pf = fopen("contact.dat", "rb"); //读文件 PeoInfo tmp = { 0 }; while (fread(&tmp, sizeof(PeoInfo), 1, pf)) { if (CheckCapacity(pc) == 0) { printf("无法加载联系人哦~\n"); return; } pc->data[pc->sz] = tmp; pc->sz++; } printf("已保存的联系人加载成功啦~\n"); return; } int Search_by_name(const Contact* pc)//查找函数 { char name[MAX_NAME] = { 0 }; scanf("%s",name); int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } void InitContact(Contact* pc) //初始化通讯录函数 { //memset(pc->data, 0, sizeof(pc->data));//静态版本 assert(pc); pc->data = malloc(DEFAULT_SZ * sizeof(PeoInfo));//开辟空间 if (pc->data == NULL)//判断指针是否为空 { perror("InitContact"); return; } pc->capacity = DEFAULT_SZ;//使用了宏定义DEFAULT_SZ=3容量 pc->sz = 0; } int CheckCapacity(Contact* pc)//增容函数 加联系人时如果空间不够就增容 { if (pc->sz == pc->capacity) { PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INT_SZ)*sizeof(PeoInfo)); //如果容量满了用realloc函数增容,INT_SZ宏定义为2 if (ptr == NULL) { perror("CheckCapacity"); return 0; } else { pc->data = ptr;//将增容后的指针赋给pc->data pc->capacity += INT_SZ;//capacity相应增加 printf("增容成功\n"); } return 1; } return 1; } void AddContact(Contact* pc)//增加联系人 { assert(pc); /*if (pc->sz == MAX) { printf("联系人已满\n"); return; }*/ if (0 == CheckCapacity(pc)) { printf("无法增容哦~\n"); return; } printf("请输入要添加的联系人名字、性别、年龄、电话、地址:\n"); scanf("%s %s %d %s %s",pc->data[pc->sz].name, pc->data[pc->sz].sex,&pc->data[pc->sz].age, pc->data[pc->sz].tele,pc->data[pc->sz].addr); printf("您已经成功添加%s\n", pc->data[pc->sz].name); pc->sz++; return; } void ShowContact(const Contact* pc)//显示联系人 { assert(pc); if (pc->sz == 0) { printf("您还未添加联系人哦~快选择1去添加吧~\n"); return; } int i = 0; printf("%-10s\t%-5s\t%-5s\t%-15s\t%-30s\t\n", "名字", "性别", "年龄", "电话", "住址"); for (i = 0; i < pc->sz; i++) { printf("%-10s\t%-5s\t%-5d\t%-15s\t%-30s\t\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } return; } void DelContact(Contact* pc)//删除联系人 { assert(pc); if (pc->sz == 0) { printf("您还没有加联系人哦~快选择1去添加吧~\n"); return; } printf("请输入要删除的联系人的名字:\n"); int flag = Search_by_name(pc); if (flag == -1) { printf("没有找到该联系人哦~\n"); return; } int j = 0; for (j = flag; j < pc->sz - 1; j++) { pc->data[j] = pc->data[j + 1]; } printf("您已经成功删除该联系人\n"); pc->sz--; return; } void SearchContact(const Contact* pc)//查找联系人并打印 { printf("请输入要查找的联系人的名字:\n"); int i = Search_by_name(pc); if (i == -1) { printf("没有找到该联系人哦~\n"); return; } else { printf("%-10s\t%-5s\t%-5d\t%-15s\t%-30s\t\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } return; } //释放空间 void DestroyContact(Contact* pc) { free(pc->data); pc->data = NULL; pc->capacity = 0; pc->sz = 0; } void SaveContact(Contact* pc)//保存增加的联系人到文件中 { FILE* pf = fopen("contact.dat", "wb");//打开文件 if (pf == NULL)//判断指针是否为空 { perror("SaveContact"); return; } //写数据 int i = 0; for (i = 0; i < pc->sz; i++) { fwrite(pc->data+i, sizeof(PeoInfo), 1, pf);//一回写一个大小为PeoInfo的文件 //从pc->data+i的位置开始读写到文件中 } //关闭文件 fclose(pf); pf = NULL; }
4.结语
三版通讯录循序渐进,从最开始的定容增删查改等功能的实现(上篇),到可以不定容的通讯录(中篇),最后到可以保存数据到文件并从文件中加载保存的联系人(下篇),我们不仅学会了一些基本函数的写法,还学了动态内存函数malloc,realloc等函数的用法,并熟悉了c语言文件的基本操作。