前言
在前面曾用静态、动态顺序表两种方式实现通讯录,但每次运行程序我们都得重新输入,之前输入的成员信息并不会保存,而现实中,通讯录里的信息创建后是永久保存的,除非你删除它,今天我们就来模拟一下如何将数据存储在文件中,当下一次运行时加载一下即可,这种做法更贴合实际。
程序中会用到与文件操作相关的函数,提前介绍一下:
- fopen 它的函数原型为:FILE*fopen(const char *filename,const char *mode) ,filename:创建文件的名字;mode:允许进入文件的类型;简单来说这个文件的作用就是打开一个文件流;与fclose:关闭文件流配套使用.
- perror: 它的函数原型为:void perror(const char * string) ,这是一种报告文件错误的函数;后面包括一个分号和一个空格,然后打印出一条用于解释errno当前错误代码的信息;
- fwrite: 它的函数原型为:size_t fwrite(const void buffer,size_t size,size_t count,FILEstream) ,buffer:数据写入的体格缓冲区;
通讯录简要功能:
- 初始化通讯录
- 添加联系人
- 查找联系人
- 删除联系人
- 修改联系人
- 按姓名排序
- 清空联系人
- 联系人列表
- 检查容量
- 加载文件
- 保存文件
- 销毁通讯录
- 退出
参考代码:
Contact.h:
/***********************************************************
* 程序名称:通讯录(静态顺序表) *
* 编译环境:VS2013 *
* 编制日期:2018.5.29 *
* -----by Hunter *
***********************************************************/
#ifndef __CONTACT_H__
#define __CONTACT_H__
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
enum OPPTION
{
EXIT,
ADD,
SEARCH,
DEIETE,
MODIFY,
SORT,
SHOW,
EMPTY
};
typedef char datatype;
#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_TEL 11
#define MAX_ADDR 30
#define MAX_SIZE 1000
#define FILE_NAME "contact.dat"
typedef struct PeoInfo
{
datatype Name[MAX_NAME];
datatype Sex[MAX_SEX];
int age;
datatype Tel[MAX_TEL];
datatype Addr[MAX_ADDR];
}PeoInfo, *pPeoInfo;
typedef struct Contact
{
pPeoInfo data;
int size;
int capacity;
}Contact, *pContact;
//初始化通讯录
void InitContact(pContact pc);
//添加联系人
void AddContact(pContact pc);
//删除联系人
void DeleteContact(pContact pc);
//查找联系人
int SearchContact(pContact pc);
//修改联系人
void ModifyContact(pContact pc);
//按姓排序
void SortContact(pContact pc);
//列表联系人
void ShowContact(pContact pc);
//清空联系人
void EmptyContact(pContact pc);
//销毁
void DestoryContact(pContact pc);
//加载
void LoadContact(pContact pc);
//保存
void SaveContact(pContact pc);
#endif //__CONTACT_H__
Contact.c:
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//检查扩容
void CheckCapacity(pContact pc)
{
assert(pc);
pPeoInfo *p = NULL;
if (pc->size == pc->capacity)
{
p = (pPeoInfo)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
if (p != NULL)
{
pc->data = p;
}
else
{
printf("\t\t\t增容失败");
exit(EXIT_FAILURE);
}
pc->capacity += 2;
printf("\t\t\t增容成功\n");
}
}
//加载
void LoadContact(pContact pc)
{
int i = 0;
FILE* pfRead = fopen("contact.dat", "r");
PeoInfo tmp = { 0 }; //创建临时变量保存每次读取的信息
assert(pc);
if (pfRead == NULL)
{
perror("the file to read");
exit(EXIT_FAILURE);
}
while (fread(&tmp, sizeof(PeoInfo), 1, pfRead))
{
CheckCapacity(pc);
pc->data[i] = tmp;
i++;
pc->size++;
}
fclose(pfRead);
pfRead = NULL;
}
//保存
void SaveContact(pContact pc)
{
assert(pc);
FILE *pfwrite = fopen("contact.dat", "w");
int i = 0;
if (pfwrite == NULL)
{
perror("the file to write");
exit(EXIT_FAILURE);
}
for (i = 0; i<pc->size; i++)
{
fwrite(pc->data+ i, sizeof(PeoInfo), 1, pfwrite);
}
fclose(pfwrite);
pfwrite = NULL;
}
//初始化通讯录
void InitContact(pContact pc)
{
assert(pc);
pc->size = 0;
pc->capacity = 3;
pc->data = (pPeoInfo)malloc((pc->capacity)*sizeof(PeoInfo));
if (pc->data == NULL)
{
printf("\t\t\t内存分配失败");
exit(EXIT_FAILURE);
}
memset(pc->data, 0, sizeof(pc->data));
LoadContact(pc);
}
//添加联系人
void AddContact(pContact pc)
{
assert(pc);
if (pc->size == MAX_SIZE)
{
printf("\t\t\t空间不足");
return;
}
CheckCapacity(pc);
printf("\t\t\t请输入姓名:>");
scanf("%s", pc->data[pc->size].Name);
printf("\t\t\t请输入性别:>");
scanf("%s", pc->data[pc->size].Sex);
printf("\t\t\t请输入年龄:>");
scanf("%d", &pc->data[pc->size].age);
printf("\t\t\t请输入电话号:>");
scanf("%s", pc->data[pc->size].Tel);
printf("\t\t\t请输入地址:>");
scanf("%s", pc->data[pc->size].Addr);
pc->size++;
printf("\t\t\t添加成功\n");
}
//查找联系人
int SearchContact(pContact pc)
{
char name[MAX_NAME];
int i = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无此联系人\n");
return -1;
}
printf("\t\t\t");
scanf("%s", name);
printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
for (i = 0; i < pc->size; i++)
{
if (0 == strcmp(pc->data[i].Name, name))
{
printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
pc->data[i].Name,
pc->data[i].Sex,
pc->data[i].age,
pc->data[i].Tel,
pc->data[i].Addr);
return i;
}
}
printf("\t\t\t无此联系人\n");
return -1;
}
//删除联系人
void DeleteContact(pContact pc)
{
int i = 0;
int num = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
num = SearchContact(pc);
if (num != -1)
{
int n = 0;
printf("\t\t\t确定删除? 1.yes, 2.no:>");
printf("\t\t\t");
scanf("%d", &n);
if (1 == n)
{
for (i = num; i < (pc->size) - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->size--;
printf("\t\t\t删除成功\n");
}
else
{
return;
}
}
}
//交换
void Swap(pPeoInfo *a, pPeoInfo *b)
{
pPeoInfo *Tmp;
Tmp = *a;
*a = *b;
*b = Tmp;
}
//修改联系人
void ModifyContact(pContact pc)
{
int modify = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
modify = SearchContact(pc);
if (modify != -1)
{
int n = 0;
printf("\t\t\t确认修改?1.yes 2.no:>");
printf("\t\t\t");
scanf("%d", &n);
if (1 == n)
{
printf("\t\t\t请输入姓名:>");
scanf("%s", pc->data[modify].Name);
printf("\t\t\t请输入性别:>");
scanf("%s", pc->data[modify].Sex);
printf("\t\t\t请输入年龄:>");
scanf("%d", &pc->data[modify].age);
printf("\t\t\t请输入电话号:>");
scanf("%s", pc->data[modify].Tel);
printf("\t\t\t请输入地址:>");
scanf("%s", pc->data[modify].Addr);
printf("\t\t\t修改成功\n");
}
else
{
return;
}
}
}
//按姓排序
void SortContact(pContact pc)
{
int i = 0;
int j = 0;
int flag = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
// 冒泡次数
for (i = 0; i < pc->size - 1; i++)
{
//冒泡排序
for (j = 0; j < pc->size - i - 1; j++)
{
if (strcmp(pc->data[j].Name, pc->data[j + 1].Name)>0)
{
Swap(&pc->data[j], &pc->data[j + 1]);
flag = 1;
}
}
if (0 == flag)
{
break;
}
}
printf("排序成功\n");
}
//列表联系人
void ShowContact(pContact pc)
{
int i = 0;
assert(pc);
if (0 == pc->size)
{
printf("\t\t\t无联系人\n");
return;
}
printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
for (i = 0; i < pc->size; i++)
{
printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
pc->data[i].Name,
pc->data[i].Sex,
pc->data[i].age,
pc->data[i].Tel,
pc->data[i].Addr);
}
}
//清空联系人
void EmptyContact(pContact pc)
{
assert(pc);
pc->size = 0;
printf("\t\t\t清空成功");
}
//销毁通讯录
void DestoryContact(pContact pc)
{
assert(pc);
SaveContact(pc);
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->size = 0;
printf("\t\t\t销毁成功");
}
test.c:
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void meau()
{
printf("\t\t\t****** 《通讯录》 ********\n");
printf("\t\t\t****************************************\n");
printf("\t\t\t****** 1.添加信息 2.查找信息******\n");
printf("\t\t\t****** 3.删除信息 4.修改信息******\n");
printf("\t\t\t****** 5.按姓排序 6.信息列表******\n");
printf("\t\t\t****** 7.清空信息 0.退出 ******\n");
printf("\t\t\t****************************************\n");
}
void test()
{
int input = 0;
Contact pc;
InitContact(&pc);
do
{
meau();
printf("\t\t\t请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&pc);
break;
case SEARCH:
SearchContact(&pc);
break;
case DEIETE:
DeleteContact(&pc);
break;
case MODIFY:
ModifyContact(&pc);
break;
case SORT:
SortContact(&pc);
break;
case SHOW:
ShowContact(&pc);
break;
case EMPTY:
EmptyContact(&pc);
break;
case EXIT:
break;
default:
printf("\t\t\t输入有误,请重新输入:>");
break;
}
} while (input);
}
int main()
{
Contact pc;
test();
//销毁通讯录
DestoryContact(&pc);
system("pause");
return 0;
}
结语:
最初的自己是个编程菜鸟,然而通过努力的学习,现在也能逐渐的自己写小程序了,相信这就是一种进步,暂不希望自己能有多强大。只要每一步走的充实,我相信一定会有好的回报,且行且努力!
部分资料来源于网络,版权属其原著者所有,只供学习交流之用。如有侵犯您的权益,请联系【公众号:码农印象】删除,可在下方评论,亦可邮件至ysluckly.520@qq.com。互动交流时请遵守宽容、换位思考的原则。