• C语言版——通讯录进阶(文件版本)


    前言

            在之前,我讲解了通讯录管理系统的项目程序,分别是:

    普通版通讯录项目(静态开辟内存版): C语言版通讯录操作系统_

    和进阶版通讯录项目(动态内存开辟版): C语言版通讯录——动态存储(进阶版)

            接下来,我再来讲一讲文件版本的通讯录,文件版本有个好处就是可以将调试过的程序的信息保存下来,就像一个小型简单版数据库一样。

    一.代码实现:

    1.保存调试信息写入文件中

            首先需要将程序被调试时填写的信息保存下来,写入到文件中,需要用到一个函数SaveContact();它的位置是在结束调试的分支语句中:

     在Contact.c函数实现中:

    1. void SaveContact(Contact* pc) {
    2. //创造文件并打开,
    3. FILE* fw = fopen("Contact.txt", "wb");
    4. if (fw == NULL) {
    5. printf("%s\n", strerror(errno));
    6. return 1;
    7. }
    8. //写文件
    9. else {
    10. int i = 0;
    11. for (i = 0; i < pc->count; i++) {
    12. fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
    13. }
    14. }
    15. //关闭文件
    16. fclose(fw);
    17. fw = NULL;
    18. }

            代码讲解: 先创建文件指针接收fpoen函数创建出来的Contact.txt文件返回值,文件的打开模式是"wb","wb"是二进制写文件方式。然后通过if语句去判断指针是否打开文件成功,若成功,则继续下一步:将信息写入到文件中。写入文件的步骤是通过循环的方式,将PeoInf结构体类型的成员数据一个一个往进放,最后关闭文件。

            注:使用"wb"文件打开方式,打开时每次打开文件时会生成一个新的空文件覆盖原有的文件,则每次保存的时候都会重新录一遍信息,这样就可以通讯录的实时性,即删除联系人时再保存会把删除之后的联系人信息重新录进文件(原有的信息全部擦除)

    增加两个成员:

               

     

     显示成员:

        

    按0结束调试: 

     

     

    文件内容: 

     

            如上图,通过程序调试填写的信息经过fwrite函数就可以写入文件Contact.txt中了,因为是二进制形式往里面存入,所以会有一些乱码情况(这个不打紧)。

    2. 加载信息到通讯录程序中

    在Contact.c中:

    1. //扩容
    2. void check_key(Contact* pc) {
    3. assert(pc);
    4. if (pc->count == pc->capacity) {
    5. PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
    6. if (str == NULL) {
    7. printf("%s\n", strerror(errno));
    8. return 1;
    9. }
    10. else {
    11. pc->data = str;
    12. pc->capacity += 2;
    13. printf("增容成功\n");
    14. }
    15. }
    16. }
    17. //加载文件信息到通讯录中
    18. void LoadContact(Contact* pc) {
    19. FILE* fr = fopen("Contact.txt", "rb");
    20. if (fr == NULL) {
    21. printf("%s\n", strerror(errno));
    22. return -1;
    23. }
    24. //读取文件信息
    25. PeoInf tmp = { 0 };
    26. while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
    27. check_key(pc);
    28. pc->data[pc->count] = tmp;
    29. pc->count++;
    30. }
    31. //关闭文件
    32. fclose(fr);
    33. fr = NULL;
    34. }
    35. int InitContact(Contact* pc) {
    36. assert(pc);
    37. pc->capacity = CA_begin;
    38. pc->count = 0;
    39. pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
    40. if (pc->data == NULL) {
    41. printf("%s\n", strerror(errno));
    42. return -1;
    43. }
    44. //加载文件信息到通讯录中
    45. LoadContact(pc);
    46. return 0;
    47. }

            LoadContact函数是用来实现加载信息到通讯录程序中的作用,它需要被放在初始化通讯录函数InitContact()中,LoadContact()函数的实现也是通过文件指针打开之前创建好的Contact.txt文件,使用fread函数读取文件中每个人的信息数据,需要调用扩容函数。

    调试结果:

     

    二.完整代码实现:

    test.c:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. # include
    3. #include"Contact.h"
    4. enum {
    5. EXIT,
    6. ADD,
    7. DELETE,
    8. MODIFY,
    9. SEARCH,
    10. SHOW,
    11. QSORT,
    12. TOTAL,
    13. CLEAN
    14. };
    15. void menu() {
    16. printf("**************通讯录管理系统界面***************\n");
    17. printf("********************0.Exit.********************\n");
    18. printf("********************1.Add. ********************\n");
    19. printf("********************2.Delete.******************\n");
    20. printf("********************3.Mod. ********************\n");
    21. printf("********************4.Search.******************\n");
    22. printf("********************5.Show.********************\n");
    23. printf("********************6.Sqort.*******************\n");
    24. printf("********************7.Total.*******************\n");
    25. printf("********************8.Clean.*******************\n");
    26. }
    27. int main() {
    28. int input = 0;
    29. Contact con;
    30. //初始化通讯录
    31. InitContact(&con);
    32. do {
    33. menu();
    34. printf("请输入你的选择:\n");
    35. scanf("%d", &input);
    36. switch (input) {
    37. case EXIT:
    38. SaveContact(&con);//文件保存
    39. FreeContact(&con);
    40. printf("即将退出程序\n");
    41. break;
    42. case ADD:
    43. AddContact(&con);
    44. break;
    45. case DELETE:
    46. DelContact(&con);
    47. break;
    48. case MODIFY:
    49. ModContact(&con);
    50. break;
    51. case SEARCH:
    52. SearchContact(&con);
    53. break;
    54. case SHOW:
    55. ShowContact(&con);
    56. break;
    57. case QSORT:
    58. QsortContact(&con);
    59. break;
    60. case TOTAL:
    61. TotalContact(&con);
    62. break;
    63. case CLEAN:
    64. CleanContact(&con);
    65. break;
    66. default:
    67. printf("输入错误\n");
    68. break;
    69. }
    70. } while (input);
    71. return 0;
    72. }

    Contact.c:

    1. #include"Contact.h"
    2. //扩容
    3. void check_key(Contact* pc) {
    4. assert(pc);
    5. if (pc->count == pc->capacity) {
    6. PeoInf* str = realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInf));
    7. if (str == NULL) {
    8. printf("%s\n", strerror(errno));
    9. return 1;
    10. }
    11. else {
    12. pc->data = str;
    13. pc->capacity += 2;
    14. printf("增容成功\n");
    15. }
    16. }
    17. }
    18. //加载文件信息到通讯录中
    19. void LoadContact(Contact* pc) {
    20. FILE* fr = fopen("Contact.txt", "rb");
    21. if (fr == NULL) {
    22. printf("%s\n", strerror(errno));
    23. return -1;
    24. }
    25. //读取文件信息
    26. PeoInf tmp = { 0 };
    27. while (fread(&tmp, sizeof(PeoInf), 1, fr) == 1) {
    28. check_key(pc);
    29. pc->data[pc->count] = tmp;
    30. pc->count++;
    31. }
    32. //关闭文件
    33. fclose(fr);
    34. fr = NULL;
    35. }
    36. int InitContact(Contact* pc) {
    37. assert(pc);
    38. pc->capacity = CA_begin;
    39. pc->count = 0;
    40. pc->data =(PeoInf*)calloc(CA_begin, sizeof(PeoInf));
    41. if (pc->data == NULL) {
    42. printf("%s\n", strerror(errno));
    43. return -1;
    44. }
    45. //加载文件信息到通讯录中
    46. LoadContact(pc);
    47. return 0;
    48. }
    49. //添加
    50. void AddContact(Contact* pc){
    51. assert(pc);
    52. check_key(pc);
    53. printf("正在准备添加功能验证:\n");
    54. printf("开始添加:\n");
    55. printf("请输入成员姓名:\n");
    56. scanf("%s", pc->data[pc->count].name);
    57. printf("请输入成员年龄:\n");
    58. scanf("%d", &(pc->data[pc->count].age));
    59. printf("请输入成员性别:\n");
    60. scanf("%s", pc->data[pc->count].sex);
    61. printf("请输入成员电话:\n");
    62. scanf("%s", pc->data[pc->count].tale);
    63. printf("请输入成员地址:\n");
    64. scanf("%s", pc->data[pc->count].addr);
    65. pc->count++;
    66. printf("添加成功\n");
    67. }
    68. //显示
    69. void ShowContact(Contact* pc) {
    70. assert(pc);
    71. if (pc->count == 0) {
    72. printf("通讯录为空,无法查看成员\n");
    73. return;
    74. }
    75. else {
    76. printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
    77. int i = 0;
    78. for (i = 0; i < pc->count; i++) {
    79. printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[i].name,
    80. pc->data[i].age,
    81. pc->data[i].sex,
    82. pc->data[i].tale,
    83. pc->data[i].addr
    84. );
    85. }
    86. }
    87. }
    88. //查找函数
    89. int Find_name(Contact* pc, char name[]) {
    90. assert(pc);
    91. int i = 0;
    92. for (i = 0; i < pc->count; i++) {
    93. if (strcmp(pc->data[i].name, name) == 0) {
    94. return i;
    95. }
    96. }
    97. return -1;
    98. }
    99. //删除
    100. void DelContact(Contact* pc) {
    101. assert(pc);
    102. char name[MAX_NAME] = { 0 };
    103. if (pc->count == 0) {
    104. printf("通讯录为空,无法进行删除\n");
    105. return;
    106. }
    107. else {
    108. printf("请输入要删除人的名字:\n");
    109. scanf("%s", name);
    110. int ret = Find_name(pc, name);
    111. if (ret == -1) {
    112. printf("该成员不存在\n");
    113. return;
    114. }
    115. else {
    116. printf("正在准备删除功能验证:\n");
    117. int i = 0;
    118. for (i = ret; i < pc->count - 1; i++) {
    119. pc->data[i] = pc->data[i + 1];
    120. }
    121. pc->count--;
    122. printf("删除成功\n");
    123. }
    124. }
    125. }
    126. void ModContact(Contact* pc) {
    127. assert(pc);
    128. char name[MAX_NAME] = { 0 };
    129. if (pc->count == 0) {
    130. printf("通讯录为空,无法进行修改\n");
    131. return;
    132. }
    133. else {
    134. printf("请输入要修改的人员名单:\n");
    135. scanf("%s", name);
    136. int ret = Find_name(pc, name);
    137. if (ret == -1) {
    138. printf("该成员不存在\n");
    139. return;
    140. }
    141. else {
    142. printf("正在进行修改功能验证:\n");
    143. printf("修改开始:\n");
    144. printf("请输入成员姓名:\n");
    145. scanf("%s", pc->data[ret].name);
    146. printf("请输入成员年龄:\n");
    147. scanf("%d", &(pc->data[ret].age));
    148. printf("请输入成员性别:\n");
    149. scanf("%s", pc->data[ret].sex);
    150. printf("请输入成员电话:\n");
    151. scanf("%s", pc->data[ret].tale);
    152. printf("请输入成员地址:\n");
    153. scanf("%s", pc->data[ret].addr);
    154. printf("\n修改成功\n");
    155. }
    156. }
    157. }
    158. //查找功能
    159. void SearchContact(Contact* pc) {
    160. assert(pc);
    161. char name[MAX_NAME] = { 0 };
    162. if (pc->count == 0) {
    163. printf("通讯录为空,无法进行查找\n");
    164. return;
    165. }
    166. else {
    167. printf("请输入要查找的人员名单:\n");
    168. scanf("%s", name);
    169. int ret = Find_name(pc, name);
    170. if (ret == -1) {
    171. printf("该成员不存在\n");
    172. return;
    173. }
    174. else {
    175. printf("%-20s\t %-4s\t %-5s\t %-12s\t %-20s\n", "姓名", "年龄", "性别", "电话", "地址");
    176. printf("%-20s\t %-4d\t %-5s\t %-12s\t %-20s\n", pc->data[ret].name,
    177. pc->data[ret].age,
    178. pc->data[ret].sex,
    179. pc->data[ret].tale,
    180. pc->data[ret].addr
    181. );
    182. printf("\n查找成功\n");
    183. }
    184. }
    185. }
    186. int cmp_by_name(const void* e1, const void* e2) {
    187. return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
    188. }
    189. int cmp_by_age(const void* e1, const void* e2) {
    190. return ((PeoInf*)e1)->age-((PeoInf*)e2)->age;
    191. }
    192. //排序功能
    193. void QsortContact(Contact* pc) {
    194. assert(pc);
    195. int i = 0;
    196. printf("1.按姓名排序 2.按年龄排序 \n");
    197. printf("请输入你要进行哪种排序方法?\n");
    198. scanf("%d", &i);
    199. if (i == 1) {
    200. qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_name);
    201. }
    202. else if (i == 2) {
    203. qsort(pc->data, pc->count, sizeof(PeoInf), cmp_by_age);
    204. }
    205. printf("排序成功\n");
    206. }
    207. //统计
    208. void TotalContact(Contact* pc) {
    209. assert(pc);
    210. if (pc->count == 0) {
    211. printf("通讯录为空,人员为0\n");
    212. return;
    213. }
    214. int count = pc->count;
    215. printf("此时通讯录内共有%d个成员\n", count);
    216. }
    217. int Clean(Contact * pc) {
    218. assert(pc);
    219. pc->capacity = CA_begin;
    220. pc->count = 0;
    221. pc->data = (PeoInf*)calloc(CA_begin, sizeof(PeoInf));
    222. if (pc->data == NULL) {
    223. printf("%s\n", strerror(errno));
    224. return -1;
    225. }
    226. return 0;
    227. }
    228. //一键清空
    229. void CleanContact(Contact* pc) {
    230. assert(pc);
    231. if (pc->count == 0) {
    232. printf("通讯录已为空,无法再执行此操作\n");
    233. return;
    234. }
    235. int i=0;
    236. printf("请问您确定要清空通讯录吗?确认请按9,否则按9以外的任意键\n");
    237. scanf("%d",&i);
    238. if (i == 9) {
    239. Clean(pc);
    240. printf("清空成功\n");
    241. }
    242. else if (i == 8) {
    243. return;
    244. }
    245. }
    246. void SaveContact(Contact* pc) {
    247. FILE* fw = fopen("Contact.txt", "wb");
    248. if (fw == NULL) {
    249. printf("%s\n", strerror(errno));
    250. return 1;
    251. }
    252. //写文件
    253. else {
    254. int i = 0;
    255. for (i = 0; i < pc->count; i++) {
    256. fwrite(pc->data + i, sizeof(PeoInf), 1, fw);
    257. }
    258. }
    259. //关闭文件
    260. fclose(fw);
    261. fw = NULL;
    262. }
    263. void FreeContact(Contact* pc) {
    264. free(pc->data);
    265. pc->data = NULL;
    266. }

    Contact.h:

    1. #pragma once
    2. #define _CRT_SECURE_NO_WARNINGS 1
    3. # include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define MAX_NAME 20
    9. #define MAX_SEX 5
    10. #define MAX_TALE 12
    11. #define MAX_ADDR 20
    12. #define CA_begin 3
    13. #define Add_every 2
    14. typedef struct PeoInf {
    15. char name[MAX_NAME];
    16. int age;
    17. char sex[MAX_SEX];
    18. char tale[MAX_TALE];
    19. char addr[MAX_ADDR];
    20. }PeoInf;
    21. typedef struct Contact {
    22. PeoInf* data;
    23. int count;
    24. int capacity;
    25. }Contact;
    26. int InitContact(Contact* pc);
    27. void AddContact(Contact* pc);
    28. void ShowContact(Contact* pc);
    29. void DelContact(Contact* pc);
    30. void ModContact(Contact* pc);
    31. void SearchContact(Contact* pc);
    32. void QsortContact(Contact* pc);
    33. void TotalContact(Contact* pc);
    34. void CleanContact(Contact* pc);
    35. void FreeContact(Contact* pc);
    36. //文件保存
    37. void saveContact(Contact* pc);

     

  • 相关阅读:
    浅谈无脚本自动化测试
    C++学习前言
    谈谈作用域链和闭包
    std::thread简单使用
    人脸检测及追踪回顾
    Linux之挂载新的硬盘
    汽车诊断仪算法保护芯片——LKT4305-GM
    Qt-OpenCV学习笔记--图像的腐蚀--erode()
    一看就懂:正则表达式不用背
    KG-开源项目:CMeKG【利用自然语言处理与文本挖掘技术,基于大规模医学文本数据,以人机结合的方式研发的中文医学知识图谱】
  • 原文地址:https://blog.csdn.net/weixin_69283129/article/details/126165384