剩下的步骤很简单了,话不多说直接上源码;
七.源码
contact.h
1. #pragma once 2. 3. //所需头文件的包含 4. #include <stdio.h> 5. #include <string.h> 6. #include <stdlib.h> 7. 8. //一些定义的表示大小的宏 9. #define MAX_NAME 20 10. #define MAX_SEX 10 11. #define MAX_TEL 20 12. #define MAX_ADDR 30 13. 14. #define DEFAULT_SZ 3 //默认通讯录容量 15. #define INC_SZ 2 //每次增容的大小 16. 17. 18. //定义每个联系人的信息 19. typedef struct peoinfo 20. { 21. char name[MAX_NAME]; //姓名 22. int age; //年龄 23. char sex[MAX_SEX]; //性别 24. char tel[MAX_TEL]; //电话 25. char addr[MAX_ADDR]; //地址 26. }peoinfo; 27. 28. 29. //存储每个联系人 30. typedef struct contact 31. { 32. peoinfo* data; //定义指针变量,方便后续动态内存开辟,进行通讯录扩容操作 33. int sz; //通过下标访问数组 34. int capacity; // 记录通讯录容量 35. }contact; 36. 37. typedef struct sort 38. { 39. peoinfo* sort; 40. }sort; 41. 42. //动态初始化通讯录 43. void Innitcontact(contact* pc); 44. 45. //打印通讯录 46. void printcontact(contact* pc); 47. 48. //是否增容 49. void inccapacity(contact* pc); 50. 51. 52. //读入文件中的联系人信息 53. void download(contact* pc); 54. 55. //保存文件中的联系人信息 56. void savecontact(contact* pc); 57. 58. //销毁通讯录 59. void destroycontact(contact* pc); 60. 61. //添加联系人 62. void addcontact(contact* pc); 63. 64. //删除联系人 65. void delcontact(contact* pc); 66. 67. //查找联系人 68. void searchcontact(contact* pc); 69. 70. //修改联系人 71. void modifycontact(contact* pc); 72. 73. //排序通讯录 74. void sortcontact(contact* pc); 75.
contact.c
1. #define _CRT_SECURE_NO_WARNINGS 2. 3. #include "contact.h" 4. 5. //将文件中的联系人信息读入 6. void download(contact* pc) 7. { 8. FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "r"); //以只读的方式打开文件 9. if (pf == NULL) //判断文件是否打开成功 10. { 11. perror("fopen"); 12. return; 13. } 14. 15. peoinfo tmp = { 0 }; 16. while (fread(&tmp, sizeof(peoinfo), 1, pf)) 17. { 18. inccapacity(pc); //增容函数 19. pc->data[pc->sz] = tmp; //将联系人信息写入 data 中 20. pc->sz++; //记录写入联系人的数量 21. } 22. fclose(pf); //关闭文件 23. pf = NULL; 24. } 25. 26. //保存文件中的联系人信息 27. void savecontact(contact* pc) 28. { 29. FILE* pf = fopen("D:\\C\\c-code\\CONTACT\\CONTACT\\contact.txt", "w"); //以只写的方式打开文件 30. if (pf == NULL) //判断文件是否打开成功 31. { 32. perror("savecontact"); 33. return; 34. } 35. int i = 0; 36. for (i = 0; i < pc->sz; i++) 37. { 38. fwrite(pc->data + i, sizeof(peoinfo), 1, pf); //向文件中写入通讯录的数据 39. } 40. fclose(pf); //数据写完后,关闭文件 41. pf = NULL; 42. } 43. 44. //销毁通讯录 45. void destroycontact(contact* pc) 46. { 47. pc->sz = 0; 48. pc->capacity = DEFAULT_SZ; //容量回复默认值 49. free(pc->data); //释放之前开辟的内存 50. pc->data = NULL; //指针置空,防止野指针的出现 51. } 52. 53. //动态初始化联系人 54. void Innitcontact(contact* pc) 55. { 56. pc->data = (peoinfo*)calloc(DEFAULT_SZ, sizeof(peoinfo)); //动态内存开辟,实现通讯录的动态 57. if (pc->data == NULL) //判断内存开辟是否成功 58. { 59. perror("Innitcontact"); 60. return; 61. } 62. pc->sz = 0; //初始化通讯录实时容量,也可用作下标 63. pc->capacity = DEFAULT_SZ; //初始化容量 64. download(pc); //加载文件中联系人的信息 65. } 66. 67. 68. //打印通讯录 69. void printcontact(contact* pc) 70. { 71. int i = 0; 72. printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址"); //打印的格式可以根据个人喜好来 73. for (i = 0; i < pc->sz; i++) 74. { 75. printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[i].name, 76. pc->data[i].age, 77. pc->data[i].sex, 78. pc->data[i].tel, 79. pc->data[i].addr); 80. } 81. } 82. 83. //是否增容 84. void inccapacity(contact* pc) 85. { 86. if (pc->sz == pc->capacity) 87. { 88. printf("通讯录已满,开始增容\n"); 89. peoinfo* ptr = (peoinfo*)realloc(pc->data,(DEFAULT_SZ+INC_SZ)*sizeof(peoinfo)); //利用 realloc 进行内存的再次动态开辟,实现通讯录的增容 90. 91. if(ptr == NULL) //判断内存是否开辟成功 92. { 93. printf("增容失败\n"); 94. perror("inccapacity"); 95. return; 96. } 97. else 98. { 99. pc->data = ptr; //将扩容后的通讯录首地址赋给原来的通讯录 100. pc->capacity += INC_SZ; //容量增加 101. printf("增容成功\n"); 102. } 103. } 104. } 105. 106. //查找联系人 107. int find(char tmp[], contact* pc) 108. { 109. int i = 0; 110. for (i = 0; i < pc->sz; i++) 111. { 112. if (strcmp(tmp, pc->data[i].name) == 0) //因为姓名是字符串,所以利用字符串比较函数 113. { 114. return i; //查找成功返回其下标 115. } 116. } 117. return -1; //失败则返回-1 118. } 119. 120. //添加联系人 121. void addcontact(contact* pc) 122. { 123. int input = 0; 124. do 125. { 126. 127. printf("按1继续,按0返回:>"); //利用 do ... while 结构实现联系人的多次添加 128. scanf("%d", &input); 129. 130. switch (input) 131. { 132. case 1: 133. inccapacity(pc); //判断容量是否已满,若已满,则进行增容 134. printf("开始添加\n"); //联系人各种信息的录入 135. printf("请输入姓名:>"); 136. scanf("%s", pc->data[pc->sz].name); 137. printf("请输入年龄:>"); 138. scanf("%d", &(pc->data[pc->sz].age)); 139. printf("请输入性别:>"); 140. scanf("%s", pc->data[pc->sz].sex); 141. printf("请输入电话:>"); 142. scanf("%s", pc->data[pc->sz].tel); 143. printf("请输入地址:>"); 144. scanf("%s", pc->data[pc->sz].addr); 145. pc->sz++; //添加成功后,通讯录实时容量增加1 146. printf("添加成功\n"); 147. break; 148. case 0: 149. printf("返回\n"); 150. return; 151. break; 152. default: 153. printf("选择错误,重新选择\n"); 154. break; 155. } 156. } while (input); 157. } 158. 159. //删除联系人 160. void delcontact(contact* pc) 161. { 162. char tmp[MAX_NAME]; 163. int pos = 0, i = 0; 164. if (pc->sz == 0) //判断通讯录有无数据 165. { 166. printf("通讯录为空,无法删除\n"); 167. return; 168. } 169. while (1) 170. { 171. again: 172. printf("请输入要删除的人的姓名:>"); 173. scanf("%s", tmp); 174. pos = find(tmp, pc); //查找要删除人的下标 175. if (pos == -1) 176. { 177. printf("要删除的人不存在,重新输入\n"); 178. goto again; 179. } 180. else 181. break; 182. } 183. printf("开始删除\n"); 184. for (i = pos; i < pc->sz - 1; i++) //从返回的下标 pos 开始 ,之后的每个元素向前移动一位 185. { 186. pc->data[i] = pc->data[i + 1]; 187. } 188. pc->sz--; //删除成功即通讯录的实时容量减去1 189. printf("删除成功\n"); 190. } 191. 192. //查找联系人 193. void searchcontact(contact* pc) 194. { 195. char name[MAX_NAME]; 196. int pos = 0; 197. if (pc->sz == 0) //判断通讯录中是否有数据 198. { 199. printf("通讯录为空,无法查询\n"); 200. return; 201. } 202. while (1) 203. { 204. again: 205. printf("请输入要查找人的姓名:>"); 206. scanf("%s", name); 207. pos = find(name, pc); //调用 fing 函数,并返回其下标 208. if (pos == -1) 209. { 210. printf("查无此人,重新查询\n"); //查询失败则继续 211. goto again; 212. } 213. else 214. break; 215. } 216. printf("查询成功\n"); 217. printf("%-20s\t%-5s\t%-10s\t%-20s\t%-30s\n", "姓名", "年龄", "性别", "电话", "地址"); //打印该联系人的信息 218. printf("%-20s\t%-5d\t%-10s\t%-20s\t%-30s\n", pc->data[pos].name, 219. pc->data[pos].age, 220. pc->data[pos].sex, 221. pc->data[pos].tel, 222. pc->data[pos].addr); 223. 224. } 225. 226. //修改联系人 227. void modifycontact(contact* pc) 228. { 229. if (pc->sz == 0) //判断通讯录是否有数据 230. { 231. printf("通讯录为空,无法修改\n"); 232. return; 233. } 234. char name[MAX_NAME]; 235. int pos = 0; 236. while (1) 237. { 238. again: 239. printf("请输入要修改的联系人的姓名:>"); 240. scanf("%s", name); 241. pos = find(name, pc); //返回要修改的联系人的下标 242. if (pos == -1) 243. { 244. printf("要修改的联系人不存在,重新输入\n"); 245. goto again; 246. } 247. else 248. break; 249. } 250. printf("开始修改\n"); //修改联系人信息 251. printf("请输入姓名:>"); 252. scanf("%s", pc->data[pos].name); 253. printf("请输入年龄:>"); 254. scanf("%d", &(pc->data[pos].age)); 255. printf("请输入性别:>"); 256. scanf("%s", pc->data[pos].sex); 257. printf("请输入电话:>"); 258. scanf("%s", pc->data[pos].tel); 259. printf("请输入地址:>"); 260. scanf("%s", pc->data[pos].addr); 261. printf("修改成功\n"); 262. } 263. 264. 265. //排序通讯录 266. void sortcontact(contact* pc) 267. { 268. if (pc->sz < 2) 269. { 270. printf("通讯录数据不足,无法排序\n"); //判断是否支持排序 271. return; 272. } 273. int i = 0, j = 0; 274. sort S; //变量的创建 275. S.sort= (peoinfo*)calloc(pc->capacity, sizeof(peoinfo)); //sort 的初始化 276. if (S.sort == NULL) //判断动态内存是否开辟成功 277. { 278. perror("sortcontact"); 279. return; 280. } 281. printf("开始排序\n"); 282. //qsort(pc, pc->sz, sizeof(peoinfo), cmp); 283. for (i = 0; i < pc->sz - 1; i++) //排序算法 284. { 285. for (j = i + 1; j < pc->sz; j++) 286. { 287. if (strcmp(pc->data[i].name, pc->data[j].name) > 0) 288. { 289. S.sort[i] = pc->data[i]; //交换元素 290. pc->data[i] = pc->data[j]; 291. pc->data[j] = S.sort[i]; 292. } 293. } 294. } 295. printf("排序成功\n"); 296. free(S.sort); //排序成功后释放所开辟的内存 297. S.sort = NULL; //将指针置空,防止使用野指针 298. }
test.c
1. #define _CRT_SECURE_NO_WARNINGS 2. 3. //头文件的包含 4. #include "contact.h" 5. 6. 7. //菜单 8. void menu() 9. { 10. printf("*****************************************************************\n"); 11. printf("********** 1.add 2.del **********\n"); 12. printf("********** 3.search 4.modify **********\n"); 13. printf("********** 5.see 6.sort **********\n"); 14. printf("********** 0.exit **********\n"); 15. printf("*****************************************************************\n"); 16. 17. 18. } 19. //利用枚举变量使代码表达的意思更清晰 20. enum option 21. { 22. EXIT, //默认从0开始 23. ADD, //1 24. DEL, //2 25. SEARCH, //3 26. MODIFY, //4 27. SEE, //5 28. SORT //6 29. }; 30. 31. int main() 32. { 33. int input = 0; 34. contact con; //通讯录变量创建 35. //初始化联系人数组,包含从文件中读取联系人信息 36. Innitcontact(&con); 37. do 38. { 39. menu(); 40. printf("请选择:>"); 41. scanf("%d", &input); 42. switch (input) 43. { 44. case ADD: 45. addcontact(&con); //添加 46. break; 47. case DEL: 48. delcontact(&con); //删除 49. break; 50. case SEARCH: 51. searchcontact(&con); //查找 52. break; 53. case MODIFY: 54. modifycontact(&con); //修改 55. break; 56. case SEE: 57. printcontact(&con); //打印通讯录 58. break; 59. case SORT: 60. sortcontact(&con); //排序 61. break; 62. case EXIT: 63. savecontact(&con); //保存通讯录,将联系人信息写入文件中 64. destroycontact(&con); //销毁通讯录 65. printf("退出通讯录\n"); 66. break; 67. default: 68. printf("选择错误,重新选择\n"); 69. break; 70. } 71. } while (input); 72. return 0; 73. }