前面我们已经学过了静态通讯录,动态通讯录,但这两种通讯录储存的信息在程序运行结束后就会自动消失,那么如何能够将信息储存起来呢?
今天我们来介绍可储存通讯录
接上次动态通讯录,我们需要增加的功能有两个:
1. 每一次打开通讯录要加载文件里储存的通讯录信息
2.每一次关闭通讯录要将本次通讯录信息的更改传入文件中
我们来看看具体的实现方式:
1.我们在初始化的同时加载出文件信息
//初始化通讯录
void InitContact(struct contact* con)
{
assert(con);
con->num = 0;
con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
if (con->data == NULL) //检查分配是否成功
{
printf("%s\n", strerror());
return;
}
con->capacity = DEFAULT_SZ;
//加载联系人信息
LoadContact(con);
}
//加载联系人信息
void LoadContact(struct contact*pc)
{
//打开文件
FILE*pf=fopen("contact.txt","rb");
if (NULL == pf)
{
perror("LoadContact::fopen");
return;
}
//读文件
struct pepinfo tmp = { 0 };
while (fread(&tmp,sizeof(struct pepinfo),1,pf))
{
CheckCapacity(pc);
pc->data[pc->num] = tmp;
pc->num++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
2.我们在退出通讯录之前要将信息保存
//保存联系人信息
void SaveContact(struct contact* pc)
{
//打开文件
FILE*pf =fopen("contact.txt", "wb");
//写入
if (NULL == pf)
{
perror("SaveContact::fopen");
return;
}
for (int i = 0; i < pc->num; i++)
{
//fwrite(&(pc->data[i]),sizeof(struct pepinfo),1,pf);
fwrite(pc->data + i, sizeof(struct pepinfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
下面是具体代码
test.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include"contact.h"
void menu()
{
printf("****************************************************\n");
printf("***** 1.添加联系人 2.删除联系人 *******\n");
printf("***** 3.查找联系人 4.修改联系人 *******\n");
printf("***** 5.展示联系人 6.排序联系人 *******\n");
printf("***** 7.清空联系人 0.退出 *******\n");
printf("****************************************************\n");
}
enum option
{
exit,
add,
del,
search,
modify,
show,
sort,
clear
};
int main()
{
int input = 0;
struct contact con;//创建一个通讯录
InitContact(&con);//初始化通讯录
do
{
menu();//打印菜单
printf("请选择》》");
scanf("%d", &input);
switch (input)
{
case exit:
//保存联系人信息
SaveContact(&con);
DestroyContact(&con); //退出时销毁
printf("退出\n");
break;
case add:
tianjia(&con);
break;
case del:
shanchu(&con);
break;
case search:
chazhao(&con);
break;
case modify:
xiugai(&con);
break;
case show:
dayin(&con);
break;
case sort:
paixu(&con);
break;
case clear:
qingkong(&con);
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
#include<stdio.h>
#define DEFAULT_SZ 3
//先对函数进行声明
void InitContact(struct contact* con);
void tianjia(struct contact* con);
void shanchu(struct contact* con);
void chazhao(const struct contact* con);
void dayin(struct contact* con);
void xiugai(struct contact* con);
void paixu(struct contact* con);
void CheckCapacity(struct contact* con);
//添加联系人
void tianjia(struct contact *con)
{
CheckCapacity(con);
if (con->num == max)
{
printf("\n通讯录已满,添加失败\n");
}
else
{
printf("\n请输入联系人姓名》");
scanf("%s", con->data[con->num].name);
printf("\n请输入联系人性别》");
scanf("%s", con->data[con->num].sex);
printf("\n请输入联系人年龄》");
scanf("%d", &con->data[con->num].age);//age是变量 需要取地址&
printf("\n请输入联系人电话》");
scanf("%s", con->data[con->num].tel);
printf("\n请输入联系人住址》");
scanf("%s", con->data[con->num].ads);
con->num++;
printf("\n添加成功\n");
}
}
//删除联系人
void shanchu(struct contact* con)
{
int n = 0;
printf("\n请输入要删除联系人的序列号");
scanf("%d", &n);
if (n<1 || n>con->num)
{
printf("不存在的序列号,删除失败\n");
}
else
{
for (int i = 0; i <= con->num - n; i++)
{
*(con->data[n-1 + i].name) = *(con->data[n + i ].name);
*(con->data[n-1 + i].sex) = *(con->data[n + i ].sex);
con->data[n-1 + i].age = con->data[n + i ].age;
*(con->data[n-1 + i].tel) = *(con->data[n + i ].tel);
*(con->data[n-1 + i].ads) = *(con->data[n + i ].ads);
}
con->num--;//不要忘了把联系人数量减1
printf("删除成功\n");
}
}
//查找联系人
void chazhao(const struct contact*con)
{
printf("请输入需要查找的序号>");
int n = 0;
scanf("%d", &n);
if (n > con->num)
{
printf("该序号联系人不存在\n");
}
else
{
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tel", "ads");
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
con->data[n - 1].name,
con->data[n - 1].age,
con->data[n - 1].sex,
con->data[n - 1].tel,
con->data[n - 1].ads);
}
}
//打印联系人
void dayin(struct contact *con)
{
int n = 0;
printf("%15s\t%5s\t%8s\t%15s\t%30s\n\n", "name", "age", "sex", "tel", "ads");
for( n=0;n< con->num;n++)
{
printf("%15s\t%5d\t%8s\t%15s\t%30s\n",
con->data[n].name,
con->data[n].age,
con->data[n].sex,
con->data[n].tel,
con->data[n].ads);
}
}
//修改联系人信息
void xiugai(struct contact* con)
{
int n = 0;
printf("请输入需要修改联系人的序号");
scanf("%d", &n);
if (n > con->num)
{
printf("该序号联系人不存在\n");
}
else
{
printf("\n请输入联系人姓名》");
scanf("%s", con->data[n-1].name);
printf("\n请输入联系人性别》");
scanf("%s", con->data[n-1].sex);
printf("\n请输入联系人年龄》");
scanf("%d", &con->data[n-1].age);//age是变量 需要取地址&
printf("\n请输入联系人电话》");
scanf("%s", con->data[n-1].tel);
printf("\n请输入联系人住址》");
scanf("%s", con->data[n-1].ads);
printf("\n修改成功\n");
}
}
//按照名字排序
void paixu(struct contact* con)
{
int i, j;
struct pepinfo tmp;
for (i = 0; i < con->num - 1; i++)
{
for (j = 0; j < con->num - 1 - i; j++)
{
if (0 < strcmp(con->data[j].name, con->data[j + 1].name))
{
tmp = con->data[j];
con->data[j] = con->data[j + 1];
con->data[j + 1] = tmp;
}
}
}
printf("完成排序\n");
}
//清空联系人
void qingkong(struct contact* con)
{
assert(con);
con->num = 0;
con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
if (con->data == NULL) //检查分配是否成功
{
printf("%s\n", strerror());
return;
}
con->capacity = DEFAULT_SZ;
printf("清空成功\n");
}
//检查容量
void CheckCapacity(struct contact* con)
{
if (con->num == con->capacity)
{
//每次扩容两个
struct pepinfo* ptr = (struct pepinfo*)realloc(con->data, (con->capacity + 2) * sizeof(struct pepinfo));
if (ptr != NULL)
{
con->data = ptr;
con->capacity += 2;
printf("增容成功\n");
}
else
{
perror("通讯录增容失败");
exit(1);
}
}
}
//加载联系人信息
void LoadContact(struct contact*pc)
{
//打开文件
FILE*pf=fopen("contact.txt","rb");
if (NULL == pf)
{
perror("LoadContact::fopen");
return;
}
//读文件
struct pepinfo tmp = { 0 };
while (fread(&tmp,sizeof(struct pepinfo),1,pf))
{
CheckCapacity(pc);
pc->data[pc->num] = tmp;
pc->num++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//初始化通讯录
void InitContact(struct contact* con)
{
assert(con);
con->num = 0;
con->data = (struct pepinfo*)calloc(DEFAULT_SZ, sizeof(struct pepinfo)); //分配默认大小并清空
if (con->data == NULL) //检查分配是否成功
{
printf("%s\n", strerror());
return;
}
con->capacity = DEFAULT_SZ;
//加载联系人信息
LoadContact(con);
}
//保存联系人信息
void SaveContact(struct contact* pc)
{
//打开文件
FILE*pf =fopen("contact.txt", "wb");
//写入
if (NULL == pf)
{
perror("SaveContact::fopen");
return;
}
for (int i = 0; i < pc->num; i++)
{
//fwrite(&(pc->data[i]),sizeof(struct pepinfo),1,pf);
fwrite(pc->data + i, sizeof(struct pepinfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
//销毁通讯录
void DestroyContact(contact* con)
{
free(con->data);
con->data = NULL;
con->capacity = 0;
con->num = 0;
}
contact.h
#pragma once
#define max 1000
#define name_max 20
#define sex_max 5
#define tel_max 15
#define ads_max 30
#include<stdio.h>
#include<assert.h>
struct pepinfo//描述一个人的信息
{
char name[name_max];//姓名
char sex[sex_max];//性别
int age;//年龄
char tel[tel_max];//电话号码
char ads[ads_max];//家庭住址
};
typedef struct contact
{
struct pepinfo* data;
int num;//有效元素的个数
int capacity;//容量
}contact;