三、文件操作优化通讯录:
3.1.Savecontact函数的添加(通讯录信息保存)
为了在保存内存中操作完成后的所有联系人信息,我们在程序退出之前将联系人信息以2进制的方式写进文件里面
void SaveContact(contact* con) { FILE* fp = fopen("contact.txt", "wb"); if (fp==NULL) { perror("SaveContact"); } else { printf("正在保存\n"); Sleep(1000); for (int i = 0; i < con->sz; i++) fwrite(con->data + i, sizeof(PeoInfo), 1, fp); fclose(fp); fp = NULL; printf("保存成功\n"); } }
3.2.Loadcontact函数的添加(导入通讯录信息)
在我们对于通讯录进行修改时,要将之前文件中存好的信息导入内存中去,这个步骤也应该在初始化函数中进行,我们将他分装为函数,代码如下:
void LoadContact(contact* con) { FILE* fp = fopen("contact.txt", "rb"); PeoInfo str={ 0 }; if (fp==NULL) { perror("LoadContact"); } else { printf("正在加载>>>\n"); Sleep(1000); int i = 0; while (fread(&str, sizeof(PeoInfo), 1, fp)) { check_capacity(con); con->data[i] = str; con->sz++; i++; } } fclose(fp); fp = NULL; printf("加载成功!\n"); }
四、完整代码展示:
contact.h:
#pragma once #include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #define MAX 100 #define MAX_NAME 20 #define MAX_SEX 5 #define MAX_TELE 12 #define MAX_ADDR 20 #define DEFAULT_SZ 3 #define INC_SZ 2 enum OPTION { Exit = 0, Add = 1, Del, Search, Modify, Print, sort }; typedef struct PeoInfo { char name[MAX_NAME]; char sex[MAX_SEX]; int age; char addr[MAX_ADDR]; char tele[MAX_TELE]; }PeoInfo; //静态版本 //typedef struct contact //{ // PeoInfo data[MAX]; // int sz; //}contact; //动态版本 typedef struct Contact { PeoInfo* data;//指向存放人的信息的空间 int sz;//当前已经放的信息的个数 int capacity;//当前通讯录的最大容量 }contact; //初始化消息 void Initcontact(contact *con); //增加消息 void AddContact(contact *con); //删除信息 void DelContact(contact *con); //查找个别人消息 void SeachContact(contact *con); //修改个别人消息 void ModifyContact(contact* con); //打印全部通讯录 void PrintContact(contact* con); //排序通讯录 void sortContact(contact* con); //保存通讯录中的信息到文件中 void SaveContact(contact* con); //加载文件信息到通讯录 void LoadContact(contact* con);
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" void menu() { printf("**********************************\n"); printf("**********************************\n"); printf("******** 欢迎使用本通讯录 ********\n"); printf("**********************************\n"); printf("***** 本通讯录现提供以下功能 *****\n"); printf("************ 1.Add ***************\n"); printf("************ 2.Del ***************\n"); printf("************ 3.Search ************\n"); printf("************ 4.Modify ************\n"); printf("************ 5.Print *************\n"); printf("************ 6.sort **************\n"); printf("************ 0.exit**************\n"); printf("**********************************\n"); } void Contact() { int input = 0; contact con; Initcontact(&con); do { menu(); printf("请选择>"); scanf("%d", &input); switch (input) { case Add: AddContact(&con); break; case Del: DelContact(&con); break; case Search: SeachContact(&con); break; case Modify: ModifyContact(&con); break; case Print: PrintContact(&con); break; case sort: sortContact(&con); break; case Exit: SaveContact(&con); DestroyContact(&con); printf("已成功退出"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); } int main() { Contact(); return 0; }
contact.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "contact.h" int FindByName(contact* con, char name[]) { assert(con); int i = 0; for (i = 0; i < con->sz; i++) { if (strcmp(con->data[i].name,name) == 0) { return i; } } return -1; } //静态版本: //void Initcontact(contact* con) //{ // assert(con); // con->sz = 0; // memset(con->data, 0, sizeof(con->data)); //} //动态版本: void Initcontact(contact* con) { assert(con); PeoInfo *ptr= (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo)); if (ptr == NULL) { perror("InitContact::calloc"); return; } con->sz = 0; con->capacity = DEFAULT_SZ; con->data = ptr; LoadContact(con); } void DestroyContact(contact* con) { free(con->data); con->data = NULL; con->sz = 0; con->capacity = 0; con = NULL;//?? } //静态add //void AddContact(contact* con) //{ // assert(con); // if (con->sz == 99) // { // printf("通讯录已经存满,请联系操作人员"); // return; // } // printf("请输入联系人姓名:>"); // scanf("%s", con->data[con->sz].name); // printf("请输入联系人性别:>"); // scanf("%s",con->data[con->sz].sex); // printf("请输入联系人年龄:>"); // scanf("%d", &(con->data[con->sz].age)); // printf("请输入联系人联系方式:>"); // scanf("%s", con->data[con->sz].tele); // printf("请输入联系人住址:>"); // scanf("%s", con->data[con->sz].addr); // printf("联系人信息添加成功!\n"); // con->sz++; //} // void check_capacity(contact* con) { assert(con); if (con->sz == con->capacity) { printf("内存已满,正在扩容——\n"); Sleep(1000); PeoInfo* ptr = (PeoInfo*)realloc(con->data, (con->capacity + INC_SZ) * sizeof(PeoInfo)); if (ptr==NULL) { perror("check_capacity::realloc"); return; } con->capacity += INC_SZ; con->data = ptr; printf("扩容成功\n"); } } //动态add void AddContact(contact* con) { assert(con); check_capacity(con); printf("请输入联系人姓名:>"); scanf("%s", con->data[con->sz].name); printf("请输入联系人性别:>"); scanf("%s", con->data[con->sz].sex); printf("请输入联系人年龄:>"); scanf("%d", &(con->data[con->sz].age)); printf("请输入联系人联系方式:>"); scanf("%s", con->data[con->sz].tele); printf("请输入联系人住址:>"); scanf("%s", con->data[con->sz].addr); printf("联系人信息添加成功!\n"); con->sz++; } void DelContact(contact* con) { assert(con); char name[100]; if (con->sz == 0) { printf("通讯录为空,无法删除\n"); return; } printf("请输入要删除人名字:>"); scanf("%s", name); int ret = FindByName(con, name); int i = 0; if (-1 == ret) { printf("没有找到此人\n"); return; } else { for (i = ret; i < con->sz-1; i++) { con->data[i] = con->data[i + 1]; } con->sz--; memset(&con->data[i], 0, sizeof(con->data[i])); printf("删除成功!\n"); } } void SeachContact(contact* con) { assert(con); char name[MAX_NAME]; if (con->sz == 0) { printf("通讯录为空,无法输入\n"); return; } printf("请输入查找人名字"); scanf("%s", name); int ret = FindByName(con, name); if (ret == -1) { printf("您查找的人不存在!\n"); return; } printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", con->data[ret].name, con->data[ret].age, con->data[ret].sex, con->data[ret].addr, con->data[ret].tele); } void ModifyContact(contact* con) { assert(con); char name[MAX_NAME] = { 0 }; if (con->sz == 0) { printf("通讯录为空,无法修改\n"); return; } printf("请输入查找人名字"); scanf("%s", name); int ret = FindByName(con, name); if (-1 == ret) { printf("您要修改的人不存在\n"); return; } printf("请输入联系人姓名:>"); scanf("%s", con->data[ret].name); printf("请输入联系人性别:>"); scanf("%s", con->data[ret].sex); printf("请输入联系人年龄:>"); scanf("%d", &(con->data[ret].age)); printf("请输入联系人住址:>"); scanf("%s", con->data[ret].addr); printf("请输入联系人联系方式:>"); scanf("%s", con->data[ret].tele); printf("联系人信息修改成功!\n"); } void PrintContact(contact* con) { printf("%-10s\t%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","联系人", "姓名", "年龄", "性别", "地址", "电话"); for (int i = 0; i < con->sz; i++) { printf("%-10d\t%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n",i+1, con->data[i].name, con->data[i].age, con->data[i].sex, con->data[i].addr, con->data[i].tele); } } int cmp_con_by_name(const void* e1, const void* e2) { return (strcmp(((PeoInfo *)e1)->name, ((PeoInfo*)e2)->name)); } void sortContact(contact* con) { assert(con); if (0 == con->sz) { printf("通讯录为空,无法排序\n"); return; } qsort(con->data, con->sz, sizeof(con->data[0]), cmp_con_by_name); printf("排序成功\n"); } void SaveContact(contact* con) { FILE* fp = fopen("contact.txt", "wb"); if (fp==NULL) { perror("SaveContact"); } else { printf("正在保持\n"); Sleep(1000); for (int i = 0; i < con->sz; i++) fwrite(con->data + i, sizeof(PeoInfo), 1, fp); fclose(fp); fp = NULL; printf("保存成功\n"); } } void LoadContact(contact* con) { FILE* fp = fopen("contact.txt", "rb"); PeoInfo str={ 0 }; if (fp==NULL) { perror("LoadContact"); } else { printf("正在加载>>>\n"); Sleep(1000); int i = 0; while (fread(&str, sizeof(PeoInfo), 1, fp)) { check_capacity(con); con->data[i] = str; con->sz++; i++; } } fclose(fp); fp = NULL; printf("加载成功!\n"); }
总结:
我们通过文件操作的知识和动态内存空间管理的知识终于完善了动态通讯录的编写!相信大家在自己真正写出来之后都会感觉学有所成!
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!