在前面的文章中,我介绍了通讯录的静态版本和动态版本,现在我来介绍通讯录的文件版本,注意这里通讯录的文件版本是建立在动态版本通讯录的基础上的,所以还不知道动态版本的通讯录请前往前面文章观看学习。
在这里,我只列出与动态版本不同的地方,通讯录依然包括test.c和contact.c和contact.h的三个文档,另外在项目文件夹还要有个data.txt文档存放着通讯录的信息。
初始化函数
void InitBoard(struct contact* pc)
{
assert(pc != NULL);
pc->data = (struct people*)malloc(sizeof(struct people) * DEFAULT_INT);
if(pc->data == NULL)
{
perror("InitBoard()");
}
pc->capacity = DEFAULT_INT;
pc->sz = 0;
//读取文件夹的通讯录信息
LoadContact(pc);
}
读取文件夹的联系人的信息的函数
static int Check_Capacity(struct contact* pc); //检查通讯录是否满了的函数声明
void LoadContact(struct contact* pc)
{
struct people tmp = {0};
//打开文件
FILE* pfR = fopen("data.txt","rb");
assert(pc != NULL);
if(pfR == NULL)
{
perror("LoadContact::fopen");
}
//读文件
while(fread(&tmp,sizeof(struct people),1,pfR))
{
//检验内存是否满了
Check_Capacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pfR);
pfR = NULL;
}
保存通讯录信息到文件夹的函数
void SaveContact(struct contact* pc)
{
int i = 0;
//打开文件
FILE* pfw = fopen("data.txt","wb");
assert(pc != NULL);
if(pfw == NULL)
{
perror("SaveContact::fopen");
}
//写文件
for(i=0;i<pc->sz;i++)
{
fwrite(pc->data+i,sizeof(struct people),1,pfw);
}
//关闭文件
fclose(pfw);
pfw = NULL;
}
contact.c文档代码
#include"contact.h"
static int Check_Capacity(struct contact* pc); //检查通讯录是否满了的函数声明
void LoadContact(struct contact* pc)
{
struct people tmp = {0};
//打开文件
FILE* pfR = fopen("data.txt","rb");
assert(pc != NULL);
if(pfR == NULL)
{
perror("LoadContact::fopen");
}
//读文件
while(fread(&tmp,sizeof(struct people),1,pfR))
{
//检验内存是否满了
Check_Capacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pfR);
pfR = NULL;
}
void InitBoard(struct contact* pc)
{
assert(pc != NULL);
pc->data = (struct people*)malloc(sizeof(struct people) * DEFAULT_INT);
if(pc->data == NULL)
{
perror("InitBoard()");
}
pc->capacity = DEFAULT_INT;
pc->sz = 0;
//读取文件夹的通讯录信息
LoadContact(pc);
}
static int Check_Capacity(struct contact* pc) //检查通讯录是否满了。满了就增容
{
assert(pc != NULL);
if(pc->sz == pc->capacity)
{
pc->data = (struct people*)realloc(pc->data,sizeof(struct people) * (pc->capacity + INT_SZ));
if(pc->data == NULL)
{
perror("Check_Capacity()");
return 0;
}
pc->capacity += INT_SZ;
printf("增容成功\n");
return 1;
}
else
{
return 1;
}
}
void DestroyContact(struct contact* pc)
{
assert(pc != NULL);
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
void Addcontact(struct contact* pc)
{
assert(pc != NULL);
if(0 == Check_Capacity(pc))
{
return;
}
else
{
printf("请输入想要添加联系人的名字:>");
scanf("%s",pc->data[pc->sz].name);
printf("请输入该联系人的性别:>");
scanf("%s",pc->data[pc->sz].sex);
printf("请输入该联系人的地址:>");
scanf("%s",&pc->data[pc->sz].addr);
printf("请输入该联系人的电话:>");
scanf("%s",&pc->data[pc->sz].tele);
printf("请输入该联系人的年龄:>");
scanf("%d",&(pc->data[pc->sz].age));
pc->sz++;
printf("添加联系人成功\n");
}
}
int Findpeople(struct contact* pc,char name[])
{
int i = 0;
assert(pc != NULL);
for(i=0;i<pc->sz;i++)
{
if(strcmp(pc->data[i].name,name) == 0)
{
return i;
}
}
return -1;
}
void Delcontact(struct contact* pc)
{
char name[nameMax];
int ret = 0;
int i = 0;
assert(pc != NULL);
printf("请输入想要删除的联系人:>");
scanf("%s",name);
ret = Findpeople(pc,name);
if(ret == -1)
{
printf("找不到该联系人\n");
}
else
{
for(i=ret;i<pc->sz-1;i++)
{
pc->data[i] = pc->data[i+1];
}
pc->sz--;
printf("删除该联系人成功\n");
}
}
void SearchContact(struct contact* pc)
{
char name[nameMax];
int ret = 0;
assert(pc != NULL);
printf("请输入想要联系人的名字:>");
scanf("%s",&name);
ret = Findpeople(pc,name);
if(ret == -1)
{
printf("找不到该联系人\n");
}
else
{
printf("%-20s\t%-4s\t%-30s\t%-12s\t%-5s\t\n","名字","性别","地址","电话","年龄");
printf("%-20s\t%-4s\t%-30s\t%-12s\t%-5d\t\n",pc->data[ret].name,
pc->data[ret].sex,
pc->data[ret].addr,
pc->data[ret].tele,
pc->data[ret].age);
}
}
void ModifyContact(struct contact* pc)
{
char name[nameMax];
int ret = 0;
assert(pc != NULL);
printf("请输入你要修改的联系人:>");
scanf("%s",name);
ret = Findpeople(pc,name);
if(ret == -1)
{
printf("找不到该联系人\n");
}
else
{
printf("请重新输入该联系人的信息\n");
printf("请输入该联系人的名字:>");
scanf("%s",pc->data[ret].name);
printf("请输入该联系人的性别:>");
scanf("%s",pc->data[ret].sex);
printf("请输入该联系人的地址:>");
scanf("%s",&pc->data[ret].addr);
printf("请输入该联系人的电话:>");
scanf("%s",&pc->data[ret].tele);
printf("请输入该联系人的年龄:>");
scanf("%d",&(pc->data[ret].age));
}
}
void ShowContact(struct contact* pc)
{
int i = 0;
printf("%-20s\t%-4s\t%-30s\t%-12s\t%-5s\t\n","名字","性别","地址","电话","年龄");
for(i=0;i<pc->sz;i++)
{
printf("%-20s\t%-4s\t%-30s\t%-12s\t%-5d\t\n",pc->data[i].name,
pc->data[i].sex,
pc->data[i].addr,
pc->data[i].tele,
pc->data[i].age);
}
}
void Menu()
{
printf("***************************************************************\n");
printf("***** 1.name 2.sex *****\n");
printf("***** 3.tele 4.addr *****\n");
printf("***** 5.age 0.exit *****\n");
printf("***************************************************************\n");
}
int com_by_name(const void* str1,const void* str2)
{
return strcmp(((struct people*)str1)->name,((struct people*)str2)->name);
}
int com_by_sex(const void* str1,const void* str2)
{
return strcmp(((struct people*)str1)->sex,((struct people*)str2)->sex);
}
int com_by_tele(const void* str1,const void* str2)
{
return strcmp(((struct people*)str1)->tele,((struct people*)str2)->tele);
}
int com_by_addr(const void* str1,const void* str2)
{
return strcmp(((struct people*)str1)->addr,((struct people*)str2)->addr);
}
int com_by_age(const void* str1,const void* str2)
{
return ((struct people*)str1)->age - ((struct people*)str2)->age;
}
void SortContact(struct contact* pc)
{
int input = 0;
Menu();
assert(pc != NULL);
again:
scanf("%d",&input);
switch(input)
{
case 1:
qsort(pc->data,pc->sz,sizeof(struct people),com_by_name);
break;
case 2:
qsort(pc->data,pc->sz,sizeof(struct people),com_by_sex);
break;
case 3:
qsort(pc->data,pc->sz,sizeof(struct people),com_by_tele);
break;
case 4:
qsort(pc->data,pc->sz,sizeof(struct people),com_by_addr);
break;
case 5:
qsort(pc->data,pc->sz,sizeof(struct people),com_by_age);
break;
case 0:
break;
default:
printf("输入错误,请重新输入");
goto again;
break;
}
if(input == 0)
{
printf("退出排序\n");
}
else
{
printf("排序成功\n");
}
}
void SaveContact(struct contact* pc)
{
int i = 0;
//打开文件
FILE* pfw = fopen("data.txt","wb");
assert(pc != NULL);
if(pfw == NULL)
{
perror("SaveContact::fopen");
}
//写文件
for(i=0;i<pc->sz;i++)
{
fwrite(pc->data+i,sizeof(struct people),1,pfw);
}
//关闭文件
fclose(pfw);
pfw = NULL;
}
test.c文档代码
#include "contact.h"
void menu()
{
printf("***************************************************************\n");
printf("***** 1.add 2.del *****\n");
printf("***** 3.search 4.modify *****\n");
printf("***** 5.show 6.sort *****\n");
printf("***** 0.exit *****\n");
printf("***************************************************************\n");
}
int main()
{
int input = 0;
struct contact con;
InitBoard(&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:
ModifyContact(&con);
break;
case 5:
ShowContact(&con);
break;
case 6:
SortContact(&con);
break;
case 0:
SaveContact(&con);
printf("保存文件成功\n");
DestroyContact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
}while(input);
}
contact.h文档代码
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#define nameMax 20
#define addrMax 30
#define teleMax 12
#define sexMax 3
#define Max 100
#define DEFAULT_INT 3
#define INT_SZ 2
struct people
{
char name[nameMax];
char addr[addrMax];
char tele[teleMax];
char sex[sexMax];
int age;
};
struct contact
{
struct people* data;
int sz;
int capacity;
};
//初始化通讯录
void InitBoard(struct contact* pc);
//添加联系人的信息
void Addcontact(struct contact* pc);
//删除联系人的信息
void Delcontact(struct contact* pc);
//搜索联系人的信息
void SearchContact(struct contact* pc);
//修改联系人的信息
void ModifyContact(struct contact* pc);
//显示所有联系人的信息
void ShowContact(struct contact* pc);
//排序联系人的信息
void SortContact(struct contact* pc);
//删除通讯录
void DestroyContact(struct contact* pc);
//加载文件信息的内容到通讯录
void LoadContact(struct contact* pc);
//将通讯录信息加载到文件中
void SaveContact(struct contact* pc);
创建data.txt文档
在项目的文件夹寻找,在代码文档中创建一个data.txt文档,存储通讯录信息。
文件版本通讯录的优势
如下面运行图片,我还未输入数据时,并且我正在上一次运行中输入联系人的信息和保存。
那我选择显示通讯录信息会发生什么呢?
由运行结果可以得知,打印出了联系人的信息。
观察data.txt文档可以发现,存储着的联系人的信息(上次运行程序结束时保存的),注意在程序运行时,输入data.txt文档是二进制的,而文本编辑作用于二进制时,只能得出乱码。
这就是文档版本通讯录的功能,让信息不会在程序结束时丢失,但是在实际的应用中,我们不会把程序运行的信息存储在文档中。既不安全效率又低,程序的信息将会存储在数据库中。
今天对于通讯录的分享到此结束,关注点一点,下期更精彩。