前言
在之前,我讲解了通讯录管理系统的项目程序,分别是:
普通版通讯录项目(静态开辟内存版): C语言版通讯录操作系统_
和进阶版通讯录项目(动态内存开辟版): C语言版通讯录——动态存储(进阶版)
接下来,我再来讲一讲文件版本的通讯录,文件版本有个好处就是可以将调试过的程序的信息保存下来,就像一个小型简单版数据库一样。
首先需要将程序被调试时填写的信息保存下来,写入到文件中,需要用到一个函数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中了,因为是二进制形式往里面存入,所以会有一些乱码情况(这个不打紧)。
在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函数读取文件中每个人的信息数据,需要调用扩容函数。
调试结果:
- #define _CRT_SECURE_NO_WARNINGS 1
- # include
- #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;
- }
- #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;
- }
- #pragma once
- #define _CRT_SECURE_NO_WARNINGS 1
- # include
- #include
- #include
- #include
- #include
-
- #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);