通讯录的进阶

来源:互联网 发布:淘宝买家信用怎么升级 编辑:程序博客网 时间:2024/06/05 06:05

上一篇博客,写了通讯录的简单版本,虽然需要的功能基本都有,但是仍然存在许多问题:

1.当通讯录的实际人数只有几十个时,开辟500个人的信息的内存,显然会浪费,当通讯录人数多于500时,没有足够的内存去存储这么多人的信息;

2.当程序退出时,输入的信息无法保存下来,程序再次打开时,原先输入的数据已经没有了。

鉴于以上两点,对程序进行了改进:一方面,使用malloc,realloc,free等函数动态开辟内存,当人数增加时,可以动态增加内存;另一方面,使用fread,fwritefopen,fclose等函数,在程序退出时将数据写入文件中进行保存,当程序再次打开时,可以将文件中的数据加载到程序中。

在功能上,与上一版一致,包括联系人的添加,删除,修改,查找,展示,排序,清空及退出。

头文件contact.h

#ifndef __CONTACT_H__ #define __CONTACT_H__ #include <stdio.h>#include <string.h>  #include <assert.h>#include <stdlib.h>#define NAME_MAX 20//姓名能占用的最大空间#define SEX_MAX 5//性别#define ADDR_MAX 30//地址#define TELE_MAX 12 //电话#define DEFAULT_SZ 3 //默认容量#define DEFAULT_ADD 2//增容增加的容量#define FILENAME "contact.dat"//文件名称typedef struct PeoInfo{char name[NAME_MAX];int age;char sex[SEX_MAX];char addr[ADDR_MAX];char tele[TELE_MAX];}PeoInfo;//struct PeoInfo a; <=> PeoInfo a;typedef struct Contact{PeoInfo* data;//数据存储区域int sz;//有效元素个数int capacity;//当前容量}Contact, *pContact;//函数声明void InitContact(pContact pcon);//初始化void AddContact(pContact pcon);//添加void ShowContact(const pContact pcon);//浏览void DelContact(pContact pcon);//删除void SearchContact(pContact pcon);//查找void ModifyContact(pContact pcon);//修改void SortContach(pContact pcon);//排序void ClearContact(pContact pcon);//清空void DestroyContact(pContact pcon);//释放动态内存void SaveContactData(pContact pcon);//保存数据,写入文件void LoadContactData(pContact pcon);//加载信息#endif

源文件contact.c

#include "contact.h"void InitContact(pContact pcon)//开辟动态内存并初始化{pcon->sz = 0;pcon->data = malloc(DEFAULT_SZ*sizeof(PeoInfo));if (pcon->data == NULL){perror("use malloc");exit(EXIT_FAILURE);}memset(pcon->data, 0, DEFAULT_SZ*sizeof(PeoInfo));pcon->capacity = DEFAULT_SZ;LoadContactData(pcon);}static void CheckCapacity(pContact pcon)//检查是否需要增容,static修饰的函数只能在本文件中使用{if (pcon->sz == pcon->capacity){//增容PeoInfo* ptr = realloc(pcon->data, (pcon->capacity + DEFAULT_ADD)*sizeof(PeoInfo));if (ptr == NULL){perror("use realloc");exit(EXIT_FAILURE);//失败退出}elsepcon->data = ptr;pcon->capacity += DEFAULT_ADD;//printf("增容成功\n");}}void AddContact(pContact pcon)//添加{assert(pcon);//断言,用于检验是否为NULL,便于调试,             //若函数错误的接受了一个NULL参数,程序就会停止,并打印出提示信息; //若表达式为真(非零),它不会打印任何东西,程序继续执行。CheckCapacity(pcon);printf("请输入名字:> ");scanf("%s", pcon->data[pcon->sz].name);printf("请输入年龄:> ");scanf("%d", &pcon->data[pcon->sz].age);printf("请输入性别:> ");scanf("%s", pcon->data[pcon->sz].sex);printf("请输入地址:> ");scanf("%s", pcon->data[pcon->sz].addr);printf("请输入电话:> ");scanf("%s", pcon->data[pcon->sz].tele);pcon->sz++;printf("\n添加成功!\n");}void ShowContact(const pContact pcon)//浏览所有联系人{int i = 0;assert(pcon);printf("%8s\t%8s\t%8s\t%8s\t%8s\n", "name", "age", "sex", "addr", "tele");for (i = 0; i < pcon->sz; i++){printf("%8s\t", pcon->data[i].name);printf("%8d\t", pcon->data[i].age);printf("%8s\t", pcon->data[i].sex);printf("%8s\t", pcon->data[i].addr);printf("%8s\n", pcon->data[i].tele);}}static int find(pContact pcon,char *name1)//查找函数,如果找到返回联系人所在的排名,否则返回-1{int i = 0;assert(pcon);assert(name1);for (i = 0; i < pcon->sz; i++){if (strcmp(pcon->data[i].name, name1) == 0){return i;}}return -1;}void DelContact(pContact pcon)//删除{int find_name;int i = 0;char name1[NAME_MAX];assert(pcon);printf("请输入删除的人姓名:> ");scanf("%s", name1);find_name = find(pcon, name1);if (find_name != -1){for (i = find_name; i < pcon->sz; i++)pcon->data[i] = pcon->data[i + 1];//后一个人信息覆盖到前一个pcon->sz--;printf("删除成功\n");}}void SearchContact(pContact pcon)//查找联系人{int ret = 0;int find_name = 0;char name1[NAME_MAX];assert(pcon);do{printf("请输入要查找的人名字:> ");scanf("%s", name1);find_name = find(pcon, name1);if (find_name != -1){printf("\n");printf("姓名:%s\n", pcon->data[find_name].name);printf("年龄:%d\n", pcon->data[find_name].age);printf("性别:%s\n", pcon->data[find_name].sex);printf("地址:%s\n", pcon->data[find_name].addr);printf("电话:%s\n", pcon->data[find_name].tele);}elseprintf("没有找到此人\n");printf("是否继续,继续查找请选择1,结束查找请选择0:> ");scanf("%d", &ret);while (ret != 0 && ret != 1){printf("选择错误!请重新选择:> ");scanf("%d", &ret);}} while (ret);}void ModifyContact(pContact pcon)//修改信息{int ret = 0;int find_name = 0;char name1[NAME_MAX];assert(pcon);do{printf("请输入要修改的人名字:> ");scanf("%s", name1);find_name = find(pcon, name1);if (find_name != -1){printf("\n");printf("请输入修改后的姓名:");scanf("%s", pcon->data[find_name].name);printf("请输入修改后的年龄:");scanf("%d", &pcon->data[find_name].age);printf("请输入修改后的性别:");scanf("%s", pcon->data[find_name].sex);printf("请输入修改后的地址:");scanf("%s", pcon->data[find_name].addr);printf("请输入修改后的电话:");scanf("%s", pcon->data[find_name].tele);}elseprintf("没有找到此人\n");printf("是否继续,继续修改请选择1,结束修改请选择0:> ");scanf("%d", &ret);while (ret != 0 && ret != 1){printf("选择错误!请重新选择:> ");scanf("%d", &ret);}} while (ret);}void SortContach(pContact pcon)//对联系人按姓名排序{int i = 0;int j = 0;assert(pcon);printf("姓名从A-Z的顺序为:\n");for (i = 0; i < pcon->sz; i++){for (j = 0; j < pcon->sz - i - 1; j++){if (strcmp(pcon->data[j].name, pcon->data[j + 1].name)>0){PeoInfo tmp;tmp = pcon->data[j];pcon->data[j] = pcon->data[j + 1];pcon->data[j + 1] = tmp;}}}ShowContact(pcon);}void ClearContact(pContact pcon)//清空联系人{int ret = 0;assert(pcon);printf("确定清空?确定选择1,取消选择0:) ");scanf("%d", &ret);if (ret == 1){pcon->sz = 0;//没有显示memset(pcon->data, 0, sizeof(pcon->data));printf("删除成功\n");}while (ret != 0 && ret != 1){printf("选择错误!请重新选择:) ");scanf("%d", &ret);}}void DestroyContact(pContact pcon)//释放动态内存{free(pcon->data);pcon->data = NULL;pcon->capacity = 0;pcon->sz = 0;}void SaveContactData(pContact pcon)//保存数据写入文件{FILE* pfout = fopen(FILENAME, "w");int i = 0;if (pfout == NULL){perror("SaveContactData::fopen");//报错exit(EXIT_FAILURE);}for (i = 0; i < pcon->sz; i++){fwrite(pcon->data + i, sizeof(PeoInfo), 1, pfout);}fclose(pfout);}void LoadContactData(pContact pcon)//加载文件中的数据{FILE* pfin = fopen(FILENAME, "r");PeoInfo tmp = { 0 };if (pfin == NULL){perror("LoadContactData::fopen");exit(EXIT_FAILURE);}while (fread(&tmp, sizeof(PeoInfo), 1, pfin)){CheckCapacity(pcon);pcon->data[pcon->sz] = tmp;pcon->sz++;}fclose(pfin);}

测试函数test.c

#define _CRT_SECURE_NO_WARNINGS#include "contact.h"void menu()//菜单{printf("\n");printf("******************************************\n");printf("***********1.添加       2.浏览  **********\n");printf("***********3.删除       4.查找  **********\n");printf("***********5.修改       6.排序  **********\n");printf("***********7.清空       0.退出  **********\n");printf("******************************************\n");}enum//枚举{EXIT,//0.退出ADD,//1.添加SHOW,//2.浏览DEL,//3.删除SEARCH,//4.查找MODIFY,//5.修改SORT,//6.排序CLEAR,//7.清空};void test(){int input = 0;Contact my_con;InitContact(&my_con);do{menu();printf("\n请输入你的选择:> ");scanf("%d", &input);switch (input){case ADD://添加联系人AddContact(&my_con);break;case SHOW://浏览联系人ShowContact(&my_con);break;case DEL://删除联系人DelContact(&my_con);break;case SEARCH://查找联系人SearchContact(&my_con);break;case MODIFY://修改联系人ModifyContact(&my_con);break;case SORT://按姓名排序联系人SortContach(&my_con);break;case CLEAR://清空联系人ClearContact(&my_con);break;case EXIT://退出,写入信息到文件,并释放开辟的动态内存SaveContactData(&my_con);DestroyContact(&my_con);break;}} while (input);}int main(){test();return 0;}
阅读全文
2 0