鱼C论坛

 找回密码
 立即注册
查看: 1227|回复: 7

[已解决]在第二次调用查找函数的时候就出错,能帮我看看吗?

[复制链接]
发表于 2020-2-23 16:28:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Telbook
  5. {
  6.         char name[12];
  7.         char number[15];
  8.         char beizhu[24];
  9.         struct Telbook *next;
  10. } PLR,*PLRPIN;


  11. void PrintInfo(PLRPIN Info);
  12. void InsertInfo(PLRPIN *Info); //把地址给它,用*把系统分给头指针的地址里的值拿出来做修改,就可以指向其它的值,所以要两层引用
  13. void InputInfo(PLRPIN);
  14. void releaseInfo(PLRPIN *Info);//释放所有内存空间,不是一个结构哟
  15. void searchInfo(PLRPIN Info);
  16. void DelInfo(PLRPIN *Info);
  17. void ModfiyInfo(PLRPIN *INFO);


  18. #define ME_ALLCARD 1
  19. #define ME_FOUNDCARD 2
  20. #define ME_DELCARD 3
  21. #define ME_MODIFYCARD 4
  22. #define ME_NEWCARD 5
  23. #define ME_EXIT 0

  24. #define _CRT_SECURE_NO_WARNINGS //排错

  25. int main()
  26. {
  27.         int iMenu;
  28.         char cExit,cInput;
  29.         PLRPIN Headr=NULL; //声明一个头指针,并给值等0;

  30.        
  31.         do
  32.         {
  33.                 printf("\n|-------------------------------|菜单|-----------------------------------|\n\n");
  34.                 printf("|  1.显示所有名片|2.查找名片|3.删除名片|4.修改名片|5.新建名片|0.退出  |\n\n");
  35.                 printf("|--------------------------------------------------------------------------|\n");

  36.                 printf("\n请输入数字选择菜单:");
  37. reInput:
  38.                 scanf("%d",&iMenu); //条件选择菜单
  39.                 switch(iMenu)
  40.                 {
  41.                 case ME_ALLCARD:
  42.                         PrintInfo(Headr);
  43.                         break;
  44.                 case ME_FOUNDCARD:
  45.                
  46.                         searchInfo(Headr);
  47.                         break;
  48.                 case ME_DELCARD:
  49.                         DelInfo(&Headr);
  50.                         break;
  51.                 case ME_NEWCARD:
  52.                         while(1)
  53.                         {
  54.                                 printf("请问是否要新建名片(Y/N):");
  55.                                 do
  56.                                 {
  57.                                         cInput=getchar();

  58.                                 }while(cInput !='Y' && cInput != 'N');
  59.                                 if(cInput == 'Y')
  60.                                 {
  61.                                         InsertInfo(&Headr);
  62.                                 }
  63.                                 else
  64.                                 {
  65.                                         break;
  66.                                 }
  67.                         }
  68.                        
  69.                         break;
  70.                 case ME_MODIFYCARD:
  71.                         ModfiyInfo(&Headr);
  72.                         break;
  73.                 case ME_EXIT:
  74.                         printf("感谢您的使用,程序准备退出!\n确认退出请输入(Y/N):");
  75.                         do
  76.                         {
  77.                         cExit=getchar();
  78.                         }while(cExit != 'Y' && cExit != 'N');
  79.                         if(cExit == 'Y')
  80.                         {
  81.                                 releaseInfo(&Headr);
  82.                                 exit(1);
  83.                         }
  84.                         break;
  85.                 default :
  86.                         printf("输入的选项无效,请重新输入(1~5):");
  87.                         goto reInput;
  88.                         break;
  89.                 }
  90.         }while(1);
  91.         //releaseInfo(&Headr);
  92.         return 0;
  93. }


  94. void DelInfo(PLRPIN *Info) //删除信息
  95. {
  96.         char cName[24];
  97.         char cYesNo;
  98.         PLRPIN Current,Previous;

  99.         printf("请输入要删除的名片姓名:");
  100.         scanf("%s",cName);
  101.         printf("确定要删除 %s 吗?(Y/N):",cName);
  102.         do
  103.         {
  104.                
  105.                 cYesNo = getchar();
  106.         }while (cYesNo != 'Y' && cYesNo != 'N');
  107.        
  108.         if(cYesNo == 'Y')
  109.         {
  110.                 Current = *Info;
  111.                 Previous = NULL;

  112.                 while(Current != NULL && Current->name == cName) //搜查符合的条件
  113.                 {
  114.                         Previous =Current;
  115.                         Current=Current->next;
  116.                 }
  117.                 if(Current == NULL)
  118.                 {
  119.                         printf("没有找到要删除的名片,请确认您的输入!\n");
  120.                         return ;
  121.                 }
  122.                 else
  123.                 {
  124.                         if(Previous == NULL)
  125.                         {
  126.                                 *Info=Current->next;

  127.                         }
  128.                         else
  129.                         {
  130.                                 Previous->next=Current->next;
  131.                         }
  132.                         printf("删除成功!\n");
  133.                          free(Current);
  134.                 }
  135.         }
  136. }

  137. void InsertInfo(PLRPIN *Info) //传入指向指针结构的指针来修改指针/拿到头指指针就能操作单链表,所有主函数里的是头指针,传递给其它函数便于操作。
  138. {
  139.         PLRPIN Temp,New;
  140.         static PLRPIN Nup; //尾插法的重点,必须是静态变量,才能一直指向NULL
  141.         New=(PLRPIN)malloc(sizeof(PLR));

  142.         if(NULL == New)
  143.         {
  144.                 printf("新的空间分配失败\n");
  145.                 return ;
  146.         }

  147.         InputInfo(New);
  148.         //--------------------尾插法---------------------------------
  149.         if(*Info != NULL)
  150.         {
  151.                 Nup->next = New;
  152.                 New->next=NULL;

  153.                 /*------------遍历效率代------------------
  154.                 while (Temp->next != NULL)
  155.                 {
  156.                         //Temp = Temp->next; //搜查NULL
  157.                 }
  158.                 //找到NULL插入数据
  159.                 Temp->next= New;
  160.                 New->next = NULL;
  161.                 ---------------------------*/
  162.         }
  163.         else
  164.         {
  165.                 *Info = New;
  166.                 New->next = NULL;
  167.         }
  168.                 Nup=New;
  169.         /**************************头插法*********************************
  170.         if(*Info != NULL)
  171.         {
  172.                 Temp=*Info; //把头指针放入TEMP 再把新的转接赋值达到插入的目的。
  173.                 *Info=New;
  174.                 New->next=Temp;
  175.         }
  176.         else
  177.         {
  178.                 *Info=New;
  179.                 New->next=NULL;
  180.         }
  181.         *******************************************************************/
  182. }

  183. void InputInfo(PLRPIN Info) //输入信息
  184. {
  185.         PLRPIN New;
  186.         New=Info;
  187.         printf("请输入姓名:");
  188.         scanf("%s",New->name);
  189.         printf("请给人物职业:");
  190.         scanf("%s",New->beizhu);
  191.         printf("请输入号码:");
  192.         scanf("%s",New->number);
  193. }

  194. void PrintInfo(PLRPIN Info) //打印输出
  195. {
  196.        
  197.         PLRPIN New;
  198.         int count =1;

  199.         New=Info;

  200.         printf("\n\n|------------------------------|通迅录|----------------------------------|\n\n");
  201.         printf("|编号|\t|姓名|\t|职业|\t|联系方式|\n");
  202.         while(New != NULL )
  203.         {
  204.                 printf("%5d%17s%18s%21s\n",count,New->name,New->beizhu,New->number);
  205.                 New=New->next;
  206.                 count++;
  207.         }
  208.         putchar('\n');
  209. }

  210. void releaseInfo(PLRPIN *Info) //释放空间
  211. {
  212.         PLRPIN Temp;
  213.         while (*Info != NULL)
  214.         {
  215.                 Temp=*Info;
  216.                 *Info=(*Info)->next;
  217.                 free(Temp);
  218.         }
  219. }

  220. void searchInfo(PLRPIN Info)  //查找信息
  221. {
  222.         char target[128];
  223.         PLRPIN New;
  224.         printf("请输入要找查名片的信息[姓名,职业,电话号码] :");
  225.         scanf("%s",target);

  226.         New=Info;

  227.         while(New != NULL)
  228.         {
  229.                 if(!strcmp(New->name,target) || !strcmp(New->beizhu,target) || !strcmp(New->number,target))
  230.                 {
  231.                         break;
  232.                 }
  233.                 New = New->next;
  234.         }


  235.         if(New == NULL)
  236.         {
  237.                 printf("很抱赚,没有找到您要的结果!\n");
  238.         }
  239.         else
  240.         {
  241.                 do
  242.                 {
  243.                         printf("已找到符合条件的名片...\n");
  244.                         PrintInfo(New);
  245.                 }while(New->next != NULL);               
  246.         }

  247.         releaseInfo(&New);
  248.        
  249. }


  250. void ModfiyInfo(PLRPIN *Info)  //修改信息
  251. {
  252.         char cName[24];
  253.         char cYesNo;
  254.         PLRPIN Current;

  255.         printf("请输入要修改名片的姓名:");
  256.         scanf("%s",cName);
  257.         printf("确定要修改 %s 信息吗?(Y/N):",cName);

  258.         do
  259.         {
  260.                 cYesNo = getchar();
  261.         }while (cYesNo != 'Y' && cYesNo != 'N');
  262.        
  263.         if(cYesNo == 'Y')
  264.         {
  265.                 Current = *Info;
  266.                

  267.                 while(Current != NULL && Current->name == cName) //搜查符合的条件
  268.                 {
  269.                         Current=Current->next;
  270.                 }
  271.                 if(Current == NULL)
  272.                 {
  273.                         printf("没有找到要修改的名片,请确认您的输入!\n");
  274.                         return ;
  275.                 }
  276.                 else
  277.                 {
  278.                         printf("找到匹配:%s %s %s\n",Current->name,Current->beizhu,Current->number );
  279.                         printf("将%s修改为:",Current->name);
  280.                         scanf("%s",Current->name);

  281.                         printf("将%s修改为:",Current->beizhu);
  282.                         scanf("%s",Current->beizhu);

  283.                         printf("将%s修改为:",Current->number);
  284.                         scanf("%s",Current->number);
  285.                         printf("修改后的信息为:%s %s %s\n",Current->name,Current->beizhu,Current->number );
  286.                         printf("修改成功!\n");
  287.                 }
  288.         }
  289. }
复制代码



第二次调用查找函数就出错,但不知道是什么原因。
最佳答案
2020-2-25 16:08:41
帮你修改了。
主要是DelInfo()和searcheInfo();详细看注释。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Telbook
  5. {
  6.     char name[12];
  7.     char number[15];
  8.     char beizhu[24];
  9.     struct Telbook *next;
  10. } PLR, *PLRPIN;

  11. void PrintInfo(PLRPIN Info);
  12. void InsertInfo(PLRPIN *Info); //把地址给它,用*把系统分给头指针的地址里的值拿出来做修改,就可以指向其它的值,所以要两层引用
  13. void InputInfo(PLRPIN);
  14. void releaseInfo(PLRPIN *Info); //释放所有内存空间,不是一个结构哟
  15. void searchInfo(PLRPIN Info);
  16. void DelInfo(PLRPIN *Info);
  17. void ModfiyInfo(PLRPIN *INFO);

  18. #define ME_ALLCARD 1
  19. #define ME_FOUNDCARD 2
  20. #define ME_DELCARD 3
  21. #define ME_MODIFYCARD 4
  22. #define ME_NEWCARD 5
  23. #define ME_EXIT 0

  24. #define _CRT_SECURE_NO_WARNINGS //排错

  25. int main()
  26. {
  27.     int iMenu;
  28.     char cExit, cInput;
  29.     PLRPIN Headr = NULL; //声明一个头指针,并给值等0;

  30.     do
  31.     {
  32.         printf("\n|-------------------------------|菜单|-----------------------------------|\n\n");
  33.         printf("|  1.显示所有名片|2.查找名片|3.删除名片|4.修改名片|5.新建名片|0.退出  |\n\n");
  34.         printf("|--------------------------------------------------------------------------|\n");

  35.         printf("\n请输入数字选择菜单:");
  36.     reInput:
  37.         scanf("%d", &iMenu); //条件选择菜单
  38.         switch (iMenu)
  39.         {
  40.         case ME_ALLCARD:
  41.             PrintInfo(Headr);
  42.             break;
  43.         case ME_FOUNDCARD:
  44.             searchInfo(Headr);
  45.             break;
  46.         case ME_DELCARD:
  47.             DelInfo(&Headr);
  48.             break;
  49.         case ME_NEWCARD:
  50.             while (1)
  51.             {
  52.                 printf("请问是否要新建名片(Y/N):");
  53.                 do
  54.                 {
  55.                     cInput = getchar();

  56.                 } while (cInput != 'Y' && cInput != 'N');
  57.                 if (cInput == 'Y')
  58.                 {
  59.                     InsertInfo(&Headr);
  60.                 }
  61.                 else
  62.                 {
  63.                     break;
  64.                 }
  65.             }
  66.             break;
  67.         case ME_MODIFYCARD:
  68.             ModfiyInfo(&Headr);
  69.             break;
  70.         case ME_EXIT:
  71.             printf("感谢您的使用,程序准备退出!\n确认退出请输入(Y/N):");
  72.             do
  73.             {
  74.                 cExit = getchar();
  75.             } while (cExit != 'Y' && cExit != 'N');
  76.             if (cExit == 'Y')
  77.             {
  78.                 releaseInfo(&Headr);
  79.                 exit(1);
  80.             }
  81.             break;
  82.         default:
  83.             printf("输入的选项无效,请重新输入(1~5):");
  84.             goto reInput;
  85.             break;
  86.         }
  87.     } while (1);
  88.     //releaseInfo(&Headr);
  89.     return 0;
  90. }

  91. void DelInfo(PLRPIN *Info) //删除信息
  92. {
  93.     char cName[24];
  94.     char cYesNo;
  95.     PLRPIN Current, Previous;

  96.     printf("请输入要删除的名片姓名:");
  97.     scanf("%s", cName);
  98.     printf("确定要删除 %s 吗?(Y/N):", cName);
  99.     do
  100.     {
  101.         cYesNo = getchar();
  102.     } while (cYesNo != 'Y' && cYesNo != 'N');

  103.     if (cYesNo == 'Y')
  104.     {
  105.         Current = *Info;
  106.         Previous = NULL;
  107.         //while (Current != NULL && Current->name == cName) //这里逻辑错误;应该是Current->name!=name
  108.         while (Current != NULL && strcmp(Current->name, cName))
  109.         {
  110.             Previous = Current;
  111.             Current = Current->next;
  112.         }

  113.         if (Current == NULL)
  114.         {
  115.             printf("没有找到要删除的名片,请确认您的输入!\n");
  116.             return;
  117.         }
  118.         else
  119.         {
  120.             if (Previous == NULL)
  121.             {
  122.                 *Info = Current->next;
  123.             }
  124.             else
  125.             {
  126.                 Previous->next = Current->next;
  127.             }
  128.             printf("删除成功!\n");
  129.             free(Current);
  130.         }
  131.     }
  132. }

  133. void InsertInfo(PLRPIN *Info) //传入指向指针结构的指针来修改指针/拿到头指指针就能操作单链表,所有主函数里的是头指针,传递给其它函数便于操作。
  134. {
  135.     PLRPIN Temp, New;
  136.     static PLRPIN Nup; //尾插法的重点,必须是静态变量,才能一直指向NULL
  137.     New = (PLRPIN)malloc(sizeof(PLR));

  138.     if (NULL == New)
  139.     {
  140.         printf("新的空间分配失败\n");
  141.         return;
  142.     }

  143.     InputInfo(New);
  144.     //--------------------尾插法---------------------------------
  145.     if (*Info != NULL)
  146.     {
  147.         Nup->next = New;
  148.         New->next = NULL;

  149.         /*------------遍历效率代------------------
  150.                 while (Temp->next != NULL)
  151.                 {
  152.                         //Temp = Temp->next; //搜查NULL
  153.                 }
  154.                 //找到NULL插入数据
  155.                 Temp->next= New;
  156.                 New->next = NULL;
  157.                 ---------------------------*/
  158.     }
  159.     else
  160.     {
  161.         *Info = New;
  162.         New->next = NULL;
  163.     }
  164.     Nup = New;
  165.     /**************************头插法*********************************
  166.         if(*Info != NULL)
  167.         {
  168.                 Temp=*Info; //把头指针放入TEMP 再把新的转接赋值达到插入的目的。
  169.                 *Info=New;
  170.                 New->next=Temp;
  171.         }
  172.         else
  173.         {
  174.                 *Info=New;
  175.                 New->next=NULL;
  176.         }
  177.         *******************************************************************/
  178. }

  179. void InputInfo(PLRPIN Info) //输入信息
  180. {
  181.     PLRPIN New;
  182.     New = Info;
  183.     printf("请输入姓名:");
  184.     scanf("%s", New->name);
  185.     printf("请给人物职业:");
  186.     scanf("%s", New->beizhu);
  187.     printf("请输入号码:");
  188.     scanf("%s", New->number);
  189. }

  190. void PrintInfo(PLRPIN Info) //打印输出
  191. {

  192.     PLRPIN New;
  193.     int count = 1;

  194.     New = Info;

  195.     printf("\n\n|------------------------------|通迅录|----------------------------------|\n\n");
  196.     printf("|编号|\t|姓名|\t|职业|\t|联系方式|\n");
  197.     while (New != NULL)
  198.     {
  199.         printf("%5d%17s%18s%21s\n", count, New->name, New->beizhu, New->number);
  200.         New = New->next;
  201.         count++;
  202.     }
  203.     putchar('\n');
  204. }

  205. void releaseInfo(PLRPIN *Info) //释放空间
  206. {
  207.     PLRPIN Temp;
  208.     while (*Info != NULL)
  209.     {
  210.         Temp = *Info;
  211.         *Info = (*Info)->next;
  212.         free(Temp);
  213.     }
  214. }

  215. void searchInfo(PLRPIN Info) //查找信息
  216. {
  217.     char target[128];
  218.     PLRPIN New;
  219.     printf("请输入要找查名片的信息[姓名,职业,电话号码] :");
  220.     scanf("%s", target);

  221.     New = Info;
  222.     PLRPIN founded=NULL;
  223.    
  224.     // while (New != NULL)
  225.     // {
  226.     //     if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
  227.     //     {
  228.     //         break;
  229.     //     }
  230.     //     New = New->next;
  231.     // } //这一块有问题,只找到第一个符号条件的名片。

  232.     while (New != NULL) // 查找目标名片,把所有找到的名片用新链表founded指示
  233.     {
  234.         if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
  235.         {
  236.             PLRPIN node= (PLRPIN)malloc(sizeof(PLR)); // 新建结点存储搜索到的结点
  237.             *node = *New; //将找到的名片内容copy到新链表中
  238.             node->next = NULL; //next 复位,防止影响原链表内容
  239.             if (founded == NULL)
  240.             {
  241.                 founded = node;
  242.             }
  243.             else
  244.             {
  245.                 founded->next = node;
  246.             }
  247.         }
  248.         New = New->next;
  249.     }

  250.     if (founded == NULL)
  251.     {
  252.         printf("很抱赚,没有找到您要的结果!\n");
  253.     }
  254.     else
  255.     {
  256.         printf("已找到符合条件的名片...\n");
  257.         PrintInfo(founded); // 打印搜索处理的名片
  258.         // do
  259.         // {
  260.         //     printf("已找到符合条件的名片...\n");
  261.         //     //PrintInfo(New);//这个函数是从New所指的结点打印之后的所有名片啊!这样调用有问题吧;

  262.         // } while (New->next != NULL);
  263.     }
  264.     releaseInfo(&founded); // 打印完成后释放掉新建的链表

  265.     //releaseInfo(&New); //不能调用releaseInfo; New所指向的名片结点和Info中的某些结点是共用的。
  266.                          //调用之后,会把Info中与指针New地址相同的结点之后的所有结点的内存空间释放掉
  267. }

  268. void ModfiyInfo(PLRPIN *Info) //修改信息
  269. {
  270.     char cName[24];
  271.     char cYesNo;
  272.     PLRPIN Current;

  273.     printf("请输入要修改名片的姓名:");
  274.     scanf("%s", cName);
  275.     printf("确定要修改 %s 信息吗?(Y/N):", cName);

  276.     do
  277.     {
  278.         cYesNo = getchar();
  279.     } while (cYesNo != 'Y' && cYesNo != 'N');

  280.     if (cYesNo == 'Y')
  281.     {
  282.         Current = *Info;

  283.         while (Current != NULL && Current->name == cName) //搜查符合的条件
  284.         {
  285.             Current = Current->next;
  286.         }
  287.         if (Current == NULL)
  288.         {
  289.             printf("没有找到要修改的名片,请确认您的输入!\n");
  290.             return;
  291.         }
  292.         else
  293.         {
  294.             printf("找到匹配:%s %s %s\n", Current->name, Current->beizhu, Current->number);
  295.             printf("将%s修改为:", Current->name);
  296.             scanf("%s", Current->name);

  297.             printf("将%s修改为:", Current->beizhu);
  298.             scanf("%s", Current->beizhu);

  299.             printf("将%s修改为:", Current->number);
  300.             scanf("%s", Current->number);
  301.             printf("修改后的信息为:%s %s %s\n", Current->name, Current->beizhu, Current->number);
  302.             printf("修改成功!\n");
  303.         }
  304.     }
  305. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-2-23 22:14:36 | 显示全部楼层
本帖最后由 4goodworld 于 2020-2-23 22:15 编辑

个人探讨,你这个检索,为啥要循环呢?
  1.   do
  2.                 {
  3.                         printf("已找到符合条件的名片...\n");
  4.                         PrintInfo(New);
  5.                 }while(New->next != NULL);      
复制代码

你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个?
  1.     while(New != NULL )
  2.         {
  3.                 printf("%5d%17s%18s%21s\n",count,New->name,New->beizhu,New->number);
  4.                 New=New->next;
  5.                 count++;
  6.         }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-23 23:34:14 | 显示全部楼层
4goodworld 发表于 2020-2-23 22:14
个人探讨,你这个检索,为啥要循环呢?

你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个? ...

因为有可能会找到两个,必如我输入职业:有3个是职业是一样的就可以全打出来,还有就是显示所有的时候
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-23 23:36:04 | 显示全部楼层
4goodworld 发表于 2020-2-23 22:14
个人探讨,你这个检索,为啥要循环呢?

你这个打印函数为啥要循环打印呢?找到了一个,不应该打印一个? ...

您帮我测试一下,第二次调用查找函数就出错什么原因呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-23 23:54:22 | 显示全部楼层
黄翼 发表于 2020-2-23 23:34
因为有可能会找到两个,必如我输入职业:有3个是职业是一样的就可以全打出来,还有就是显示所有的时候

我个人的建议,你得把自己的函数构思好、设计好,很多东西杂在一起,反而前后制约,让你顾此失彼。
如果打印只打印一个
然后,是不是就可以在搜索里优化,继续搜下去然后继续打印
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 16:08:41 | 显示全部楼层    本楼为最佳答案   
帮你修改了。
主要是DelInfo()和searcheInfo();详细看注释。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Telbook
  5. {
  6.     char name[12];
  7.     char number[15];
  8.     char beizhu[24];
  9.     struct Telbook *next;
  10. } PLR, *PLRPIN;

  11. void PrintInfo(PLRPIN Info);
  12. void InsertInfo(PLRPIN *Info); //把地址给它,用*把系统分给头指针的地址里的值拿出来做修改,就可以指向其它的值,所以要两层引用
  13. void InputInfo(PLRPIN);
  14. void releaseInfo(PLRPIN *Info); //释放所有内存空间,不是一个结构哟
  15. void searchInfo(PLRPIN Info);
  16. void DelInfo(PLRPIN *Info);
  17. void ModfiyInfo(PLRPIN *INFO);

  18. #define ME_ALLCARD 1
  19. #define ME_FOUNDCARD 2
  20. #define ME_DELCARD 3
  21. #define ME_MODIFYCARD 4
  22. #define ME_NEWCARD 5
  23. #define ME_EXIT 0

  24. #define _CRT_SECURE_NO_WARNINGS //排错

  25. int main()
  26. {
  27.     int iMenu;
  28.     char cExit, cInput;
  29.     PLRPIN Headr = NULL; //声明一个头指针,并给值等0;

  30.     do
  31.     {
  32.         printf("\n|-------------------------------|菜单|-----------------------------------|\n\n");
  33.         printf("|  1.显示所有名片|2.查找名片|3.删除名片|4.修改名片|5.新建名片|0.退出  |\n\n");
  34.         printf("|--------------------------------------------------------------------------|\n");

  35.         printf("\n请输入数字选择菜单:");
  36.     reInput:
  37.         scanf("%d", &iMenu); //条件选择菜单
  38.         switch (iMenu)
  39.         {
  40.         case ME_ALLCARD:
  41.             PrintInfo(Headr);
  42.             break;
  43.         case ME_FOUNDCARD:
  44.             searchInfo(Headr);
  45.             break;
  46.         case ME_DELCARD:
  47.             DelInfo(&Headr);
  48.             break;
  49.         case ME_NEWCARD:
  50.             while (1)
  51.             {
  52.                 printf("请问是否要新建名片(Y/N):");
  53.                 do
  54.                 {
  55.                     cInput = getchar();

  56.                 } while (cInput != 'Y' && cInput != 'N');
  57.                 if (cInput == 'Y')
  58.                 {
  59.                     InsertInfo(&Headr);
  60.                 }
  61.                 else
  62.                 {
  63.                     break;
  64.                 }
  65.             }
  66.             break;
  67.         case ME_MODIFYCARD:
  68.             ModfiyInfo(&Headr);
  69.             break;
  70.         case ME_EXIT:
  71.             printf("感谢您的使用,程序准备退出!\n确认退出请输入(Y/N):");
  72.             do
  73.             {
  74.                 cExit = getchar();
  75.             } while (cExit != 'Y' && cExit != 'N');
  76.             if (cExit == 'Y')
  77.             {
  78.                 releaseInfo(&Headr);
  79.                 exit(1);
  80.             }
  81.             break;
  82.         default:
  83.             printf("输入的选项无效,请重新输入(1~5):");
  84.             goto reInput;
  85.             break;
  86.         }
  87.     } while (1);
  88.     //releaseInfo(&Headr);
  89.     return 0;
  90. }

  91. void DelInfo(PLRPIN *Info) //删除信息
  92. {
  93.     char cName[24];
  94.     char cYesNo;
  95.     PLRPIN Current, Previous;

  96.     printf("请输入要删除的名片姓名:");
  97.     scanf("%s", cName);
  98.     printf("确定要删除 %s 吗?(Y/N):", cName);
  99.     do
  100.     {
  101.         cYesNo = getchar();
  102.     } while (cYesNo != 'Y' && cYesNo != 'N');

  103.     if (cYesNo == 'Y')
  104.     {
  105.         Current = *Info;
  106.         Previous = NULL;
  107.         //while (Current != NULL && Current->name == cName) //这里逻辑错误;应该是Current->name!=name
  108.         while (Current != NULL && strcmp(Current->name, cName))
  109.         {
  110.             Previous = Current;
  111.             Current = Current->next;
  112.         }

  113.         if (Current == NULL)
  114.         {
  115.             printf("没有找到要删除的名片,请确认您的输入!\n");
  116.             return;
  117.         }
  118.         else
  119.         {
  120.             if (Previous == NULL)
  121.             {
  122.                 *Info = Current->next;
  123.             }
  124.             else
  125.             {
  126.                 Previous->next = Current->next;
  127.             }
  128.             printf("删除成功!\n");
  129.             free(Current);
  130.         }
  131.     }
  132. }

  133. void InsertInfo(PLRPIN *Info) //传入指向指针结构的指针来修改指针/拿到头指指针就能操作单链表,所有主函数里的是头指针,传递给其它函数便于操作。
  134. {
  135.     PLRPIN Temp, New;
  136.     static PLRPIN Nup; //尾插法的重点,必须是静态变量,才能一直指向NULL
  137.     New = (PLRPIN)malloc(sizeof(PLR));

  138.     if (NULL == New)
  139.     {
  140.         printf("新的空间分配失败\n");
  141.         return;
  142.     }

  143.     InputInfo(New);
  144.     //--------------------尾插法---------------------------------
  145.     if (*Info != NULL)
  146.     {
  147.         Nup->next = New;
  148.         New->next = NULL;

  149.         /*------------遍历效率代------------------
  150.                 while (Temp->next != NULL)
  151.                 {
  152.                         //Temp = Temp->next; //搜查NULL
  153.                 }
  154.                 //找到NULL插入数据
  155.                 Temp->next= New;
  156.                 New->next = NULL;
  157.                 ---------------------------*/
  158.     }
  159.     else
  160.     {
  161.         *Info = New;
  162.         New->next = NULL;
  163.     }
  164.     Nup = New;
  165.     /**************************头插法*********************************
  166.         if(*Info != NULL)
  167.         {
  168.                 Temp=*Info; //把头指针放入TEMP 再把新的转接赋值达到插入的目的。
  169.                 *Info=New;
  170.                 New->next=Temp;
  171.         }
  172.         else
  173.         {
  174.                 *Info=New;
  175.                 New->next=NULL;
  176.         }
  177.         *******************************************************************/
  178. }

  179. void InputInfo(PLRPIN Info) //输入信息
  180. {
  181.     PLRPIN New;
  182.     New = Info;
  183.     printf("请输入姓名:");
  184.     scanf("%s", New->name);
  185.     printf("请给人物职业:");
  186.     scanf("%s", New->beizhu);
  187.     printf("请输入号码:");
  188.     scanf("%s", New->number);
  189. }

  190. void PrintInfo(PLRPIN Info) //打印输出
  191. {

  192.     PLRPIN New;
  193.     int count = 1;

  194.     New = Info;

  195.     printf("\n\n|------------------------------|通迅录|----------------------------------|\n\n");
  196.     printf("|编号|\t|姓名|\t|职业|\t|联系方式|\n");
  197.     while (New != NULL)
  198.     {
  199.         printf("%5d%17s%18s%21s\n", count, New->name, New->beizhu, New->number);
  200.         New = New->next;
  201.         count++;
  202.     }
  203.     putchar('\n');
  204. }

  205. void releaseInfo(PLRPIN *Info) //释放空间
  206. {
  207.     PLRPIN Temp;
  208.     while (*Info != NULL)
  209.     {
  210.         Temp = *Info;
  211.         *Info = (*Info)->next;
  212.         free(Temp);
  213.     }
  214. }

  215. void searchInfo(PLRPIN Info) //查找信息
  216. {
  217.     char target[128];
  218.     PLRPIN New;
  219.     printf("请输入要找查名片的信息[姓名,职业,电话号码] :");
  220.     scanf("%s", target);

  221.     New = Info;
  222.     PLRPIN founded=NULL;
  223.    
  224.     // while (New != NULL)
  225.     // {
  226.     //     if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
  227.     //     {
  228.     //         break;
  229.     //     }
  230.     //     New = New->next;
  231.     // } //这一块有问题,只找到第一个符号条件的名片。

  232.     while (New != NULL) // 查找目标名片,把所有找到的名片用新链表founded指示
  233.     {
  234.         if (!strcmp(New->name, target) || !strcmp(New->beizhu, target) || !strcmp(New->number, target))
  235.         {
  236.             PLRPIN node= (PLRPIN)malloc(sizeof(PLR)); // 新建结点存储搜索到的结点
  237.             *node = *New; //将找到的名片内容copy到新链表中
  238.             node->next = NULL; //next 复位,防止影响原链表内容
  239.             if (founded == NULL)
  240.             {
  241.                 founded = node;
  242.             }
  243.             else
  244.             {
  245.                 founded->next = node;
  246.             }
  247.         }
  248.         New = New->next;
  249.     }

  250.     if (founded == NULL)
  251.     {
  252.         printf("很抱赚,没有找到您要的结果!\n");
  253.     }
  254.     else
  255.     {
  256.         printf("已找到符合条件的名片...\n");
  257.         PrintInfo(founded); // 打印搜索处理的名片
  258.         // do
  259.         // {
  260.         //     printf("已找到符合条件的名片...\n");
  261.         //     //PrintInfo(New);//这个函数是从New所指的结点打印之后的所有名片啊!这样调用有问题吧;

  262.         // } while (New->next != NULL);
  263.     }
  264.     releaseInfo(&founded); // 打印完成后释放掉新建的链表

  265.     //releaseInfo(&New); //不能调用releaseInfo; New所指向的名片结点和Info中的某些结点是共用的。
  266.                          //调用之后,会把Info中与指针New地址相同的结点之后的所有结点的内存空间释放掉
  267. }

  268. void ModfiyInfo(PLRPIN *Info) //修改信息
  269. {
  270.     char cName[24];
  271.     char cYesNo;
  272.     PLRPIN Current;

  273.     printf("请输入要修改名片的姓名:");
  274.     scanf("%s", cName);
  275.     printf("确定要修改 %s 信息吗?(Y/N):", cName);

  276.     do
  277.     {
  278.         cYesNo = getchar();
  279.     } while (cYesNo != 'Y' && cYesNo != 'N');

  280.     if (cYesNo == 'Y')
  281.     {
  282.         Current = *Info;

  283.         while (Current != NULL && Current->name == cName) //搜查符合的条件
  284.         {
  285.             Current = Current->next;
  286.         }
  287.         if (Current == NULL)
  288.         {
  289.             printf("没有找到要修改的名片,请确认您的输入!\n");
  290.             return;
  291.         }
  292.         else
  293.         {
  294.             printf("找到匹配:%s %s %s\n", Current->name, Current->beizhu, Current->number);
  295.             printf("将%s修改为:", Current->name);
  296.             scanf("%s", Current->name);

  297.             printf("将%s修改为:", Current->beizhu);
  298.             scanf("%s", Current->beizhu);

  299.             printf("将%s修改为:", Current->number);
  300.             scanf("%s", Current->number);
  301.             printf("修改后的信息为:%s %s %s\n", Current->name, Current->beizhu, Current->number);
  302.             printf("修改成功!\n");
  303.         }
  304.     }
  305. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 17:08:28 | 显示全部楼层
黄翼 发表于 2020-2-23 23:36
您帮我测试一下,第二次调用查找函数就出错什么原因呢?

第二次调用查找函数出错是因为你第一次掉的时候查找函数最后的releaseInfo(New)把链表中的一部分结点删掉了,导致数据结构被破坏。New的前一个结点的next不等于Null,但是其指向的结点New已经吧free掉了。
具体看我在6楼的回复
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-2 19:12:48 | 显示全部楼层
major_lyu 发表于 2020-2-25 17:08
第二次调用查找函数出错是因为你第一次掉的时候查找函数最后的releaseInfo(New)把链表中的一部分结点删掉 ...

谢谢哈
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-13 01:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表