前言
在之前,我讲解了通讯录管理系统的项目程序,分别是:
普通版通讯录项目(静态开辟内存版): C语言版通讯录操作系统_
和进阶版通讯录项目(动态内存开辟版): C语言版通讯录——动态存储(进阶版)
接下来,我再来讲一讲文件版本的通讯录,文件版本有个好处就是可以将调试过的程序的信息保存下来,就像一个小型简单版数据库一样。
一.代码实现:
1.保存调试信息写入文件中
首先需要将程序被调试时填写的信息保存下来,写入到文件中,需要用到一个函数SaveContact();它的位置是在结束调试的分支语句中:
在Contact.c函数实现中:
void SaveContact(Contact* pc) {
//创造文件并打开,
FILE* fw = fopen("Contact.txt", "wb");
if (fw == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//写文件
else {
int i = 0;
for (i = 0; i < pc->count; i++) {
fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
}
}
//关闭文件
fclose(fw);
fw = NULL;
}
代码讲解: 先创建文件指针接收fpoen函数创建出来的Contact.txt文件返回值,文件的打开模式是"wb","wb"是二进制写文件方式。然后通过if语句去判断指针是否打开文件成功,若成功,则继续下一步:将信息写入到文件中。写入文件的步骤是通过循环的方式,将PeoInf结构体类型的成员数据一个一个往进放,最后关闭文件。
注:使用"wb"文件打开方式,打开时每次打开文件时会生成一个新的空文件覆盖原有的文件,则每次保存的时候都会重新录一遍信息,这样就可以通讯录的实时性,即删除联系人时再保存会把删除之后的联系人信息重新录进文件(原有的信息全部擦除)
增加两个成员:
显示成员:
按0结束调试:
文件内容:
如上图,通过程序调试填写的信息经过fwrite函数就可以写入文件Contact.txt中了,因为是二进制形式往里面存入,所以会有一些乱码情况(这个不打紧)。
2. 加载信息到通讯录程序中
在Contact.c中:
//扩容
void check_key(Contact* pc) {
assert(pc);
if (pc->count == pc->capacity) {
PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
if (str == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
else {
pc->data = str;
pc->capacity += 2;
printf("增容成功\n");
}
}
}
//加载文件信息到通讯录中
void LoadContact(Contact* pc) {
FILE* fr = fopen("Contact.txt", "rb");
if (fr == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//读取文件信息
PeoInf tmp = { 0 };
while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
check_key(pc);
pc->data[pc->count] = tmp;
pc->count++;
}
//关闭文件
fclose(fr);
fr = NULL;
}
int InitContact(Contact* pc) {
assert(pc);
pc->capacity = CA_begin;
pc->count = 0;
pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
if (pc->data == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//加载文件信息到通讯录中
LoadContact(pc);
return 0;
}
LoadContact函数是用来实现加载信息到通讯录程序中的作用,它需要被放在初始化通讯录函数InitContact()中,LoadContact()函数的实现也是通过文件指针打开之前创建好的Contact.txt文件,使用fread函数读取文件中每个人的信息数据,需要调用扩容函数。
调试结果:
二.完整代码实现:
test.c:
#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
#include"Contact.h"
enum {
EXIT,
ADD,
DELETE,
MODIFY,
SEARCH,
SHOW,
QSORT,
TOTAL,
CLEAN
};
void menu() {
printf("**************通讯录管理系统界面***************\n");
printf("********************0.Exit.********************\n");
printf("********************1.Add. ********************\n");
printf("********************2.Delete.******************\n");
printf("********************3.Mod. ********************\n");
printf("********************4.Search.******************\n");
printf("********************5.Show.********************\n");
printf("********************6.Sqort.*******************\n");
printf("********************7.Total.*******************\n");
printf("********************8.Clean.*******************\n");
}
int main() {
int input = 0;
Contact con;
//初始化通讯录
InitContact(&con);
do {
menu();
printf("请输入你的选择:\n");
scanf("%d", &input);
switch (input) {
case EXIT:
SaveContact(&con);//文件保存
FreeContact(&con);
printf("即将退出程序\n");
break;
case ADD:
AddContact(&con);
break;
case DELETE:
DelContact(&con);
break;
case MODIFY:
ModContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case QSORT:
QsortContact(&con);
break;
case TOTAL:
TotalContact(&con);
break;
case CLEAN:
CleanContact(&con);
break;
default:
printf("输入错误\n");
break;
}
} while (input);
return 0;
}
Contact.c:
#include"Contact.h"
//扩容
void check_key(Contact* pc) {
assert(pc);
if (pc->count == pc->capacity) {
PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
if (str == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
else {
pc->data = str;
pc->capacity += 2;
printf("增容成功\n");
}
}
}
//加载文件信息到通讯录中
void LoadContact(Contact* pc) {
FILE* fr = fopen("Contact.txt", "rb");
if (fr == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//读取文件信息
PeoInf tmp = { 0 };
while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
check_key(pc);
pc->data[pc->count] = tmp;
pc->count++;
}
//关闭文件
fclose(fr);
fr = NULL;
}
int InitContact(Contact* pc) {
assert(pc);
pc->capacity = CA_begin;
pc->count = 0;
pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
if (pc->data == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//加载文件信息到通讯录中
LoadContact(pc);
return 0;
}
//添加
void AddContact(Contact* pc){
assert(pc);
check_key(pc);
printf("正在准备添加功能验证:\n");
printf("开始添加:\n");
printf("请输入成员姓名:\n");
scanf("%s", pc->data[pc->count].name);
printf("请输入成员年龄:\n");
scanf("%d", &(pc->data[pc->count].age));
printf("请输入成员性别:\n");
scanf("%s", pc->data[pc->count].sex);
printf("请输入成员电话:\n");
scanf("%s", pc->data[pc->count].tale);
printf("请输入成员地址:\n");
scanf("%s", pc->data[pc->count].addr);
pc->count++;
printf("添加成功\n");
}
//显示
void ShowContact(Contact* pc) {
assert(pc);
if (pc->count == 0) {
printf("通讯录为空,无法查看成员\n");
return;
}
else {
printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < pc->count; i++) {
printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tale,
pc->data[i].addr
);
}
}
}
//查找函数
int Find_name(Contact* pc, char name[]) {
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++) {
if (strcmp(pc->data[i].name, name) == 0) {
return i;
}
}
return -1;
}
//删除
void DelContact(Contact* pc) {
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0) {
printf("通讯录为空,无法进行删除\n");
return;
}
else {
printf("请输入要删除人的名字:\n");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1) {
printf("该成员不存在\n");
return;
}
else {
printf("正在准备删除功能验证:\n");
int i = 0;
for (i = ret; i < pc->count - 1; i++) {
pc->data[i] = pc->data[i + 1];
}
pc->count--;
printf("删除成功\n");
}
}
}
void ModContact(Contact* pc) {
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0) {
printf("通讯录为空,无法进行修改\n");
return;
}
else {
printf("请输入要修改的人员名单:\n");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1) {
printf("该成员不存在\n");
return;
}
else {
printf("正在进行修改功能验证:\n");
printf("修改开始:\n");
printf("请输入成员姓名:\n");
scanf("%s", pc->data[ret].name);
printf("请输入成员年龄:\n");
scanf("%d", &(pc->data[ret].age));
printf("请输入成员性别:\n");
scanf("%s", pc->data[ret].sex);
printf("请输入成员电话:\n");
scanf("%s", pc->data[ret].tale);
printf("请输入成员地址:\n");
scanf("%s", pc->data[ret].addr);
printf("\n修改成功\n");
}
}
}
//查找功能
void SearchContact(Contact* pc) {
assert(pc);
char name[MAX_NAME] = { 0 };
if (pc->count == 0) {
printf("通讯录为空,无法进行查找\n");
return;
}
else {
printf("请输入要查找的人员名单:\n");
scanf("%s", name);
int ret = Find_name(pc, name);
if (ret == -1) {
printf("该成员不存在\n");
return;
}
else {
printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[ret].name,
pc->data[ret].age,
pc->data[ret].sex,
pc->data[ret].tale,
pc->data[ret].addr
);
printf("\n查找成功\n");
}
}
}
int cmp_by_name(const void* e1, const void* e2) {
return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
}
int cmp_by_age(const void* e1, const void* e2) {
return ((PeoInf*)e1)->age-((PeoInf*)e2)->age;
}
//排序功能
void QsortContact(Contact* pc) {
assert(pc);
int i = 0;
printf("1.按姓名排序 2.按年龄排序 \n");
printf("请输入你要进行哪种排序方法?\n");
scanf("%d", &i);
if (i == 1) {
qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_name);
}
else if (i == 2) {
qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_age);
}
printf("排序成功\n");
}
//统计
void TotalContact(Contact* pc) {
assert(pc);
if (pc->count == 0) {
printf("通讯录为空,人员为0\n");
return;
}
int count = pc->count;
printf("此时通讯录内共有%d个成员\n", count);
}
int Clean(Contact * pc) {
assert(pc);
pc->capacity = CA_begin;
pc->count = 0;
pc->data = (PeoInf*)calloc(CA_begin, sizeof(PeoInf));
if (pc->data == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
return 0;
}
//一键清空
void CleanContact(Contact* pc) {
assert(pc);
if (pc->count == 0) {
printf("通讯录已为空,无法再执行此操作\n");
return;
}
int i=0;
printf("请问您确定要清空通讯录吗?确认请按9,否则按9以外的任意键\n");
scanf("%d",&i);
if (i == 9) {
Clean(pc);
printf("清空成功\n");
}
else if (i == 8) {
return;
}
}
void SaveContact(Contact* pc) {
FILE* fw = fopen("Contact.txt", "wb");
if (fw == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//写文件
else {
int i = 0;
for (i = 0; i < pc->count; i++) {
fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
}
}
//关闭文件
fclose(fw);
fw = NULL;
}
void FreeContact(Contact* pc) {
free(pc->data);
pc->data = NULL;
}
Contact.h:
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<errno.h>
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TALE 12
#define MAX_ADDR 20
#define CA_begin 3
#define Add_every 2
typedef struct PeoInf {
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tale[MAX_TALE];
char addr[MAX_ADDR];
}PeoInf;
typedef struct Contact {
PeoInf* data;
int count;
int capacity;
}Contact;
int InitContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(Contact* pc);
void DelContact(Contact* pc);
void ModContact(Contact* pc);
void SearchContact(Contact* pc);
void QsortContact(Contact* pc);
void TotalContact(Contact* pc);
void CleanContact(Contact* pc);
void FreeContact(Contact* pc);
//文件保存
void saveContact(Contact* pc);