学习了C语言的文件操作之后,就可以将我之前写的通讯录管理系统再次进行改造,改造成文件版本,将联系人信息存储到文件当中,这样程序结束之后通讯录信息依旧可以保存。
这是我之前写的两个版本:
下面是需要改变的部分
如果要将通讯录的信息存储到文件中,就要在销毁通讯录、退出通讯录之前进行保存。
1.保存通讯录
我把它封装成一个函数 SaveContact();
void SaveContact(const Con* pc)
{
//打开文件
FILE* pf = fopen("contact.txt","wb");
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->p+i,sizeof(Peoinfo),1,pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
2.加载通讯录
通讯录创建之后是空的,要把文件中存有的联系人信息导入到通讯录中,所以初始化通讯录函数也需要改造。
//加载函数
void LoadContact(Con* pc)
{
//打开文件
FILE* pf = fopen("contact.txt","rb");
if (pf==NULL)
{
perror("LoadContact::foopen");
return;
}
//读文件
Peoinfo tmp = { 0 };
while (fread(&tmp, sizeof(Peoinfo), 1, pf))
{
//加载进来的时候空间可能不够,所以涉及到增容
CheckCapcity(pc);
pc->p[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//文件版本
void InitContact(Con* pc)
{
assert(pc);
pc->sz = 0;
pc->capcity = START_SZ;
pc->p = (struct Peoinfo*)malloc(pc->capcity * sizeof(struct Peoinfo));
if (pc->p == NULL)
{
perror("InitContact::malloc");
return;
}
memset(pc->p, 0, pc->capcity * sizeof(struct Peoinfo));
//加载文件信息到通讯录中
LoadContact(pc);
}
效果展示
此时文件里已经有了信息,启动程序之后,不用添加,选择打印,就可以将存储的信息打印出来
代码展示(分文件)
1.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
printf(" 通讯录\n");
printf("*************************************\n");
printf("****** 1、Add 2、Del *********\n");
printf("****** 3、Modify 4、Search *********\n");
printf("****** 5、Print 6、Sort *********\n");
printf("****** 0、Exit *********\n");
printf("*************************************\n");
}
void test()
{
int input = 0;
struct Contact con;
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case add:
AddContact(&con);
break;
case del:
DelContact(&con);
break;
case modify:
Modify(&con);
break;
case search:
Search(&con);
break;
case print:
Print(&con);
break;
case sort:
Sort(&con);
break;
case Exit:
SaveContact(&con);
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
2.contact.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 13
#define ADDR_MAX 30
#define People_MAX 1000
//通讯录初始化默认空间大小
#define START_SZ 3
//类型声明
typedef struct Peoinfo//每个人的信息
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}Peoinfo;
typedef struct Contact
{
struct Peoinfo* p;//指向动态开辟内存空间
int sz;//记录存放在通讯录中的人数
int capcity;//记录开辟的空间的当前最大容量
}Con;
//通讯录功能
enum fun
{
Exit,
add,
del,
modify,
search,
print,
sort
};
enum modifyoption//修改信息选项
{
Name = 1,
Sex,
Age,
Tele,
Addr
};
//函数声明
//初始化通讯录
void InitContact(Con* pc);
//增加联系人
void AddContact(Con* pc);
//打印
void Print(const Con* pc);
//删除联系人
void DelContact(Con* pc);
//查找
int FindByName(const Con* pc,char* name);
//查找联系人
void Search(const Con* pc);
//修改联系人信息
void Modify(Con* pc);
//排序
void Sort(Con* pc);
//增容
void CheckCapcity(Con* pc);
//销毁通讯录
void DestroyContact(Con* pc);
//文件版本
//保存通讯录
void SaveContact(const Con* pc);
3.contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//静态版
//void InitContact(Con* pc)
//{
// assert(pc);
// pc->sz = 0;
// memset(pc->p,0,sizeof(pc->p));
//}
//动态版
//void InitContact(Con* pc)
//{
// assert(pc);
// pc->sz = 0;
// pc->capcity = START_SZ;
// pc->p = (struct Peoinfo*)malloc(pc->capcity*sizeof(struct Peoinfo));
// if (pc->p == NULL)
// {
// perror("InitContact::malloc");
// return;
// }
// memset(pc->p, 0, pc->capcity * sizeof(struct Peoinfo));
//
//}
//
void LoadContact(Con* pc)
{
//打开文件
FILE* pf = fopen("contact.txt","rb");
if (pf==NULL)
{
perror("LoadContact::foopen");
return;
}
//读文件
Peoinfo tmp = { 0 };
while (fread(&tmp, sizeof(Peoinfo), 1, pf))
{
//加载进来的时候空间可能不够,所以涉及到增容
CheckCapcity(pc);
pc->p[pc->sz] = tmp;
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//文件版本
void InitContact(Con* pc)
{
assert(pc);
pc->sz = 0;
pc->capcity = START_SZ;
pc->p = (struct Peoinfo*)malloc(pc->capcity * sizeof(struct Peoinfo));
if (pc->p == NULL)
{
perror("InitContact::malloc");
return;
}
memset(pc->p, 0, pc->capcity * sizeof(struct Peoinfo));
//加载文件信息到通讯录中
LoadContact(pc);
}
void CheckCapcity(Con* pc)
{
if (pc->sz == pc->capcity)
{
Peoinfo* tmp = (Peoinfo*)realloc(pc->p, (pc->capcity + 2) * sizeof(Peoinfo));//每次增加2个
if (tmp != NULL)
{
pc->p = tmp;
}
pc->capcity += 2;
printf("增容成功\n");
}
}
//释放动态开辟的空间
void DestroyContact(Con* pc)
{
free(pc->p);
pc->p = NULL;
pc->capcity = 0;
pc->sz = 0;
printf("销毁成功\n");
}
void AddContact(Con* pc)
{
assert(pc);
//静态版本
/*if (pc->sz == People_MAX)
{
printf("通讯录已满,无法增加\n");
return;
}*/
//动态版本 满了要增容
CheckCapcity(pc);
printf("请输入名字:");
scanf("%s", pc->p[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->p[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &(pc->p[pc->sz].age));
printf("请输入电话:");
scanf("%s", pc->p[pc->sz].tele);
printf("请输入住址:");
scanf("%s", pc->p[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void Print(const Con* pc)
{
assert(pc);
//打印
int i = 0;
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[i].name, pc->p[i].sex, pc->p[i].age, pc->p[i].tele, pc->p[i].addr);
}
}
void DelContact(Con* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录已空,无法删除\n");
return;
}
//要删除,首先要找到删除的对象
char name[NAME_MAX] = { 0 };
printf("请输入要查找的名字:");
scanf("%s", name);
int ret = FindByName(pc,name);//找到返回下标,找不到返回-1
if (ret == -1)
{
printf("找不到\n");
return;
}
else
{
//删除-->把后面的数据覆盖到要删除的地方
int i = 0;
for (i = ret; i < pc->sz-1; i++)
{
pc->p[i] = pc->p[i + 1];
}
pc->sz--;
printf("删除成功\n");
return;
}
}
int FindByName(const Con* pc,char* name)
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->p[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void Search(const Con* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录是空的,找不到\n");
return;
}
//找
char name[NAME_MAX] = { 0 };
printf("请输入要查找的名字:");
scanf("%s", name);
int ret = FindByName(pc, name);
if (ret == -1)
{
printf("找不到\n");
return;
}
else
{
//找到并打印
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
return;
}
}
void Modify(Con* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录是空的,无法修改\n");
return;
}
//先找到指定目标
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人的名字:");
scanf("%s", name);
int ret = FindByName(pc, name);
//修改
char sex[SEX_MAX] = { 0 };
char tele[TELE_MAX] = { 0 };
char addr[ADDR_MAX] = { 0 };
int age = 0;
if (ret == -1)
{
printf("找不到\n");
return;
}
else
{
//找到打印显示,并修改
int input = 0;
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
printf("------------------------------\n");
printf("%s %s %s %s %s\n", "1、名字", "2、性别", "3、年龄", "4、电话", "5、住址");
printf("请选择要修改的信息:");//定义一个修改信息选项的枚举
scanf("%d", &input);
switch (input)
{
case Name:
printf("请输入修改信息:");
scanf("%s", name);
memcpy(pc->p[ret].name, name, NAME_MAX);
printf("修改成功\n");
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
break;
case Sex:
printf("请输入修改信息:");
scanf("%s", sex);
memcpy(pc->p[ret].sex, sex, SEX_MAX);
printf("修改成功\n");
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
break;
case Age:
printf("请输入修改信息:");
scanf("%d", age);
memcpy(pc->p[ret].age, age,sizeof(int));
printf("修改成功\n");
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
break;
case Tele:
printf("请输入修改信息:");
scanf("%s", tele);
memcpy(pc->p[ret].tele, tele, TELE_MAX);
printf("修改成功\n");
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
break;
case Addr:
printf("请输入修改信息:");
scanf("%s", addr);
memcpy(pc->p[ret].addr, addr, ADDR_MAX);
printf("修改成功\n");
printf("%-20s %-5s %-10s %-13s %-30s\n", "名字", "性别", "年龄", "电话", "住址");
printf("%-20s %-5s %-10d %-13s %-30s\n", pc->p[ret].name, pc->p[ret].sex, pc->p[ret].age, pc->p[ret].tele, pc->p[ret].addr);
break;
default:
break;
}
return;
}
}
static void SortMenu()
{
printf("*************************\n");
printf("*** 1、名字 2、年龄 ***\n");
printf("*************************\n");
}
static int cmp_by_name(const void* e1,const void* e2)
{
return strcmp((((struct Peoinfo*)e1)->name), ((struct Peoinfo*)e2)->name);
}
static int cmp_by_age(const void* e1, const void* e2)
{
return (((struct Peoinfo*)e1)->age)-((struct Peoinfo*)e2)->age;
}
void Sort(Con* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录是空的,无法排序\n");
return;
}
//排序 用qsort
int input = 0;
SortMenu();
printf("请选择排序的方式:");
scanf("%d", &input);
switch (input)
{
case 1:
qsort(pc->p,pc->sz,sizeof(struct Peoinfo),cmp_by_name);
printf("排序成功\n");
break;
case 2:
qsort(pc->p, pc->sz, sizeof(struct Peoinfo), cmp_by_age);
printf("排序成功\n");
break;
default:
printf("选择错误\n");
break;
}
}
void SaveContact(const Con* pc)
{
//打开文件
FILE* pf = fopen("contact.txt","wb");
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
//写文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->p+i,sizeof(Peoinfo),1,pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
本文含有隐藏内容,请 开通VIP 后查看