通讯录--文件保存

本文是基于动态存储的通讯录实现中加以修改:动态存储实现通讯录

增加数据写入文件函数:

//将数据写入文件
void WriteFile(mindan* book) {
 FILE* fp = fopen("test.txt", "w");
 if (fp == NULL) {
  perror("文件打开失败!\n");
  return;
 }
 for (int i = 0; i < book->size; i++) {
  fwrite(&(book->everyone[i]),sizeof(information),1,fp);
 }
 fclose(fp);
}

增加加载文件数据存储:

void LoadFile(mindan* book) {
 FILE* fp = fopen("test.txt", "r");
 if (fp == NULL) {
  perror("文件打开失败!\n");
  return;
 }
 information temp = { 0 };
 int n;
 while (1) {
  n = fread(&temp, sizeof(information), 1, fp);
  if (n < 1) {
   break;
  }
  book->everyone[book->size] = temp;
  book->size++;
  if (book->size > book->num) {
   book->num += 20;
   information* newper = (information*)malloc(book->num*sizeof(information));
   memcpy(newper, book->everyone, book->size*sizeof(information));
   free(book->everyone);
  }
 }
  
}

只要再合适的地方调用两者即实现数据存入文件和

int main() {
 mindan person_info;
 Init(&person_info);
 LoadFile(&person_info);
 //定义函数指针func 代表void(*) (mindan*)
 typedef void(*func)(mindan*);
 func fun_table[] = {
  NULL,
  AddInformation,
  DelInformation,
  FindInformation,
  ReInformation,
  PrintInformation,
  DisInformation,
  SortInformation
 };
 while (1) {
  int choose = meau();
  if (choose < 0||choose > sizeof(fun_table)/sizeof(fun_table[0])) {
   printf("输入无效,请重新输入\n");
   continue;
  }
  if (choose == 0) {
   printf("再见\n");
   WriteFile(&person_info);
   break;
  }
  else {
   fun_table[choose](&person_info);
  }
 }
 system("pause");
 return 0;
}
实训项目,满足以下要求 【要求】 (1)程序的主窗口如左图所示。 程序启动时,窗口左边的“姓名”列表框中显示了本软件中已保存的所有人员姓名,从中选择一个姓名,窗口左边的“详细信息”区域显示出此人的详细通讯录内容。 (2)窗口顶部“城市”和“性别”两个列表框中列出了可供选择的城市名称和姓名。使用这两个控件,可以筛选出感兴趣的内容。例如,在“城市”中选择“南京”,在性别中选择“男”,则在“姓名”列表框中只显示出程序所保存的住在南京的男性人员。选择“城市”和“性别”中的“全部”,则列出所有人员。 (3)单击“添加”按钮 ,弹出一个对话框。通过此对话框,可以添加新的通讯录条目。在添加新条目时,所在城市应从组合框中选择,若组合框中没有想要的城市,可以直接在组合框中键入。要求键入的新城市名能自动添加到“添加”对话框中“所在城市”组合框和主窗口中“城市”组合框的下拉列表中。 (4)在主窗口中点击“删除”按钮 可以删除当前显示的条目。 (5)增加“保存”和“打开”按钮或菜单项,要求能够自动保存所做的添加和删除操作。 (6)所有的数据保存在.txt文件中,并能读出。比如.txt文件的每一行保存一条记录。如:姓名|性别|生日…………【可选用CFile/CStdioFile类】 【提示】创建通讯类,包括姓名、性别、生日、所在城市、工作单位、办公电话、住宅电话等必要信息。
<think>我们根据用户需求,需要实现通讯录数据的文件保存功能。参考引用内容,通讯录通常包含联系人信息(姓名、年龄、性别、电话、地址等),我们需要将通讯录中的这些数据保存文件中,以便下次程序启动时能够读取。步骤:1.定义通讯录数据结构(如结构体数组或链表)2.实现保存文件的函数:将通讯录中的数据写入文件(文本文件或二进制文件)3.实现从文件读取的函数:在程序启动时,从文件中读取数据到通讯录根据引用[1],我们需要使用C语言的文件操作函数,如fopen,fwrite,fread,fclose等。这里我们以二进制文件为例进行读写,因为二进制文件保存结构体数据更为方便。示例代码将包括:-通讯录结构定义(参考引用[2])-保存通讯录文件(SaveContactToFile)-文件加载通讯录到程序(LoadContactFromFile)注意:通讯录结构定义与引用[2]类似,但为了简化,我们使用固定大小的数组,并记录当前联系人数量。代码示例:```#include<stdio.h>#include<string.h>//定义联系人信息结构体#defineMAX_NAME20#defineMAX_SEX6#defineMAX_ADDR30#defineMAX_TELE13#defineMAX_CONTACT1000typedefstructPersonInfo{charname[MAX_NAME];intage;charsex[MAX_SEX];charaddr[MAX_ADDR];tele[MAX_TELE];}PersonInfo;typedefstructContact{PersonInfodata[MAX_CONTACT];//联系人数组intsize;//当前联系人数量}Contact;//保存通讯录文件voidSaveContactToFile(Contact*pcon,constchar*filename){FILE*pf=fopen(filename,"wb");//以二进制写入方式打开文件if(pf==NULL){perror("SaveContactToFile");return;}//先写入当前联系人数量fwrite(&pcon->size,sizeof(int),1,pf);//再写入联系人数组for(inti=0;i<pcon->size;i++){fwrite(&pcon->data[i],sizeof(PersonInfo),1,pf);}fclose(pf);}//从文件加载通讯录voidLoadContactFromFile(Contact*pcon,constchar*filename){FILE*pf=fopen(filename,"rb");//以二进制读取方式打开文件if(pf==NULL){perror("LoadContactFromFile");return;}//先读取联系人数量fread(&pcon->size,sizeof(int),1,pf);//再读取每个联系人信息for(inti=0;i<pcon->size;i++){fread(&pcon->data[i],sizeof(PersonInfo),1,pf);}fclose(pf);}//初始化通讯录(可以从文件加载,也可以初始化为空)voidInitContact(Contact*pcon){memset(pcon,0,sizeof(Contact));//初始化为0//可以选择在这里加载文件,或者由调用者决定}//其他通讯录操作(添加、删除等)这里省略...intmain(){Contactmy_contact;//初始化通讯录InitContact(&my_contact);//尝试从文件加载LoadContactFromFile(&my_contact,"contact.dat");//这里可以进行其他操作,比如添加联系人等//程序退出前保存SaveContactToFile(&my_contact,"contact.dat");return0;}```说明:1.使用二进制文件保存,优点是读写效率高,但缺点是文件内容不可直接阅读,且跨平台性可能受字节序影响。2.在保存时,我们先保存联系人数量(一个整数),然后依次保存每个联系人(结构体)。这样在读取时可以先知道有多少个联系人。3.在程序启动时,调用LoadContactFromFile从文件加载数据到通讯录结构体;在程序退出前,调用SaveContactToFile保存。如果希望保存为文本文件,则可以使用fprintf和fscanf,但需要逐字段读写,并且注意格式。这里以二进制方式为例。注意:如果通讯录结构体中有指针成员,则不能直接这样读写(因为写入的是指针值,而不是指向的内容),但本例中没有指针,所以可行。相关问题:1.如何将通讯录数据保存为文本文件?2.如果通讯录使用动态内存(如链表)存储联系人,文件读写该如何实现?3.文件读写过程中出现错误(如磁盘空间不足)应该如何处理?4.如何保证通讯录文件在多个程序实例同时访问时的数据一致性?5.如何加密通讯录文件以保护用户隐私?</think>### C语言实现通讯录数据文件保存方法 在C语言中实现通讯录数据的文件保存功能,核心是使用文件操作函数(`fopen`, `fwrite`, `fread`, `fclose`等)。以下是具体实现步骤和示例代码: --- #### **1. 定义通讯录数据结构** 参考引用[2][^2]中的结构体定义: ```c // contact.h #define NAME_MAX 20 #define SEX_MAX 6 #define ADDR_MAX 30 #define TELE_MAX 13 typedef struct { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char addr[ADDR_MAX]; char tele[TELE_MAX]; } ContactEntry; typedef struct { ContactEntry entries[MAX_CONTACTS]; // MAX_CONTACTS=1000 int count; // 当前联系人数量 } ContactBook; ``` --- #### **2. 保存通讯录文件** 使用二进制写入模式(`"wb"`)保存数据: ```c #include <stdio.h> void SaveToFile(ContactBook* book, const char* filename) { FILE* fp = fopen(filename, "wb"); if (!fp) { perror("文件打开失败"); return; } // 先写入联系人数量 fwrite(&book->count, sizeof(int), 1, fp); // 写入所有联系人数据 fwrite(book->entries, sizeof(ContactEntry), book->count, fp); fclose(fp); printf("数据已保存至 %s\n", filename); } ``` --- #### **3. 从文件加载通讯录** 使用二进制读取模式(`"rb"`)加载数据: ```c void LoadFromFile(ContactBook* book, const char* filename) { FILE* fp = fopen(filename, "rb"); if (!fp) { perror("文件打开失败"); return; } // 读取联系人数量 fread(&book->count, sizeof(int), 1, fp); // 读取联系人数据 fread(book->entries, sizeof(ContactEntry), book->count, fp); fclose(fp); printf("已从 %s 加载 %d 条记录\n", filename, book->count); } ``` --- #### **4. 主函数调用示例** ```c int main() { ContactBook myBook; // 初始化通讯录(可添加数据) // AddContact(&myBook, "张三", 30, "男", "北京", "13800138000"); // 保存数据到文件 SaveToFile(&myBook, "contacts.dat"); // 从文件加载数据 ContactBook loadedBook; LoadFromFile(&loadedBook, "contacts.dat"); return 0; } ``` --- #### **关键点说明** 1. **二进制文件优势** - 直接读写结构体,无需格式转换 - 效率高于文本文件(尤其大数据量时) - 支持复杂数据类型(如`int`) 2. **错误处理** - 检查`fopen`返回值(避免空指针) - 使用`perror`输出错误原因 3. **数据完整性** - 先写入数量(`count`),再写入数组 - 确保读取顺序与写入一致 4. **文件路径** - 使用相对路径(如`"contacts.dat"`)或绝对路径 --- ### 文本文件保存方法(可选) 若需人类可读格式,改用文本模式: ```c void SaveAsText(ContactBook* book, const char* filename) { FILE* fp = fopen(filename, "w"); for (int i = 0; i < book->count; i++) { fprintf(fp, "%s,%d,%s,%s,%s\n", book->entries[i].name, book->entries[i].age, book->entries[i].sex, book->entries[i].addr, book->entries[i].tele); } fclose(fp); } ``` --- ### 注意事项 1. **结构体对齐问题** 二进制读写时,确保结构体无填充字节(可用`#pragma pack(1)`)。 2. **文件路径权限** 检查程序是否有权读写目标文件。 3. **数据加密** 敏感信息(如电话)可先加密再存储。 通过上述方法,可实现通讯录数据的持久化存储,解决程序重启后数据丢失的问题[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值