自从上次通讯录项目被字符串项目整的自闭了之后,用了5天时间重新整理了一下通讯录的思路,并且能够正常的使用,今天按模块把基于链表的通讯录2.0版本记录一下,供后续积累经验。
首先总结一下 通讯录2.0版的不足之处:
- 由于程序基本都写在堆区和栈区,所以当程序结束后,内存里的东西也就没了,如果继续优化的话,考虑连接数据库,或者低级一点,结束前写入.txt文本,开启程序前再从.txt文件写入
- 界面粗糙,也算是c语言程序的特性吧,不像java甚至于c++能写的界面友好一点,但是作为我在这个学习阶段的逻辑训练和代码量的积累,还是比较成功的
那么接下来就分模块讲述一下整个通讯录的思路吧,先列一下思路图
第一个,就说一下上次初次尝试写通讯录时让我很纠结的 字符串输入问题,上一次利用指针和字符数组写入,要么是报错,要么就是最后一次输入内容会把前面所有字符串内容都给覆盖掉,其实上一次也有想到过利用 getchar() 函数去自己写一个getstring()的函数,但由于当时重点放在指针上(最后是因为scanf无法给指向堆区的指针写入内容),就没有太多尝试
1.getstring()函数
1 char *GetString() 2 { 3 int size = 5; 4 int count = 0; 5 char *str = (char *)malloc(size); 6 char *pMark = str; 7 char *newstr = NULL; 8 char c; 9 while((c = getchar()) != '\n') 10 { 11 *str = c; 12 str++; 13 count++; 14 if(count + 1 == size) 15 { 16 *str = '\0'; 17 size += 5; 18 newstr = (char *)malloc(size); 19 strcpy_s(newstr,size,pMark); 20 free(pMark); 21 pMark = newstr; 22 str = newstr + count; 23 } 24 } 25 *str = '\0'; 26 27 return pMark;
思路:由于字符数组在程序运行后,长度是定下来的,对用户的输入长度就有很大限制,所以首先在堆区开辟第一个空间,利用Getchar()获取输入缓冲区内内容,向第一个空间内依次输入字符,并计数。利用计数给第一个空间留一个‘\0’的位置,再开辟一个同样大小的空间,将第一个空间内的字符串复制给这个空间内,然后用pMark始终指向后一个开辟的空间,str从‘\0’位置继续赋值,直到识别到‘\n’为止
第二个,在编程过程中发现利用scanf()输入时,在字符缓冲区内总是会有残留的'\n',每一次都得用getchar()去清理缓存区,一是太麻烦,二是经常会忘,干脆就封装一个函数,专门用来获取字符,而且不会受到换行符的麻烦
2.GetKey()
1 char GetKey() 2 { 3 char c; 4 char z = '!'; 5 int flag = 1; 6 while((c=getchar()) != '\n' || 1 == flag) //考虑了\n在之前的情况 7 { 8 z = c; 9 flag = 0; 10 } 11 return z; 12 }
思路:没有什么复杂的思路,就是把'\n'排除在外,我另外又设置了一个标记,就是因为在后面的模块写的过程当中忘记了自己封装好的函数,直接使用scanf然后后面的函数也成功的把‘\n’获取进去了(好无奈啊,这个找了很长时间的bug),所以干脆就加个标记。
第三个,也是因为自己太懒了,不想每次都添加很多信息,就写了三个随机生成序号,姓名和电话号码的函数,在前期测试的时候使用
3.GetTestMessage()
1 int GetId() 2 { 3 static int id = 0; //使用静态变量 4 id++; 5 return id; 6 } 7 char *GetName() //随机分配姓名 8 { 9 char *pname = (char *)malloc(6); 10 int i; 11 for(i = 0;i < 5;i++) 12 { 13 pname[i] = rand()%26 + 'a'; 14 } 15 pname[i] = '\0'; 16 17 return pname; 18 } 19 char *GetTel() //随机分配电话号码 20 { 21 char *ptel = (char *)malloc(12); 22 int i; 23 int num = rand()%4+1; 24 switch(num) 25 { 26 case 1: 27 strcpy_s(ptel,12,"132"); 28 break; 29 case 2: 30 strcpy_s(ptel,12,"157"); 31 break; 32 case 3: 33 strcpy_s(ptel,12,"188"); 34 break; 35 default: 36 strcpy_s(ptel,12,"150"); 37 break; 38 } 39 for(i = 3;i < 11;i++) 40 { 41 ptel[i] = rand()%10 + '0'; 42 } 43 ptel[i] = '\0'; 44 45 return ptel; 46 }
思路:看了很多面经经常会问到 static的作用,我这里也是最浅显的一个作用声明静态变量,全局范围内可以使用,其他的我也在深入的了解,另外为了号码伪造的更像一点,用了三个号码段吧
第四个:到这才正式进入通讯录主题功能的编写,首先是获取通讯录单个结点,我分为两个部分来写,一方面是测试数据,一方面在后面可以添加
4.GetNode()
List *GetNode() //获取测试数据 { List *pTemp = (List *)malloc(sizeof(List)); pTemp->id = GetId(); pTemp->name = GetName(); pTemp->tel = GetTel(); pTemp->next = NULL; return pTemp; } List *GetMyNode() //获取自我添加数据 { List *pTemp = (List *)malloc(sizeof(List)); pTemp->id = GetId(); printf("请输入姓名: "); pTemp->name = GetString(); printf("请输入电话: "); pTemp->tel = GetString(); pTemp->next = NULL; return pTemp; }
思路:典型的链表添加
第五个:想一想能不能做一个分页功能呢,当数据量大的时候利用ws来翻页,所以我分为三个模块来实现这个分页功能,第一个是获取分页信息(当前页码,总共页码数,总共信息数,一页多少信息数),第二个是遍历链表按每页多少信息数,来截分,第三个是实现利用w s键来翻页,以及能返回主界面等等功能按键
5.Page()
1 Page *GetPage(List *pHead,int OnePageInfo) //获取页码信息 2 { 3 4 Page *pPage = (Page *)malloc(sizeof(Page)); 5 pPage->CurrentPage = 0; 6 pPage->TotalInfo = 0; 7 pPage->OnePageInfo = OnePageInfo; 8 while(pHead) 9 { 10 pPage->TotalInfo++; 11 pHead = pHead->next; 12 } 13 pPage->TotalPage = pPage->TotalInfo%pPage->OnePageInfo == 0 ? pPage->TotalInfo / pPage->OnePageInfo : pPage->TotalInfo / pPage->OnePageInfo + 1; //三目运算符 相当于if-else的简写 14 15 return pPage; 16 } 17 void ShowInfo(List *pHead,Page *pPage) //对结点进行截分 18 { 19 int PageBegin = (pPage->CurrentPage - 1) * pPage->OnePageInfo + 1; 20 int PageEnd = (pPage->CurrentPage) * (pPage->OnePageInfo); 21 int InfoNum = 0; 22 while(pHead) 23 { 24 InfoNum++; 25 if(InfoNum >= PageBegin && InfoNum <= PageEnd) 26 printf("%d\t%s\t%s\n",pHead->id,pHead->name,pHead->tel); 27 pHead = pHead->next; 28 } 29 return; 30 31 } 32 void TurnPage(List *pHead,Page *pPage) //利用按键进行翻页以及其他功能 33 { 34 char c = 's'; 35 while(1) 36 { 37 switch(c) 38 { 39 case 's': 40 if(pPage->CurrentPage < pPage->TotalPage) 41 { 42 pPage->CurrentPage++; 43 ShowInfo(pHead,pPage); 44 ShowMenu(pPage); 45 } 46 else 47 { 48 printf("已经是最后一页了!\n"); 49 ShowMenu(pPage); 50 } 51 break; 52 case 'w': 53 if(pPage->CurrentPage > 1) 54 { 55 pPage->CurrentPage--; 56 ShowInfo(pHead,pPage); 57 ShowMenu(pPage); 58 } 59 else 60 { 61 printf("已经是第一页了!\n"); 62 ShowMenu(pPage); 63 } 64 break; 65 case 'e': 66 return; 67 break; 68 case 'c': 69 return; 70 break; 71 case 'd': 72 return; 73 break; 74 case 'y': 75 return; 76 break; 77 case 'u': 78 return; 79 break; 80 default: 81 printf("请输入规定的按键!\n"); 82 break; 83 } 84 c = GetKey(); 85 g_Key = c; 86 // getchar(); //清空缓冲区内的\n 87 } 88 }
思路:难点在于第一个模块中确定哪些信息是能直接获取的,哪些是间接获得的。也是心血来潮用了一个三目运算符,感觉和if-else没啥区别,可能是我太菜了,哈哈哈,第二个模块中结点截获的开始位置和终止位置的确定也是一个难点,利用已知信息来确定。第三个难点其实就是我找了很长时间bug的那个‘\n’,有兴趣的话可以把 c = GetKey(); 直接写成c = getchar()体验一下。
第六个:添加功能过于简单就不直接把模块列出来了,直接在源码中展示,画个重点,我觉得最难的部分 查询功能就要来了
6.Query()
1 void Query(List *pHead) 2 { 3 List *pDel; 4 List *newpHead = NULL; 5 List *newpEnd = NULL; 6 char Choose; 7 char *KeyWord = NULL; 8 List *pNode = NULL; 9 List *pMark = pHead; 10 while(1) 11 { 12 while(1) 13 { 14 printf("请输入查询关键字: "); 15 KeyWord = GetString(); 16 printf("a.确认 其他键.重新输入\n"); 17 Choose = GetKey(); 18 //switch(Choose) 19 //{ 20 //case 'a': 21 // printf("%s\n",KeyWord); 22 // return; 23 // break; 24 //case 'c': 25 // printf("请重新输入!\n"); 26 // free(KeyWord); //堆区内存不需要的话就要及时释放 27 // break; 28 //} 29 if(Choose == 'a') //第二种方法 30 { 31 break; 32 } 33 else 34 { 35 free(KeyWord); //堆区内存不需要的话就要及时释放 36 KeyWord = NULL; 37 } 38 } 39 pHead = pMark; 40 while(pHead) 41 { 42 if(!strncmp(pHead->name,KeyWord,strlen(KeyWord)) || !strncmp(pHead->tel,KeyWord,strlen(KeyWord))) //输入的长度可以用字符串长度 43 { 44 pNode = (List *)malloc(sizeof(List)); //创建一个新的链表 用现成的接口和函数进行调用 45 pNode->id = pHead->id; 46 pNode->name = pHead->name; 47 pNode->tel = pHead->tel; 48 pNode->next = NULL; 49 AddNode(&newpHead,&newpEnd,pNode); 50 } 51 pHead = pHead->next; 52 } 53 Browse(newpHead); 54 while(newpHead) //清除之前所有的结点 55 { 56 pDel = newpHead; 57 newpHead = newpHead->next; 58 free(pDel); 59 pDel = NULL; 60 } 61 if('e' == g_Key || 'd' == g_Key || 'u' == g_Key) 62 { 63 return; 64 } 65 } 66 }
思路:我想做一个前缀模糊查询,难点在于1.多个功能按键的嵌套 2.如何加入按键 3.查询后的信息如何在遍历呢,解决如下1.我也做了尝试发现switch的话一个case里需要加很多东西,就用if-else代替了,意外发现效果还不错,2.利用已有的获取菜单里的模块 加入按键,并且设一个全局变量,能在不同模块下都有不一样的菜单 3.这个我也是思考了很久,决定重新创建一个链表,专门存查找的信息,并且为了养成好滴习惯,堆区不用的空间,立马及时的清理干净。
接下来的修改和删除功能就很简单了,总结起来就是 不要造成内存浪费,记得一级和二级指针的区别,其他的和查询就很像啦
接下来直接上源码了
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<time.h> 4 #include<string.h> 5 typedef struct NODE 6 { 7 int id; 8 char *name; 9 char *tel; 10 struct NODE *next; 11 }List; 12 typedef struct PAGE 13 { 14 int CurrentPage; //当前页数 15 int TotalPage; //总页数 16 int TotalInfo; //总条数 17 int OnePageInfo; //每页多少条 18 }Page; 19 int GetId(); 20 char *GetName(); 21 char *GetTel(); 22 List *GetNode(); 23 List *GetMyNode(); 24 void AddNode(List **ppHead,List **ppEnd,List *pNode); //添加通讯录信息 25 void InitInfo(List **ppHead,List **ppEnd,int n); //初始化数据 26 Page *GetPage(List *pHead,int OnePageInfo); //获得页码信息 27 void ShowInfo(List *pHead,Page *pPage); //展示当前页信息 28 void TurnPage(List *pHead,Page *pPage); //翻页功能 29 char GetKey(); //获得按键,将缓冲区内的\n给排除掉 30 void Browse(List *pHead); //浏览通讯录信息 31 void ShowMenu(Page *pPage); //页码信息显示 32 char *GetString(); //获取字符串(scanf()函数无法给指针赋值) 33 void AddMessage(List **ppHead,List **ppEnd); //添加通讯录信息功能 34 void Query(List *pHead); //查询功能 35 void DeleteInfo(List **ppHead,List **ppEnd); //删除通讯录信息功能 36 void DeleteNode(List **ppHead,List **ppEnd,int id); //删除结点模块 37 void UpDataInfo(List *pHead); //修改通讯录信息功能 38 int g_MenuType; //全局变量以g_开头 39 char g_Key; //判断是否为b 40 int main() 41 { 42 char c; 43 List *pHead = NULL; 44 List *pEnd = NULL; 45 InitInfo(&pHead,&pEnd,10); 46 while(1) 47 { 48 printf("1.查看通讯录\n"); 49 printf("2.添加信息\n"); 50 printf("3.查询信息\n"); 51 printf("4.删除信息\n"); 52 printf("5.修改信息\n"); 53 printf("q.退出\n"); 54 c = GetKey(); 55 switch(c) 56 { 57 case '1': 58 g_MenuType = 1; 59 Browse(pHead); 60 break; 61 case '2': 62 AddMessage(&pHead,&pEnd); 63 break; 64 case '3': 65 g_MenuType = 3; 66 Query(pHead); 67 break; 68 case '4': 69 g_MenuType = 4; 70 DeleteInfo(&pHead,&pEnd); 71 break; 72 case '5': 73 g_MenuType = 5; 74 UpDataInfo(pHead); 75 break; 76 case 'q': 77 return 0; 78 break; 79 } 80 } 81 return 0; 82 } 83 int GetId() 84 { 85 static int id = 0; 86 id++; 87 return id; 88 } 89 char *GetName() //随机分配姓名 90 { 91 char *pname = (char *)malloc(6); 92 int i; 93 for(i = 0;i < 5;i++) 94 { 95 pname[i] = rand()%26 + 'a'; 96 } 97 pname[i] = '\0'; 98 99 return pname; 100 } 101 char *GetTel() //随机分配电话号码 102 { 103 char *ptel = (char *)malloc(12); 104 int i; 105 int num = rand()%4+1; 106 switch(num) 107 { 108 case 1: 109 strcpy_s(ptel,12,"132"); 110 break; 111 case 2: 112 strcpy_s(ptel,12,"157"); 113 break; 114 case 3: 115 strcpy_s(ptel,12,"188"); 116 break; 117 default: 118 strcpy_s(ptel,12,"150"); 119 break; 120 } 121 for(i = 3;i < 11;i++) 122 { 123 ptel[i] = rand()%10 + '0'; 124 } 125 ptel[i] = '\0'; 126 127 return ptel; 128 } 129 List *GetNode() 130 { 131 List *pTemp = (List *)malloc(sizeof(List)); 132 pTemp->id = GetId(); 133 pTemp->name = GetName(); 134 pTemp->tel = GetTel(); 135 pTemp->next = NULL; 136 137 return pTemp; 138 } 139 List *GetMyNode() 140 { 141 List *pTemp = (List *)malloc(sizeof(List)); 142 pTemp->id = GetId(); 143 printf("请输入姓名: "); 144 pTemp->name = GetString(); 145 printf("请输入电话: "); 146 pTemp->tel = GetString(); 147 pTemp->next = NULL; 148 149 150 return pTemp; 151 } 152 void AddNode(List **ppHead,List **ppEnd,List *pNode) 153 { 154 if(*ppHead == NULL) 155 { 156 *ppHead = pNode; 157 } 158 else 159 { 160 (*ppEnd)->next = pNode; 161 } 162 *ppEnd = pNode; 163 164 return; 165 } 166 void InitInfo(List **ppHead,List **ppEnd,int n) 167 { 168 int i; 169 srand((unsigned int)time(NULL)); 170 for(i = 0;i < n;i++) 171 { 172 AddNode(ppHead,ppEnd,GetNode()); 173 } 174 175 } 176 Page *GetPage(List *pHead,int OnePageInfo) 177 { 178 179 Page *pPage = (Page *)malloc(sizeof(Page)); 180 pPage->CurrentPage = 0; 181 pPage->TotalInfo = 0; 182 pPage->OnePageInfo = OnePageInfo; 183 while(pHead) 184 { 185 pPage->TotalInfo++; 186 pHead = pHead->next; 187 } 188 pPage->TotalPage = pPage->TotalInfo%pPage->OnePageInfo == 0 ? pPage->TotalInfo / pPage->OnePageInfo : pPage->TotalInfo / pPage->OnePageInfo + 1; //三目运算符 相当于if-else的简写 189 190 return pPage; 191 } 192 void ShowInfo(List *pHead,Page *pPage) 193 { 194 int PageBegin = (pPage->CurrentPage - 1) * pPage->OnePageInfo + 1; 195 int PageEnd = (pPage->CurrentPage) * (pPage->OnePageInfo); 196 int InfoNum = 0; 197 while(pHead) 198 { 199 InfoNum++; 200 if(InfoNum >= PageBegin && InfoNum <= PageEnd) 201 printf("%d\t%s\t%s\n",pHead->id,pHead->name,pHead->tel); 202 pHead = pHead->next; 203 } 204 return; 205 206 } 207 void TurnPage(List *pHead,Page *pPage) 208 { 209 char c = 's'; 210 while(1) 211 { 212 switch(c) 213 { 214 case 's': 215 if(pPage->CurrentPage < pPage->TotalPage) 216 { 217 pPage->CurrentPage++; 218 ShowInfo(pHead,pPage); 219 ShowMenu(pPage); 220 } 221 else 222 { 223 printf("已经是最后一页了!\n"); 224 ShowMenu(pPage); 225 } 226 break; 227 case 'w': 228 if(pPage->CurrentPage > 1) 229 { 230 pPage->CurrentPage--; 231 ShowInfo(pHead,pPage); 232 ShowMenu(pPage); 233 } 234 else 235 { 236 printf("已经是第一页了!\n"); 237 ShowMenu(pPage); 238 } 239 break; 240 case 'e': 241 return; 242 break; 243 case 'c': 244 return; 245 break; 246 case 'd': 247 return; 248 break; 249 case 'y': 250 return; 251 break; 252 case 'u': 253 return; 254 break; 255 default: 256 printf("请输入规定的按键!\n"); 257 break; 258 } 259 c = GetKey(); 260 g_Key = c; 261 // getchar(); //清空缓冲区内的\n 262 } 263 } 264 char GetKey() 265 { 266 char c; 267 char z = '!'; 268 int flag = 1; 269 while((c=getchar()) != '\n' || 1 == flag) //考虑了\n在之前的情况 270 { 271 z = c; 272 flag = 0; 273 } 274 return z; 275 } 276 void Browse(List *pHead) 277 { 278 Page *pPage = GetPage(pHead,5); 279 TurnPage(pHead,pPage); 280 } 281 void ShowMenu(Page *pPage) 282 { 283 switch(g_MenuType) 284 { 285 case 1: 286 printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo); 287 break; 288 case 3: 289 printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\tc重新查询\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo); 290 break; 291 case 4: 292 printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\td删除信息\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo); 293 break; 294 case 5: 295 printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\tu修改信息\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo); 296 break; 297 } 298 299 300 } 301 char *GetString() 302 { 303 int size = 5; 304 int count = 0; 305 char *str = (char *)malloc(size); 306 char *pMark = str; 307 char *newstr = NULL; 308 char c; 309 while((c = getchar()) != '\n') 310 { 311 *str = c; 312 str++; 313 count++; 314 if(count + 1 == size) 315 { 316 *str = '\0'; 317 size += 5; 318 newstr = (char *)malloc(size); 319 strcpy_s(newstr,size,pMark); 320 free(pMark); 321 pMark = newstr; 322 str = newstr + count; 323 } 324 } 325 *str = '\0'; 326 327 return pMark; 328 } 329 void AddMessage(List **ppHead,List **ppEnd) 330 { 331 List *pNode = GetMyNode(); 332 AddNode(ppHead,ppEnd,pNode); 333 } 334 void Query(List *pHead) 335 { 336 List *pDel; 337 List *newpHead = NULL; 338 List *newpEnd = NULL; 339 char Choose; 340 char *KeyWord = NULL; 341 List *pNode = NULL; 342 List *pMark = pHead; 343 while(1) 344 { 345 while(1) 346 { 347 printf("请输入查询关键字: "); 348 KeyWord = GetString(); 349 printf("a.确认 其他键.重新输入\n"); 350 Choose = GetKey(); 351 //switch(Choose) 352 //{ 353 //case 'a': 354 // printf("%s\n",KeyWord); 355 // return; 356 // break; 357 //case 'c': 358 // printf("请重新输入!\n"); 359 // free(KeyWord); //堆区内存不需要的话就要及时释放 360 // break; 361 //} //第一种方法 用switch去选择按键 362 if(Choose == 'a') //第二种方法 363 { 364 break; 365 } 366 else 367 { 368 free(KeyWord); //堆区内存不需要的话就要及时释放 369 KeyWord = NULL; 370 } 371 } 372 pHead = pMark; 373 while(pHead) 374 { 375 if(!strncmp(pHead->name,KeyWord,strlen(KeyWord)) || !strncmp(pHead->tel,KeyWord,strlen(KeyWord))) //输入的长度可以用字符串长度 376 { 377 pNode = (List *)malloc(sizeof(List)); //创建一个新的链表 用现成的接口和函数进行调用 378 pNode->id = pHead->id; 379 pNode->name = pHead->name; 380 pNode->tel = pHead->tel; 381 pNode->next = NULL; 382 AddNode(&newpHead,&newpEnd,pNode); 383 } 384 pHead = pHead->next; 385 } 386 Browse(newpHead); 387 while(newpHead) //清除之前所有的结点 388 { 389 pDel = newpHead; 390 newpHead = newpHead->next; 391 free(pDel); 392 pDel = NULL; 393 } 394 if('e' == g_Key || 'd' == g_Key || 'u' == g_Key) 395 { 396 return; 397 } 398 } 399 } 400 void DeleteNode(List **ppHead,List **ppEnd,int id) 401 { 402 List *pDel = NULL; 403 List *pMov = *ppHead; 404 if((*ppHead)->id == id) 405 { 406 pDel = *ppHead; 407 *ppHead = (*ppHead)->next; 408 free(pDel->name); 409 free(pDel->tel); 410 free(pDel); 411 pDel = NULL; 412 printf("删除成功!\n"); 413 return; 414 } 415 if(pMov->next) 416 { 417 if(pMov->next->id == id) 418 { 419 if(pMov->next == *ppEnd) 420 { 421 pDel = *ppEnd; 422 *ppEnd = pMov; 423 (*ppEnd)->next = NULL; 424 } 425 else 426 { 427 pDel = pMov->next; 428 pMov->next = pMov->next->next; 429 } 430 free(pDel->name); 431 free(pDel->tel); 432 free(pDel); 433 pDel = NULL; 434 printf("删除成功!\n"); 435 return; 436 } 437 pMov = pMov->next; 438 } 439 } 440 void DeleteInfo(List **ppHead,List **ppEnd) 441 { 442 int i; 443 while(1) 444 { 445 Query(*ppHead); 446 if('e'==g_Key) 447 { 448 break; 449 } 450 printf("请输入要删除的编号: "); 451 scanf("%d",&i); 452 DeleteNode(ppHead,ppEnd,i); 453 printf("y.继续删除 其他键返回\n"); 454 if(GetKey() != 'y') 455 { 456 break; 457 } 458 } 459 } 460 void UpDataInfo(List *pHead) 461 { 462 char *str = NULL; 463 int id; 464 while(1) 465 { 466 Query(pHead); 467 if('e'==g_Key) 468 { 469 break; 470 } 471 printf("请输入修改的编号: "); 472 scanf("%d",&id); //用getchar()清除缓冲区内信息 473 getchar(); 474 while(pHead) 475 { 476 if(pHead->id == id) 477 { 478 printf("请修改姓名: "); 479 str = GetString(); 480 if(strlen(str) > 0) 481 { 482 free(pHead->name); 483 pHead->name = str; 484 } 485 printf("请修改电话号: "); 486 str = GetString(); 487 if(strlen(str) > 0) 488 { 489 free(pHead->tel); 490 pHead->tel = str; 491 } 492 return; 493 } 494 pHead = pHead->next; 495 } 496 } 497 }
2019-04-28 23:37:16 编程小菜鸡自我反省,大佬勿喷,谢谢!!!