鱼C论坛

 找回密码
 立即注册
查看: 705|回复: 6

[已解决]为什么会出现死循环?

[复制链接]
发表于 2023-7-16 18:31:40 | 显示全部楼层 |阅读模式

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

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

x
屏幕截图 2023-07-16 182713.png


代码如下:
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>


  4. typedef struct Node
  5. {
  6.         int value;
  7.         struct Node *next;
  8. }Node;

  9. void printList(Node *head)
  10. {

  11.         head = head->next;
  12.         int i=1;
  13.         while(head!=NULL)
  14.         {
  15.                 printf("%d ",head->value);
  16.                 head = head->next;
  17.                
  18.         }
  19.         printf("\n");
  20. }

  21. void makeList(Node **head,int len,int Max)
  22. {
  23.       
  24.         Node *r,*n;
  25.         r = *head;
  26.       
  27.         srand((unsigned)time(NULL));
  28.         int i=1;
  29.         while(i++ <=len)
  30.         {
  31.                 n = (Node*)malloc(sizeof(Node));
  32.                 n->value = rand()%Max+1;
  33.                
  34.                 r->next =n;
  35.                 n->next = NULL;
  36.                 r= n;
  37.         }
  38.         printf("链表创建完毕!\n");
  39. }
  40. void Mid(Node *head)
  41. {
  42.         Node *max,*min;
  43.         max = head;
  44.         min = head;
  45.         while(max->next != NULL)
  46.         {
  47.                 if(max->next->next != NULL)
  48.                 {
  49.                         max = max->next->next;
  50.                         min = min->next;
  51.                 }
  52.         }
  53.         printf("中间节点的值为:%d\n",min->value);
  54. }


  55. int main()
  56. {
  57.         Node *head = (Node *)malloc(sizeof(Node));
  58.         printf("1,查看链表\n");
  59.         printf("2,创建链表(尾插法)\n");
  60.         printf("3,链表长度\n");
  61.         printf("4,中间节点值\n");
  62.         printf("0,退出\n");
  63.         int ch;
  64.         int len=20,Max = 100;
  65.         while(1)
  66.         {      
  67.                 printf("\n请输入编号选择操作(0/1/2/3/4):\n");
  68.                 scanf("%d",&ch);
  69.                 switch(ch)
  70.                 {
  71.                         case 2:makeList(&head,len,Max);break;
  72.                         case 1:printList(head);break;
  73.                         case 3:printf("Length = %d\n",len);break;
  74.                         case 4:Mid(head);break;
  75.                         case 0:return;
  76.                         default:printf("输入有误!请重新输入!");
  77.                 }
  78.                
  79.         }


  80.       
  81.         return 0;
  82. }
复制代码
然后运行过程中功能部分即输入01234是正常的,但是在输入其它东西之后就出现了死循环
我们编译输入一个5:
屏幕截图 2023-07-16 182947.png

很正常,然后我们再输入一个字母:
屏幕截图 2023-07-16 183049.png

就出现了死循环
最佳答案
2023-7-16 20:07:18
  1. while (1)
  2. {
  3.     printf("\n请输入编号选择操作(0/1/2/3/4):\n");
  4.     scanf("%d", &ch);
  5.     fflush(stdin);  // 清空输入缓冲区

  6.     switch (ch)
  7.     {
  8.         case 2: makeList(&head, len, Max); break;
  9.         case 1: printList(head); break;
  10.         case 3: printf("Length = %d\n", len); break;
  11.         case 4: Mid(head); break;
  12.         case 0: return 0;
  13.         default:
  14.             printf("输入有误!请重新输入!");
  15.             fflush(stdin);  // 清空输入缓冲区
  16.             break;
  17.     }
  18. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-16 18:32:08 | 显示全部楼层
死循环问题是因为你在读取输入时使用了  scanf  函数。在你的代码中,你尝试使用  scanf  函数来读取一个整数。然而,如果用户输入的不是整数(例如,一个字母或者特殊字符), scanf  函数会失败,输入的字符将仍然保留在输入缓冲区中,导致程序陷入死循环。

在你的例子中,当用户输入一个字母(比如 'a')时, scanf  尝试读取一个整数,但是无法成功。因为 'a' 仍然在输入缓冲区中,所以下一次循环, scanf  又会尝试读取同样的 'a',导致死循环。

解决这个问题的一个常见方法是,在  scanf  失败时清空输入缓冲区。例如,你可以在你的  default  case中添加代码以清空输入缓冲区:
  1. default:
  2.     printf("输入有误!请重新输入!");
  3.     while ((ch = getchar()) != '\n' && ch != EOF);
  4.     break;
复制代码

这段代码将读取并丢弃输入缓冲区中的所有字符,直到读取到换行符  \n  或文件结束符 EOF,这样就可以避免死循环问题了。在用户输入非整数时,程序会显示错误消息,并要求用户重新输入。

另外一个可能的方法是使用 fgets 和 sscanf 来读取和解析输入,这种方式会更安全,因为 fgets 会读取整行输入,包括换行符,而 sscanf 则可以在字符串中解析出我们需要的数据。如果 sscanf 失败,我们就知道输入是无效的,然后可以给出错误提示。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-16 18:32:08 | 显示全部楼层
在你的代码中,死循环的原因是在输入非数字字符时,输入流中保留了非数字字符,导致下一次循环读取时继续读取到非数字字符,从而进入死循环。

为了解决这个问题,你可以在每次读取输入后,清空输入流中的内容,以确保下一次读取不会受到影响。

可以使用以下代码来清空输入流:
  1. int c;
  2. while ((c = getchar()) != '\n' && c != EOF) {}
复制代码

将该代码段添加到每次输入后即可。

具体修改后的代码如下:
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>
  4. typedef struct Node {
  5.     int value;
  6.     struct Node *next;
  7. } Node;
  8. void printList(Node *head) {
  9.     head = head->next;
  10.     int i = 1;
  11.     while (head != NULL) {
  12.         printf("%d ", head->value);
  13.         head = head->next;
  14.     }
  15.     printf("\n");
  16. }
  17. void makeList(Node **head, int len, int Max) {
  18.     Node *r, *n;
  19.     r = *head;
  20.     srand((unsigned) time(NULL));
  21.     int i = 1;
  22.     while (i++ <= len) {
  23.         n = (Node *) malloc(sizeof(Node));
  24.         n->value = rand() % Max + 1;
  25.         r->next = n;
  26.         n->next = NULL;
  27.         r = n;
  28.     }
  29.     printf("链表创建完毕!\n");
  30. }
  31. void Mid(Node *head) {
  32.     Node *max, *min;
  33.     max = head;
  34.     min = head;
  35.     while (max->next != NULL) {
  36.         if (max->next->next != NULL) {
  37.             max = max->next->next;
  38.             min = min->next;
  39.         }
  40.     }
  41.     printf("中间节点的值为:%d\n", min->value);
  42. }
  43. int main() {
  44.     Node *head = (Node *) malloc(sizeof(Node));
  45.     printf("1,查看链表\n");
  46.     printf("2,创建链表(尾插法)\n");
  47.     printf("3,链表长度\n");
  48.     printf("4,中间节点值\n");
  49.     printf("0,退出\n");
  50.     int ch;
  51.     int len = 20, Max = 100;
  52.     while (1) {
  53.         printf("\n请输入编号选择操作(0/1/2/3/4):\n");
  54.         scanf("%d", &ch);
  55.         switch (ch) {
  56.             case 2:
  57.                 makeList(&head, len, Max);
  58.                 break;
  59.             case 1:
  60.                 printList(head);
  61.                 break;
  62.             case 3:
  63.                 printf("Length = %d\n", len);
  64.                 break;
  65.             case 4:
  66.                 Mid(head);
  67.                 break;
  68.             case 0:
  69.                 return 0;
  70.             default:
  71.                 printf("输入有误!请重新输入!");
  72.                 break;
  73.         }
  74.         // 清空输入流
  75.         int c;
  76.         while ((c = getchar()) != '\n' && c != EOF) {}
  77.     }
  78.     return 0;
  79. }
复制代码

通过在每次输入后清空输入流,可以避免因输入非数字字符导致的死循环问题。

希望这可以解决你的问题!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-16 18:32:27 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-16 20:07:18 | 显示全部楼层    本楼为最佳答案   
  1. while (1)
  2. {
  3.     printf("\n请输入编号选择操作(0/1/2/3/4):\n");
  4.     scanf("%d", &ch);
  5.     fflush(stdin);  // 清空输入缓冲区

  6.     switch (ch)
  7.     {
  8.         case 2: makeList(&head, len, Max); break;
  9.         case 1: printList(head); break;
  10.         case 3: printf("Length = %d\n", len); break;
  11.         case 4: Mid(head); break;
  12.         case 0: return 0;
  13.         default:
  14.             printf("输入有误!请重新输入!");
  15.             fflush(stdin);  // 清空输入缓冲区
  16.             break;
  17.     }
  18. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-16 20:54:53 From FishC Mobile | 显示全部楼层
个人倾向于用fflush
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-17 11:15:59 | 显示全部楼层
yinda_peng 发表于 2023-7-16 20:54
个人倾向于用fflush

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-20 00:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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