yinda_peng 发表于 2023-7-16 18:31:40

为什么会出现死循环?




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


typedef struct Node
{
      int value;
      struct Node *next;
}Node;

void printList(Node *head)
{

      head = head->next;
      int i=1;
      while(head!=NULL)
      {
                printf("%d ",head->value);
                head = head->next;
               
      }
      printf("\n");
}

void makeList(Node **head,int len,int Max)
{
      
      Node *r,*n;
      r = *head;
      
      srand((unsigned)time(NULL));
      int i=1;
      while(i++ <=len)
      {
                n = (Node*)malloc(sizeof(Node));
                n->value = rand()%Max+1;
               
                r->next =n;
                n->next = NULL;
                r= n;
      }
      printf("链表创建完毕!\n");
}
void Mid(Node *head)
{
      Node *max,*min;
      max = head;
      min = head;
      while(max->next != NULL)
      {
                if(max->next->next != NULL)
                {
                        max = max->next->next;
                        min = min->next;
                }
      }
      printf("中间节点的值为:%d\n",min->value);
}


int main()
{
      Node *head = (Node *)malloc(sizeof(Node));
      printf("1,查看链表\n");
      printf("2,创建链表(尾插法)\n");
      printf("3,链表长度\n");
      printf("4,中间节点值\n");
      printf("0,退出\n");
      int ch;
      int len=20,Max = 100;
      while(1)
      {      
                printf("\n请输入编号选择操作(0/1/2/3/4):\n");
                scanf("%d",&ch);
                switch(ch)
                {
                        case 2:makeList(&head,len,Max);break;
                        case 1:printList(head);break;
                        case 3:printf("Length = %d\n",len);break;
                        case 4:Mid(head);break;
                        case 0:return;
                        default:printf("输入有误!请重新输入!");
                }
               
      }


      
      return 0;
}然后运行过程中功能部分即输入01234是正常的,但是在输入其它东西之后就出现了死循环
我们编译输入一个5:


很正常,然后我们再输入一个字母:


就出现了死循环

isdkz 发表于 2023-7-16 18:32:08

死循环问题是因为你在读取输入时使用了scanf函数。在你的代码中,你尝试使用scanf函数来读取一个整数。然而,如果用户输入的不是整数(例如,一个字母或者特殊字符), scanf函数会失败,输入的字符将仍然保留在输入缓冲区中,导致程序陷入死循环。

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

解决这个问题的一个常见方法是,在scanf失败时清空输入缓冲区。例如,你可以在你的defaultcase中添加代码以清空输入缓冲区:

default:
    printf("输入有误!请重新输入!");
    while ((ch = getchar()) != '\n' && ch != EOF);
    break;


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

另外一个可能的方法是使用 fgets 和 sscanf 来读取和解析输入,这种方式会更安全,因为 fgets 会读取整行输入,包括换行符,而 sscanf 则可以在字符串中解析出我们需要的数据。如果 sscanf 失败,我们就知道输入是无效的,然后可以给出错误提示。

陶远航 发表于 2023-7-16 18:32:08

在你的代码中,死循环的原因是在输入非数字字符时,输入流中保留了非数字字符,导致下一次循环读取时继续读取到非数字字符,从而进入死循环。

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

可以使用以下代码来清空输入流:

int c;
while ((c = getchar()) != '\n' && c != EOF) {}


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

具体修改后的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Node {
    int value;
    struct Node *next;
} Node;

void printList(Node *head) {
    head = head->next;
    int i = 1;
    while (head != NULL) {
      printf("%d ", head->value);
      head = head->next;
    }
    printf("\n");
}

void makeList(Node **head, int len, int Max) {
    Node *r, *n;
    r = *head;
    srand((unsigned) time(NULL));
    int i = 1;
    while (i++ <= len) {
      n = (Node *) malloc(sizeof(Node));
      n->value = rand() % Max + 1;
      r->next = n;
      n->next = NULL;
      r = n;
    }
    printf("链表创建完毕!\n");
}

void Mid(Node *head) {
    Node *max, *min;
    max = head;
    min = head;
    while (max->next != NULL) {
      if (max->next->next != NULL) {
            max = max->next->next;
            min = min->next;
      }
    }
    printf("中间节点的值为:%d\n", min->value);
}

int main() {
    Node *head = (Node *) malloc(sizeof(Node));
    printf("1,查看链表\n");
    printf("2,创建链表(尾插法)\n");
    printf("3,链表长度\n");
    printf("4,中间节点值\n");
    printf("0,退出\n");

    int ch;
    int len = 20, Max = 100;

    while (1) {
      printf("\n请输入编号选择操作(0/1/2/3/4):\n");
      scanf("%d", &ch);

      switch (ch) {
            case 2:
                makeList(&head, len, Max);
                break;
            case 1:
                printList(head);
                break;
            case 3:
                printf("Length = %d\n", len);
                break;
            case 4:
                Mid(head);
                break;
            case 0:
                return 0;
            default:
                printf("输入有误!请重新输入!");
                break;
      }

      // 清空输入流
      int c;
      while ((c = getchar()) != '\n' && c != EOF) {}
    }

    return 0;
}


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

希望这可以解决你的问题!

yinda_peng 发表于 2023-7-16 18:32:27

@夏季的春秋

sfqxx 发表于 2023-7-16 20:07:18

while (1)
{
    printf("\n请输入编号选择操作(0/1/2/3/4):\n");
    scanf("%d", &ch);
    fflush(stdin);// 清空输入缓冲区

    switch (ch)
    {
      case 2: makeList(&head, len, Max); break;
      case 1: printList(head); break;
      case 3: printf("Length = %d\n", len); break;
      case 4: Mid(head); break;
      case 0: return 0;
      default:
            printf("输入有误!请重新输入!");
            fflush(stdin);// 清空输入缓冲区
            break;
    }
}

yinda_peng 发表于 2023-7-16 20:54:53

个人倾向于用fflush

sfqxx 发表于 2023-7-17 11:15:59

yinda_peng 发表于 2023-7-16 20:54
个人倾向于用fflush

{:10_275:}
页: [1]
查看完整版本: 为什么会出现死循环?