• 学C的第三十一天【通讯录的实现】


    =========================================================================

    相关代码gitee自取C语言学习日记: 加油努力 (gitee.com)

     =========================================================================

    接上期

    学C的第三十天【自定义类型:结构体、枚举、联合】_高高的胖子的博客-CSDN博客

     =========================================================================

                         

    通讯录需求:

                 

    实现一个通讯录

    通讯录中存放保存人的信息

    名字年龄性别

    电话地址

                 

            通讯录相关功能

    • 通讯录中可以存放100个人的信息
    • 增加联系人
    • 删除指定联系人
    • 修改指定联系人
    • 查找指定联系人
    • 显示所有联系人的信息
    • 排序功能

             

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

    多文件实现通讯录

    (1). contact.h文件 -- 相关函数和结构体类型的声明:

                   

    1 . 结构体 struct PeoInfo -- 存放通讯录联系人的信息:

                    

    使用 typedef 重命名结构体

    struct PeoInfo 重命名PeoInfo

    方便后续使用

                  

    图示:

                  

                  

    2 . 结构体 struct contact -- 通讯录类型:

                    

    使用 typedef 重命名结构体, 

                         

    创建通讯录信息结构体变量数组

                        

    创建一个变量来记录当前通讯录data的人数

                          

    图示:

                         

                  

    3 . 函数 InitContact() 的声明 -- 初始化通讯录类型变量

                    

    参数接收 -- 通讯录类型变量地址

    返回类型 -- void

                       

    图示:

                         

                  

    4 . 函数 AddContact() 的声明 -- 增加通讯录成员:

                    

    参数接收 -- 通讯录类型变量地址

    返回类型 -- void

                     

    图示:

                         

                  

    5 . 对常量使用进行优化 -- 设置 全局变量 和 枚举

                     

    (一). 

    设置 全局变量

    contact.h 中,

    定义全局变量 MAX 100 -- 设置通讯录最多人数,

    其它通讯录信息也是同理

    图示:

                    

    (二). 

    设置 枚举

    对测试中,用户输入的选项进行枚举

    用对应的功能名字代表对应的选项

                     

    在 contact.h 文件中设置好后,

    在 test.c 文件中进行修改

    图示:

                         

                  

    6 . 函数 ShowContact() 的声明 -- 打印通讯录所有成员信息:

                    

    参数接收 -- const Contact* pc

    只是打印,不用修改所以设置为常量

               

    返回类型 -- void

                      

    图示:

                         

                  

    7 . 函数 FindByName() 的声明 -- 删除指定通讯录成员信息:

                    

    参数接收 -- 通讯录类型变量地址 要查找的名字字符串

    返回类型 -- int,返回找到的元素下标 或 未找到情况的-1

             

    注:

    该函数只在 contact.c文件 中支持其它函数,
    为了保密可以不在该文件声明

                   

    图示:

                         

                  

    8 . 函数 DelContact() 的声明 -- 删除指定通讯录成员信息:

                    

    参数接收 -- 通讯录类型变量地址

    返回类型 -- void

                     

    图示:

                         

                         

    9 . 函数 SearchContact() 的声明 -- 查找指定通讯录成员信息:

                    

    参数接收 -- const Contact* pc

    只是打印,不用修改所以设置为常量

               

    返回类型 -- void

                       

    图示:

                         

                  

    10 . 函数 ModifyContact() 的声明 -- 查找指定通讯录成员信息:

                    

    参数接收 -- 通讯录类型变量地址

    返回类型 -- void

                     

    图示:

                         

    该文件对应代码:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. //contact.h文件 -- 相关函数和类型的声明:
    3. //包含头文件:
    4. #include
    5. #include
    6. #include
    7. //定义全局变量 MAX 100 -- 设置通讯录最多人数
    8. #define MAX 100
    9. //通讯录信息也是同理:
    10. #define MAX_NAME 20
    11. #define MAX_SEX 5
    12. #define MAX_TELE 12
    13. #define MAX_ADDR 30
    14. //对测试中,用户输入的选项进行枚举,
    15. //用对应的功能名字代表对应的选项:
    16. enum OPTION
    17. {
    18. //枚举中的内容默认0开始往后排:
    19. EXIT, // 0 对应 退出
    20. ADD, // 1 对应 增加
    21. DEL, // 2 对应 删除
    22. SEARCH, // 3 对应 搜索
    23. MODIFY, // 4 对应 修改
    24. SHOW, // 5 对应 显示所有
    25. SORT // 6 对应 排序
    26. };
    27. //1.结构体 struct PeoInfo -- 存放保存人的信息:
    28. //使用 typedef 重命名结构体,
    29. typedef struct PeoInfo
    30. {
    31. char name[MAX_NAME]; //名字
    32. int age; //年龄
    33. char sex[MAX_SEX]; //性别
    34. char tele[MAX_TELE]; //电话
    35. char addr[MAX_ADDR]; //地址
    36. }PeoInfo;
    37. //2.结构体 struct contact -- 通讯录类型:
    38. //使用 typedef 重命名结构体,
    39. typedef struct contact
    40. {
    41. //创建通讯信息录结构体变量数组:
    42. PeoInfo data[MAX];
    43. //创建一个变量来记录当前通讯录data的人数:
    44. int sz;
    45. }Contact;
    46. //3.函数 InitContact() 的声明 -- 初始化通讯录类型变量
    47. void InitContact(Contact* pc);
    48. //4.函数 AddContact() 的声明 -- 增加通讯录成员:
    49. void AddContact(Contact* pc);
    50. //6.函数 ShowContact() 的声明 -- 打印通讯录所有成员信息:
    51. void ShowContact(const Contact* pc);
    52. //7.函数 FindByName() 的声明 -- 删除指定通讯录成员信息:
    53. //该函数只在 contact.c文件 中支持其它函数,
    54. //为了保密可以不在该文件声明
    55. int FindByName(Contact* pc, char name[]);
    56. //8.函数 DelContact() 的声明 -- 删除指定通讯录成员信息:
    57. void DelContact(Contact* pc);
    58. //9.函数 SearchContact() 的声明 -- 查找指定通讯录成员信息:
    59. void SearchContact(const Contact* pc);
    60. //10 . 函数 ModifyContact() 的声明 -- 查找指定通讯录成员信息:
    61. void ModifyContact(Contact* pc);

                         

    ————————————————————————————————————————

                        

    (2). contact.c文件 -- 自定义函数的实现:

                  

    1 . 函数 InitContact() -- 初始化通讯录类型变量

                    

    contact.h文件包含 头文件

    再在 contact.c文件包含通讯录函数声明头文件:

                  

    使用 memset系统函数初始化data数组

    参数1被设置的空间 -- data

    参数2要设置的值 -- 0 (全部初始化为0)

    参数3要设置的空间大小 -- sizeof(pc->data) ,直接计算出大小

                        

    联系人个数 sz 初始化为0

                       

    图示:

                         

                  

    2 . 函数 AddContact() -- 增加通讯录成员:

                    

    增加的前提还没放满

    判断通讯录是否人数已满

                     

    如果未满则开始添加信息

    sz data数组 的下标对应的,
    所以可以通过 sz 找到 data 的对应元素
    通过对应元素找到对应元素的相应信息

    如果对应的信息是数组,可以不加 取地址符&

    使用 scanf()函数 将信息放进去

                   

    添加完一个联系人后,将指针移向下一个联系人位置

                   

    打印添加成功信息

                       

    图示:

                         

                  

    3 . 函数 ShowContact() -- 打印通讯录所有成员信息:

                    

    打印列标题

    再使用 for循环 循环打印信息

    注意巧用 printf()函数

                

    图示:

                         

                  

    4 . 函数 FindByName() -- 删除指定通讯录成员信息:

                    

    使用 for循环 循环在通讯录中查找该人坐标

    使用 strcmp函数 进行判断名字是否存在

    如果找到了则返回下标未找到则返回-1

                    

    图示:

                         

                  

    5 . 函数 DelContact() -- 删除指定通讯录成员信息:

                    

    判断通讯录是否为空为空没法删除则直接返回

                    

    不为空

    输入接收删除的联系人名字

                     

    调用 FindByName()函数 在通讯录中查找该人下标

                   

    未找到打印相应信息并返回

             

    找到了删除该下标的联系人

                

    删除后,将指针向前移一位

                

    最后打印删除成功

                     

    图示:

                         

                  

    6 . 函数 SearchContact() -- 查找指定通讯录成员信息:

                    

    输入接收查找的联系人名字

                     

    调用 FindByName()函数 在通讯录中查找该人下标

                   

    未找到打印相应信息并返回

             

    找到了打印该下标的联系人信息

                   

    图示:

                         

                  

    7 . 函数 ModifyContact() -- 查找指定通讯录成员信息:

                    

    输入接收修改的联系人名字

                     

    调用 FindByName()函数 在通讯录中查找该人下标

                   

    未找到打印相应信息并返回

             

    找到了修改该下标联系人信息

                   
     图示:

                         

    该文件对应代码:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. //contact.c文件 -- 自定义函数的实现:
    3. //包含头文件:
    4. #include "contact.h"
    5. //1.函数 InitContact() --初始化通讯录类型变量
    6. void InitContact(Contact* pc)
    7. {
    8. //断言:
    9. assert(pc);
    10. memset(pc->data, 0, sizeof(pc->data));
    11. /*使用 memset系统函数,初始化data数组。
    12. 参数1:被设置的空间 -- data
    13. 参数2:要设置的指-- 0 (全部初始化为0)
    14. 参数3:要设置的空间大小-- sizeof(pc->data) ,
    15. 直接计算出大小*/
    16. //联系人个数初始化为0:
    17. pc->sz = 0;
    18. }
    19. //2.函数 AddContact() 的声明 -- 增加通讯录成员:
    20. void AddContact(Contact* pc)
    21. {
    22. //断言:
    23. assert(pc);
    24. //增加的前提是还没放满:
    25. if (pc->sz == MAX)
    26. {
    27. printf("通讯录已满,无法添加\n");
    28. //无法添加直接返回:
    29. return;
    30. }
    31. //没满则开始增加信息:
    32. // sz 和 data数组 的下标是对应的,
    33. // 所以可以通过 sz 找到 data 的对应元素,
    34. // 再通过对应元素找到对应元素的相应信息
    35. // 如果对应的信息是数组。可以不加&
    36. //名字:
    37. printf("请输入名字:>");
    38. //使用 scanf()函数 将信息放进去
    39. scanf("%s", pc->data[pc->sz].name);
    40. //年龄:
    41. printf("请输入年龄:>");
    42. //使用 scanf()函数 将信息放进去
    43. scanf("%d", &pc->data[pc->sz].age);
    44. //性别:
    45. printf("请输入性别:>");
    46. //使用 scanf()函数 将信息放进去
    47. scanf("%s", pc->data[pc->sz].sex);
    48. //电话:
    49. printf("请输入电话:>");
    50. //使用 scanf()函数 将信息放进去
    51. scanf("%s", pc->data[pc->sz].tele);
    52. //地址:
    53. printf("请输入地址:>");
    54. //使用 scanf()函数 将信息放进去
    55. scanf("%s", pc->data[pc->sz].addr);
    56. //添加完一个联系人后,将指针移向下一个联系人位置:
    57. pc->sz++;
    58. //打印添加成功信息:
    59. printf("成功添加联系人\n");
    60. }
    61. //3 . 函数 ShowContact() -- 打印通讯录所有成员信息:
    62. void ShowContact(const Contact* pc)
    63. {
    64. //断言:
    65. assert(pc);
    66. printf("\n");
    67. //打印列标题:
    68. printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n",
    69. "名字", "年龄", "性别", "电话", "地址");
    70. //使用 for循环 循环打印信息:
    71. int i = 0;
    72. for (i = 0; i < pc->sz; i++)
    73. {
    74. printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
    75. pc->data[i].age,
    76. pc->data[i].sex,
    77. pc->data[i].tele,
    78. pc->data[i].addr
    79. );
    80. // %20S:打印20个字符,这里名字是20个字符
    81. // \t: 使用制表符进行对齐
    82. // %4d:打印4个整型,这里是年龄
    83. // “-”号 :左对齐
    84. }
    85. printf("\n");
    86. }
    87. //4 . 函数 FindByName() -- 删除指定通讯录成员信息:
    88. int FindByName(const Contact* pc, char name[])
    89. {
    90. //遍历查找该人坐标:
    91. int i = 0;
    92. for (i = 0; i < pc->sz; i++)
    93. {
    94. if (strcmp(pc->data[i].name, name) == 0)
    95. //如果 找到了一个下标元素的name 和 要找的name 一样
    96. {
    97. return i; //返回此时找到的下标
    98. }
    99. }
    100. return -1; //未找到则返回-1
    101. }
    102. //5 . 函数 DelContact() --删除指定通讯录成员信息:
    103. void DelContact(Contact* pc)
    104. {
    105. //断言:
    106. assert(pc);
    107. //先判断通讯录是否为空:
    108. if (pc->sz == 0)
    109. {
    110. //为空就没法删除了,直接返回
    111. printf("通讯录为空,无法删除\n");
    112. return;
    113. }
    114. //创建存放要删除联系人名字的字符数组:
    115. char name[MAX_NAME] = { 0 };
    116. //输入并接收删除联系人名字:
    117. printf("请输入要删除的人名字:>");
    118. scanf("%s", name);
    119. //因为在通讯录中查找某人是多个功能所需要的,
    120. //所以可以将其封装成函数,再调用:
    121. int del = FindByName(pc, name);
    122. //如果del为-1,说明未找到:
    123. if (del == -1)
    124. {
    125. printf("要删除的人不存在\n");
    126. return; //直接返回
    127. }
    128. //如果找到了则删除坐标为del的联系人:
    129. int i = 0;
    130. for (i = del; i < pc->sz-1; i++)
    131. //从del下标开始,到倒数第二个元素
    132. {
    133. pc->data[i] = pc->data[i + 1];
    134. //把del后1个元素赋给del,循环覆盖掉del的元素
    135. //倒数第二个元素+1 为最后一个元素为止
    136. }
    137. //删除一个后,将pc指针向前移一位:
    138. pc->sz--;
    139. //打印提示:
    140. printf("成功删除该联系人\n");
    141. }
    142. //6 . 函数 SearchContact() -- 查找指定通讯录成员信息:
    143. void SearchContact(const Contact* pc)
    144. {
    145. //断言:
    146. assert(pc);
    147. //创建存放要查找的联系人名字的字符数组:
    148. char name[MAX_NAME] = { 0 };
    149. //输入并接收要查找联系人名字:
    150. printf("请输入要查找的联系人名字:>");
    151. scanf("%s", name);
    152. //使用 FindByName() 函数查找该人在通讯录中的下标:
    153. int pos = FindByName(pc, name);
    154. //如果del为-1,说明未找到:
    155. if (pos == -1)
    156. {
    157. printf("要查找的人不存在\n");
    158. return; //直接返回
    159. }
    160. else //找到了则打印该人信息:
    161. {
    162. //打印列标题:
    163. printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n",
    164. "名字", "年龄", "性别", "电话", "地址");
    165. //打印对应信息:
    166. printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name,
    167. pc->data[pos].age,
    168. pc->data[pos].sex,
    169. pc->data[pos].tele,
    170. pc->data[pos].addr);
    171. }
    172. }
    173. //7 . 函数 ModifyContact() -- 查找指定通讯录成员信息:
    174. void ModifyContact(Contact* pc)
    175. {
    176. //断言:
    177. assert(pc);
    178. //创建存放要修改的联系人名字的字符数组:
    179. char name[MAX_NAME] = { 0 };
    180. //输入并接收要修改联系人名字:
    181. printf("请输入要修改的联系人名字:>");
    182. scanf("%s", name);
    183. //使用 FindByName() 函数查找该人在通讯录中的下标:
    184. int pos = FindByName(pc, name);
    185. //如果del为-1,说明未找到:
    186. if (pos == -1)
    187. {
    188. printf("要修改的人不存在\n");
    189. return; //直接返回
    190. }
    191. else //找到了则修改该人信息:
    192. {
    193. //名字:
    194. printf("请输入名字:>");
    195. //使用 scanf()函数 将信息放进去
    196. scanf("%s", pc->data[pos].name);
    197. //年龄:
    198. printf("请输入年龄:>");
    199. //使用 scanf()函数 将信息放进去
    200. scanf("%d", &pc->data[pos].age);
    201. //性别:
    202. printf("请输入性别:>");
    203. //使用 scanf()函数 将信息放进去
    204. scanf("%s", pc->data[pos].sex);
    205. //电话:
    206. printf("请输入电话:>");
    207. //使用 scanf()函数 将信息放进去
    208. scanf("%s", pc->data[pos].tele);
    209. //地址:
    210. printf("请输入地址:>");
    211. //使用 scanf()函数 将信息放进去
    212. scanf("%s", pc->data[pos].addr);
    213. printf("修改成功\n");
    214. }
    215. }

                         

    ————————————————————————————————————————

                        

    (3). test.c文件 -- 测试通讯录:

                  

    1 . 函数 void menu() -- 打印通讯录菜单:

                    

    告知使用者输入对应数字实现对应功能

                   

    图示:

                         

                  

    2 . 函数 void test() -- 完成通讯录测试:

                    

    (一). 

    使用 do while 循环

                      

    打印菜单

                  

    根据输入的选项判断是否需要再进行服务

    可以使用 switch 语句进行筛选判断

    图示:

                 

    (二).

    包含头文件

    通过结构体 struct contact (Contact),

    创建通讯录类型变量 -- con

    包含data数组,存放有效的通讯录数据

    sz,记录存放数据的个数

                        

    创建后还需要初始化

    调用 函数InitContact() 进行初始化

    参数接收通讯录类型变量的地址 -- &con

    图示:

                   

    (三).

    如果用户输入 1

    则调用 函数AddContact()

    增加联系人,

    参数接收 &con 对通讯录进行对应操作

                

    如果用户输入 2 ,

    则调用 函数DelContact()

    删除指定通讯录成员,

    参数接收 &con 对通讯录进行对应操作

                

    如果用户输入 3 ,

    则调用 函数SearchContact()

    查找指定联系人信息,

    参数接收 &con 对通讯录进行对应操作

                

    如果用户输入 4 ,

    则调用 函数ModifyContact()

    修改指定联系人信息,

    参数接收 &con 对通讯录进行对应操作

                

    如果用户输入 5 ,

    则调用 函数ShowContact()

    打印所有联系人信息,

    参数接收 &con 对通讯录进行对应操作

                

    如果用户输入 0

    打印对应信息退出程序

                   

    如果用户 输入非法 

    打印对应信息重新输入

                  

    图示:

                         

                  

    3 . 主函数

                    

    直接调用 test()测试函数即可

                    

    图示:

                         

    该文件对应代码:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. //test.c文件 -- 测试通讯录:
    3. //包含头文件:
    4. #include "contact.h"
    5. //1 . 函数 void menu() -- 打印通讯录菜单:
    6. void menu()
    7. {
    8. // 选1:增加联系人 选2:删除联系人
    9. // 选3:搜索联系人 选4:修改联系人信息
    10. // 选5:显示所有联系人 选6:对联系人进行排序
    11. // 选0:退出通讯录
    12. printf("*****************************************************\n");
    13. printf("***** 1. add 2. del *****\n");
    14. printf("***** 3. search 4. modify *****\n");
    15. printf("***** 5. show 6. sort *****\n");
    16. printf("***** 0. exit *****\n");
    17. printf("*****************************************************\n");
    18. }
    19. //函数 void test() -- 完成通讯录测试:
    20. void test()
    21. {
    22. //创建通讯录类型变量:
    23. Contact con;
    24. //调用函数初始化通讯录类型变量:
    25. InitContact(&con);
    26. int input = 0;//接收输入的数据
    27. do
    28. {
    29. //调用菜单函数打印菜单:
    30. menu();
    31. //接收输入数据:
    32. printf("请选择:>");
    33. scanf("%d", &input);
    34. //使用switch语句进行筛选判断:
    35. switch (input)
    36. {
    37. case ADD:
    38. //如果用户输入1,
    39. //则调用AddContact()函数
    40. //添加联系人:
    41. AddContact(&con);
    42. //参数接收 &con ,对通讯录进行对应操作
    43. break;
    44. case DEL:
    45. //如果用户输入2,
    46. //则调用DelContact()函数
    47. //删除指定联系人:
    48. DelContact(&con);
    49. //参数接收 &con ,对通讯录进行对应操作
    50. break;
    51. case SEARCH:
    52. //如果用户输入3,
    53. //则调用SearchContact()函数
    54. //查找指定联系人:
    55. SearchContact(&con);
    56. //参数接收 &con ,对通讯录进行对应操作
    57. break;
    58. case MODIFY:
    59. //如果用户输入 4 ,
    60. //则调用ModifyContact()函数
    61. //修改指定联系人信息
    62. ModifyContact(&con);
    63. //参数接收 &con ,对通讯录进行对应操作
    64. break;
    65. case SHOW:
    66. //如果用户输入5,
    67. //则调用ShowContact()函数
    68. //打印所有联系人信息:
    69. ShowContact(&con);
    70. //参数接收 &con ,对通讯录进行对应操作
    71. break;
    72. case SORT:
    73. //待定
    74. break;
    75. case EXIT:
    76. //如果用户输入0,
    77. //打印对应信息并退出程序:
    78. printf("退出通讯录\n");
    79. break;
    80. default:
    81. //如果用户 输入非法,
    82. //打印对应信息并程序输入:
    83. printf("选择错误,重新选择\n");
    84. break;
    85. }
    86. } while (input);
    87. //只要输入数据不为0就继续进行
    88. }
    89. //主函数:
    90. int main()
    91. {
    92. //调用测试函数进行测试:
    93. test();
    94. return;
    95. }

                 

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                 

    最终实现效果:

  • 相关阅读:
    nginx+lua实现文件上传和下载功能
    轻量封装WebGPU渲染系统示例<21>- 3D呈现元胞自动机之生命游戏(源码)
    Mysql知识复习二
    智慧家庭中的人体动作识别研究综述
    Docker快速入门
    url转二维码处理以及常见问题
    uni-app 使用 scss 实现推荐标签区域显示效果
    JUC相关面试题
    usb host 驱动 - UVC 掉包
    z-index生效与css层叠
  • 原文地址:https://blog.csdn.net/weixin_63176266/article/details/131969914