文章目录
可实现文件保存的通讯录的实现
——接上篇2.0版本动态通讯录的优化3.0版本
一、优化改进部分
在上次的2.0版本中,我们已经拥有了可实现动态内存操作的通讯录版本,但是每次当我们输入数据,展示数据,退出之后,我们再次执行程序,会发现我们之前输入的联系人信息丢失,需要再次输入。所以,在这次的3.0版本中我们加入了保存联系人信息的功能,这将极大的优化我们对通讯录的使用体验。
具体优化如下:
(1)添加文件保存功能
1.添加了保存联系人信息的功能,在输入信息后,我们选择保存功能,输入的信息将以文件的信息 (contact.dat) 保存在我们的通讯录的文件夹中。
保存联系人的信息由 SaveContact 函数具体实现:
void SaveContact(struct Contact *ps)
{
//创建一个文件pfout
FILE * pfout = fopen("contact.dat", "wb");
if (pfout == NULL)
{
printf("文件保存失败\n");
return;
}
//写入数据
int i = 0;
for (i = 0; i < ps->size; i++)
{
fwrite(ps->date + i, sizeof(struct PeoInfor), 1, pfout);
}
//关闭文件
fclose(pfout);
pfout = NULL;
printf("联系人信息保存成功\n");
}
(2)初始化加载文件信息
2.打开通讯录程序时,我们在初始化信息的时候,加入 LoadContact 函数,来加载之前保存在“ contact.dat ”文件里的联系人信息。
在加载信息之前,我们默认存储联系人数量最大是2,如果我们加载的信息大于2个,那么我们需要调整我们的内存空间,用Check_capacity函数来实现判断是否增容以及之后的调整空间操作。
void Check_capacity(struct Contact *ps)
{
if (ps->size == ps->capacity)
{
//增容
struct PeoInfor * ptr = (struct PeoInfor *)realloc(ps->date, (ps->capacity + 2)*sizeof(struct PeoInfor));
if (ptr == NULL)
{
printf("增容失败\n");
return;
}
else
{
ps->date = ptr;
ps->capacity += 2;
}
}
}
void LoadContact(struct Contact * ps)
{
FILE * pfin = fopen("contact.dat", "rb");
if (pfin == NULL)
{
printf("加载文件失败\n");
return;
}
struct PeoInfor tmp = { 0 };
while (fread(&tmp, sizeof(struct PeoInfor), 1, pfin))
{
Check_capacity(ps);
ps->date[ps->size] = tmp;
ps->size++;
}
fclose(pfin);
pfin = NULL;
}
void InitContact(struct Contact * ps)
{
ps->size = 0;
ps->capacity = DEFAULT_SZ;
ps->date = (struct PeoInfor *)malloc(DEFAULT_SZ * sizeof(struct PeoInfor));
if (ps->date == NULL)
{
printf("通讯录初始化失败");
exit(1);
}
//加载文件
LoadContact(ps);
}
二、整体代码展示
1.test.c 通讯录主体框架测试文件
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "contact.h"
#include <string.h>
void menu()
{
//打印通讯录菜单
//0.退出菜单
//1.添加联系人信息
//2.删除指定名字的联系人信息
//3.修改联系人的信息
//4.查找好友的信息
//5.展示通讯录联系人信息
//6.对通讯录指定信息进行排序
printf("*************************************************\n");
printf("********** ——欢迎来到通讯录菜单—— *********\n");
printf("********** 0.退出菜单 *********\n");
printf("********** 1.添加联系人信息 *********\n");
printf("********* 2.删除联系人信息 *********\n");
printf("********* 3.修改联系人信息 *********\n");
printf("********* 4.查找联系人信息 *********\n");
printf("********* 5.展示联系人信息 *********\n");
printf("********* 6.保存联系人信息 *********\n");
printf("*************************************************\n");
}
//将菜单的功能一一列举出来,以枚举的类型呈现
enum
{
EXIT,
ADD,
DEL,
MODIFY,
SEARCH,
SHOW,
SAVE
};
int main()
{
int input = 0;
//创建通讯录
struct Contact con; //Con就是通讯录,里面包含1000个人的信息,及size
InitContact(&con);
do
{
menu();
printf("请选择功能:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case MODIFY:
MotifyContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case SHOW:
ShowContact(con);
break;
case EXIT:
DestroyContact(&con);
break;
case SAVE:
SaveContact(&con);
break;
default:
printf("选择错误,请重新输入!!\n");
break;
}
} while (input);
return 0;
}
2.contact.c 通讯录函数文件
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include "contact.h"
#include <stdlib.h>
#include <errno.h>
void Check_capacity(struct Contact *ps)
{
if (ps->size == ps->capacity)
{
//增容
struct PeoInfor * ptr = (struct PeoInfor *)realloc(ps->date, (ps->capacity + 2)*sizeof(struct PeoInfor));
if (ptr == NULL)
{
printf("增容失败\n");
return;
}
else
{
ps->date = ptr;
ps->capacity += 2;
}
}
}
void LoadContact(struct Contact * ps)
{
FILE * pfin = fopen("contact.dat", "rb");
if (pfin == NULL)
{
printf("加载文件失败\n");
return;
}
struct PeoInfor tmp = { 0 };
while (fread(&tmp, sizeof(struct PeoInfor), 1, pfin))
{
Check_capacity(ps);
ps->date[ps->size] = tmp;
ps->size++;
}
fclose(pfin);
pfin = NULL;
}
void InitContact(struct Contact * ps)
{
ps->size = 0;
ps->capacity = DEFAULT_SZ;
ps->date = (struct PeoInfor *)malloc(DEFAULT_SZ * sizeof(struct PeoInfor));
if (ps->date == NULL)
{
printf("通讯录初始化失败");
exit(1);
}
//加载文件
LoadContact(ps);
}
void AddContact(struct Contact* ps)
{
Check_capacity(ps);
printf("请输入姓名:>");
scanf("%s", ps->date[ps->size].name);
printf("请输入年龄:>");
scanf("%d", &(ps->date[ps->size].age));
printf("请输入性别:>");
scanf("%s", ps->date[ps->size].sex);
printf("请输入电话:>");
scanf("%s", ps->date[ps->size].tel);
printf("请输入地址:>");
scanf("%s", ps->date[ps->size].addr);
ps->size++;
printf("添加成功\n");
}
void ShowContact(struct Contact ps)
{
if (ps.size == 0)
{
printf("通讯录为空,无法展示\n");
}
else
{
printf("%10s\t%4s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < ps.size; i++)
{
printf("%10s\t%4d\t%5s\t%12s\t%20s\n",
ps.date[i].name,
ps.date[i].age,
ps.date[i].sex,
ps.date[i].tel,
ps.date[i].addr);
}
}
}
void DelContact(struct Contact *ps)
{
// 查找要删除的人在什么位置,根据名字
char name[MAX_name];
printf("请输入要删除的联系人名字:>");
scanf("%s", name);
int i = 0;
int j = 0;
//查找名字
for (i = 0; i < ps->size; i++)
{
if (0 == strcmp(name, ps->date[j].name))
{
break;
}
}
if (i == ps->size) // i从循环里出来,strcmp还是不等于0
{
printf("未找到该联系人的信息\n");
}
else
{
for (j = i; j < ps->size; j++)
{
ps->date[j] = ps->date[j + 1];
}
}
ps->size--;
printf("删除成功\n");
}
void MotifyContact(struct Contact *ps)
{
char name[MAX_name];
printf("请输入要删除的联系人名字:>");
scanf("%s", name);
int i = 0;
//查找名字
for (i = 0; i < ps->size; i++)
{
if (0 == strcmp(name, ps->date[i].name))
{
break;
}
}
if (i == ps->size) // i从循环里出来,strcmp还是不等于0
{
printf("未找到该联系人的信息\n");
}
//表示找到该联系人
//对下标为i的联系人信息进行修改
else
{
printf("请输入姓名:>");
scanf("%s", ps->date[i].name);
printf("请输入年龄:>");
scanf("%d", &(ps->date[i].age));
printf("请输入性别:>");
scanf("%s", ps->date[i].sex);
printf("请输入电话:>");
scanf("%s", ps->date[i].tel);
printf("请输入地址:>");
scanf("%s", ps->date[i].addr);
}
printf("修改成功\n");
}
void SearchContact(struct Contact *ps)
{
char name[MAX_name];
printf("请输入要查找的联系人名字:>");
scanf("%s", name);
int i = 0;
//查找名字
for (i = 0; i < ps->size; i++)
{
if (0 == strcmp(name, ps->date[i].name))
{
break;
}
}
if (i == ps->size) // i从循环里出来,strcmp还是不等于0
{
printf("未找到该联系人的信息\n");
}
//表示找到该联系人
//对下标为i的联系人信息进行显示
else
{
printf("%10s\t%4s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%10s\t%4d\t%5s\t%12s\t%20s\n",
ps->date[i].name,
ps->date[i].age,
ps->date[i].sex,
ps->date[i].tel,
ps->date[i].addr);
}
}
void DestroyContact(struct Contact *ps)
{
free(ps->date);
ps->date = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SaveContact(struct Contact *ps)
{
//创建一个文件pfout
FILE * pfout = fopen("contact.dat", "wb");
if (pfout == NULL)
{
printf("文件保存失败\n");
return;
}
//写入数据
int i = 0;
for (i = 0; i < ps->size; i++)
{
fwrite(ps->date + i, sizeof(struct PeoInfor), 1, pfout);
}
//关闭文件
fclose(pfout);
pfout = NULL;
printf("联系人信息保存成功\n");
}
3.contact.h 宏定义及函数声明文件
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 1000
#define MAX_name 20
#define MAX_tel 20
#define MAX_sex 5
#define MAX_addr 30
#define DEFAULT_SZ 2
struct PeoInfor
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tel[MAX_tel];
char addr[MAX_addr];
};
struct Contact
{
struct PeoInfor* date; // 存放个人信息
int size; //表示当前通讯录的联系人的数量
int capacity;
};
// 声明函数
void InitContact(struct Contact* ps);
void AddContact(struct Contact* ps);
void ShowContact(struct Contact ps);
void DelContact(struct Contact *ps);
void MotifyContact(struct Contact *ps);
void SearchContact(struct Contact *ps);
void DestroyContact(struct Contact *ps);
void SaveContact(struct Contact *ps);
void LoadContact(struct Contact *ps);
小结
以上 1.0版本——静态通讯录的实现
2.0版本——动态通讯录的实现
3.0版本——可文件保存的通讯录的实现
较为完整的实现了一个通讯录的大部分功能,当然我们还可以再次进行优化,添加一些更有需要的功能等,我们的C语言实战项目——通讯录到这里就结束了,希望大家可以多多练习,如果有错误,请大家对博主的文章进行指正。
谢谢大家的欣赏与关注!!!