C实现通讯录管理系统(亮点:纯链表实现、子串匹配,文件读写)

题目:通讯录管理程序

问题描述

编写一个简单的通讯录管理程序。通讯录记录有姓名,地址(省、市(县)、街道),电话号码,邮政编码等四项。

基本要求

程序应提供的基本基本管理功能有:

1) 添加:即增加一个人的记录到通信录中

2) 显示:即在屏幕上显示所有通信录中的人员信息,应能分屏显示。

3) 存储:即将通讯录信息保存在一个文件中。

4) 装入:即将文件中的信息读入程序。

5) 查询:可根据姓名查找某人的相关信息,若找到显示其姓名、地址、电话号码和邮政编码。

6) 修改:可修改一个人的除姓名外其它信息。

测试数据

程序应输入不少于10个人员的通讯录信息,应考虑到人员可以同名的情况。

实现提示

程序可用一个结构体数组、单向链表或对象数组来管理人员信息,每个人员的姓名,地址,电话号码和邮政编码用一个结构体或类实现。

代码:

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#define CHARMAX 30 6 7typedef struct record { 8 char name[CHARMAX]; 9 char phonenumber[11]; 10 char address[3][CHARMAX]; //0-省 1-市 2-街道 11 char postcode[6]; 12 struct record *next; 13} RECORD; 14 15void PrintMenu(); 16 17void AlterString(RECORD *head); 18 19RECORD *InputRecord(RECORD *head, int *total); 20 21void PrintAllRecords(RECORD *head, const int *total); 22 23RECORD *DeleteRecord(RECORD *head,int *total); 24 25RECORD *ReviseRecord(RECORD *head); 26 27RECORD *SearchRecord(RECORD *head, int onlyOneRecord) ; 28 29RECORD *ImportRecords(RECORD *head, int *total); 30 31RECORD *ExportRecords(RECORD *head); 32 33int main() { 34 int total = 0, selection; 35 RECORD *head = NULL; 36 printf("Welcome to Directory Management System!\n"); 37 printf("By XZ&YYM\n"); 38 printf("---------------------------------------------\n"); 39 40 do { 41 PrintMenu(); 42 scanf("%d", &selection); 43 system("cls"); 44 switch (selection) { 45 case 0: 46 break; 47 case 1: 48 head = InputRecord(head, &total); 49 break; 50 case 2: 51 PrintAllRecords(head, &total); 52 break; 53 case 3: 54 head = DeleteRecord(head,&total); 55 break; 56 case 4: 57 head = ReviseRecord(head); 58 break; 59 case 5: 60 SearchRecord(head,0); 61 break; 62 case 6: 63 head = ImportRecords(head,&total); 64 break; 65 case 7: 66 ExportRecords(head); 67 break; 68 default: 69 printf("\n\n-- Sorry!Please input 0-10!\n"); 70 }; 71 } while (selection != 0); 72 return 0; 73} 74 75void PrintMenu() { 76 printf("\n"); 77 printf("|1.Input record\n"); 78 printf("|2.List all records\n"); 79 printf("|3.Delete record\n"); 80 printf("|4.Revise record\n"); 81 printf("|5.Search record\n"); 82 printf("|6.Import records from file\n"); 83 printf("|7.Export records to file\n"); 84 printf("|0.Exit\n"); 85 printf("|Please input 0-7 to select function :"); 86} 87 88//功能:将字符串后的回车删掉 89//入参:链表首地址 90//出参:无 91void AlterString(RECORD *head) { 92 int m; 93 RECORD *p1 = head; 94 95 while (p1 != NULL) { 96 for (m = 0; m < CHARMAX; m++) { 97 if (*((p1->name) + m) == '\n') { 98 *((p1->name) + m) = '\0'; 99 } 100 } 101 for (m = 0; m < 11; m++) { 102 if (*((p1->phonenumber) + m) == '\n') { 103 *((p1->phonenumber) + m) = '\0'; 104 } 105 } 106 for (m = 0; m < CHARMAX; m++) { 107 if (*((p1->address[0]) + m) == '\n') { 108 *((p1->address[0]) + m) = '\0'; 109 } 110 } 111 for (m = 0; m < CHARMAX; m++) { 112 if (*((p1->address[1]) + m) == '\n') { 113 *((p1->address[1]) + m) = '\0'; 114 } 115 } 116 for (m = 0; m < CHARMAX; m++) { 117 if (*((p1->address[2]) + m) == '\n') { 118 *((p1->address[2]) + m) = '\0'; 119 } 120 } 121 for (m = 0; m < 6; m++) { 122 if (*((p1->postcode) + m) == '\n') { 123 *((p1->postcode) + m) = '\0'; 124 } 125 } 126 p1 = p1->next; 127 } 128} 129 130//功能:连续输入数据 131//入参:链表首地址,数据总数地址 132//出参:链表首地址 133RECORD *InputRecord(RECORD *head, int *total) { 134 int i = *total; 135 char inputChar; 136 RECORD *p = head, *input = (RECORD *) malloc(sizeof(RECORD)); 137 138 printf("\n-- Start to Input Record\n"); 139 140 //如果拥有数据,则输出现有数据总数 141 if (*total) { 142 printf("-- You have had %d records\n\n", *total); 143 } 144 145 do { 146 //输入数据 147 printf("Input NO.%d Record`s Name:", i + 1); 148 fflush(stdin); 149 fgets(input->name, CHARMAX + 1, stdin); 150 printf("Input NO.%d Record`s Phone Number:", i + 1); 151 fflush(stdin); 152 fgets(input->phonenumber,CHARMAX + 1, stdin); 153 printf("Input NO.%d Record`s Address:\n", i + 1); 154 printf("- Input NO.%d Record`s Province:", i + 1); 155 fflush(stdin); 156 fgets(input->address[0], CHARMAX + 1, stdin); 157 printf("- Input NO.%d Record`s City:", i + 1); 158 fflush(stdin); 159 fgets(input->address[1], CHARMAX + 1, stdin); 160 printf("- Input NO.%d Record`s Street:", i + 1); 161 fflush(stdin); 162 fgets(input->address[2], CHARMAX + 1, stdin); 163 printf("- Input NO.%d Record`s Postcode:", i + 1); 164 fflush(stdin); 165 fgets(input->postcode, 7, stdin); 166 input->next = NULL; //插入时放于链表的最后 167 168 //插入数据,分为首数据和非首数据 169 if (head == NULL) { 170 head = input; 171 p = input; 172 } else { 173 while (p->next != NULL) { 174 p = p->next; 175 } 176 p->next = input; 177 } 178 179 //增加数据计数 180 (*total)++; 181 182 //询问是否继续 183 printf("\nDo you want to continue?(Y/N):"); 184 scanf(" %c", &inputChar); 185 if (inputChar == 'Y' || inputChar == 'y') { //直接用getchar必须输入大写Y才能继续 186 //创建新的空间 187 input = (RECORD *) malloc(sizeof(RECORD)); 188 i++; 189 } else { 190 break; 191 } 192 } while (1); 193 194 //将字符串后面的回车删除 195 AlterString(head); 196 return head; 197 198} 199 200//功能:打印全部数据 201//入参:链表首地址,数据总数地址 202//出参:无 203void PrintAllRecords(RECORD *head, const int *total) { 204 int page = 1, firstIndex = 0, i, pageAmount = *total / 10 + 1; 205 RECORD *p = head; 206 do { 207 system("cls"); 208 209 //处理输入的数字过大或过小 210 if (page > pageAmount) { 211 printf("-- Sorry! The MAX of pages is %d\n", pageAmount); 212 } else if (page < 0) { 213 printf("-- Sorry! The number have to be positive\n"); 214 } else { 215 //处理分页 216 firstIndex = 10 * (page - 1); 217 218 printf("NO.\tName\tPhonenumber\tProvince\tCity\tStreet\tPostcode\t\n"); 219 220 //处理前置数据 221 p = head; 222 for (i = 0; i < firstIndex; ++i) { 223 p = p->next; 224 } 225 226 i = 0; 227 228 //输出数据 229 while (p != NULL && i < 10) { //todo 大量数据可能出现问题 230 i++; 231 printf("NO.%d\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t\n", i+firstIndex,p->name, p->phonenumber, p->address[0], p->address[1], 232 p->address[2], 233 p->postcode); 234 p = p->next; 235 } 236 printf("-- Page %d (Total %d pages)\n ", page, pageAmount); 237 } 238 239 printf("-- Jump to page number (Input 0 to finish):"); 240 scanf("%d", &page); 241 } while (page); 242} 243 244//功能:删除某条数据 245//入参:链表首地址 246//出参:链表首地址 247RECORD *DeleteRecord(RECORD *head,int *total) { 248 RECORD *p1 = head, *p2,*searchResult; 249 searchResult = SearchRecord(head, 1); 250 251 while (p1 != NULL && p1 != searchResult) { 252 p2 = p1; //p2上一个节点 253 p1 = p1->next; //p1下一个节点 254 } 255 256 if (p1 == head) { 257 head = p1->next; 258 free(p1); 259 (*total)--; //todo 260 printf("\n-- Success!\n"); 261 } else if (p1 != NULL) { 262 p2->next = p1->next; 263 free(p1); 264 (*total)--; 265 printf("\n-- Success!\n"); 266 } else { 267 printf("\n-- Do not find this id!\n"); 268 } 269 return head; 270 271 272} 273 274//功能:输出某条数据 275//入参:数据地址 276//出参:无 277void PrintOneRecord(RECORD *p) { 278 printf("Name:%s\tPhonenumber:%s\tProvince:%s\tCity:%s\tStreet::%s\tPostcode:%s\t\n", p->name, p->phonenumber, 279 p->address[0], p->address[1], p->address[2], p->postcode); 280} 281 282//功能:更改数据 283//入参:数据地址 284//出参:无 285RECORD *ReviseRecord(RECORD *head){ 286 RECORD *p1 = head, *p2,*searchResult,*input = (RECORD *) malloc(sizeof(RECORD)); 287 //返回需要更改的数组地址 288 searchResult = SearchRecord(head, 1); 289 if (!searchResult){ 290 return head; 291 } 292 //输入数据 293 printf("\nInput the newRecord`s Name:"); 294 fflush(stdin); 295 fgets(input->name, CHARMAX + 1, stdin); 296 printf("Input the newRecord`s Phone Number:"); 297 fflush(stdin); 298 fgets(input->phonenumber,CHARMAX + 1, stdin); 299 printf("Input the Record`s Address:\n"); 300 printf("- Input the newRecord`s Province:"); 301 fflush(stdin); 302 fgets(input->address[0], CHARMAX + 1, stdin); 303 printf("- Input the newRecord`s City:"); 304 fflush(stdin); 305 fgets(input->address[1], CHARMAX + 1, stdin); 306 printf("- Input the newRecord`s Street:"); 307 fflush(stdin); 308 fgets(input->address[2], CHARMAX + 1, stdin); 309 printf("- Input the newRecord`s Postcode:"); 310 fflush(stdin); 311 fgets(input->postcode, 7, stdin); 312 //插入时放于链表的最后 313 input->next = NULL; 314 315 while (p1 != NULL && p1 != searchResult) { 316 p2 = p1; //p2上一个节点 317 p1 = p1->next; //p1下一个节点 318 } 319 if (p1 == head) { 320 head = input; 321 input->next = p1->next; 322 free(p1); //是否要释放? 323 printf("\n-- Success the Revise!\n"); 324 } else if (p1 != NULL) { 325 p2->next = input; 326 input->next = p1->next; 327 free(p1); 328 printf("\n-- Success Revise!\n"); 329 } else { 330 printf("\n-- Do not find this id!\n"); 331 } 332 AlterString(head); 333 return head; 334} 335 336//功能:搜索数据,并返回唯一搜索结果 337//入参:链表首地址,是否要求返回唯一结果 338//出参:数据地址 339RECORD *SearchRecord(RECORD *head, int onlyOneRecord) { 340 int amount = 0, i = 0, selection = 0; //i,p1循环变量 341 char input[CHARMAX]; 342 RECORD *p1 = head, *results[100] = {NULL}; //result是RECORD类型的指针数组 343 344 printf("\n-- Search the record:"); 345 setbuf(stdin, NULL); 346 fgets(input, CHARMAX + 1, stdin); 347 348 //去除字符串回车 349 for (i = 0; i < CHARMAX; ++i) { 350 if (*((input) + i) == '\n') { 351 *((input) + i) = '\0'; 352 } 353 } 354 355 //遍历搜索 356 while (p1 != NULL) { 357 if (strstr(p1->name, input) || //strstr()判断是否为子串 358 strstr(p1->phonenumber, input) || 359 strstr(p1->address[0], input) || 360 strstr(p1->address[1], input) || 361 strstr(p1->address[2], input) || 362 strstr(p1->postcode, input)) { 363 results[amount] = p1; 364 amount++; 365 } 366 p1 = p1->next; 367 } 368 369 //若有多个结果,提示用户选择 370 if (amount > 1) { 371 printf("\n-- Search Result:\n"); 372 for (i = 0; i < amount; i++) { 373 printf("NO.%d\t", i + 1); 374 PrintOneRecord(results[i]); 375 } 376 if (!onlyOneRecord) { 377 return NULL; //如果不需要去重,则返回NULL 378 } 379 printf("\n-- Input the number you want to change: "); 380 scanf("%d", &selection); 381 //处理输入数据不正确,默认返回第一个 382 if (selection - 1 > amount || selection < 0) { 383 printf("\n-- Wrong input (Choose the first record automatically)"); 384 return results[0]; 385 } 386 return results[selection - 1]; 387 } else if (!amount) { 388 printf("\n-- Sorry! No result!"); 389 return NULL; 390 } else { 391 printf("\n-- Search Result:\n"); 392 PrintOneRecord(results[0]); 393 return results[0]; 394 } 395 396 397} 398 399//功能:导入文件中的数据 400//入参:链表首地址,总条数 401//出参:数据地址 402RECORD *ImportRecords(RECORD *head, int *total) { 403 int i = *total,m=3; 404 FILE *fpRead; 405 RECORD *p = head, *input; 406 407 fpRead = fopen("stu.txt","r"); 408 if(fpRead==NULL){ 409 printf("can't open file\n"); 410 return 0; 411 } 412 do { 413 //输入数据 414 input = (RECORD *) malloc(sizeof(RECORD)); 415 fread(input, sizeof(struct record),1,fpRead); 416 input->next = NULL; //插入时放于链表的最后 417 418 //插入数据,分为首数据和非首数据 419 if (head == NULL) { 420 head = input; 421 p = input; 422 } else { 423 while (p->next != NULL) { 424 p = p->next; 425 } 426 p->next = input; 427 } 428 429 //增加数据计数 430 (*total)++; 431 m--; 432 433 } while (m); 434 435 return head; 436 437} 438 439//功能:搜索数据,并返回唯一搜索结果 440//入参:链表首地址,是否要求返回唯一结果 441//出参:数据地址 442RECORD *ExportRecords(RECORD *head){ 443 FILE *fp; 444 struct record *p=head; 445 if((fp=fopen("stu.txt","wb"))==NULL) 446 { 447 printf("Fail to open the stu.txt!\n"); 448 exit(0); 449 } 450 while(p != NULL) 451 { 452 fwrite(p, sizeof(struct record),1,fp); 453 p=p->next; 454 } 455 fclose(fp); 456 printf("you have save correctly!\n"); 457 return 0; 458}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid