鱼C论坛

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

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

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

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

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

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


代码如下:
#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:
屏幕截图 2023-07-16 182947.png

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

就出现了死循环
最佳答案
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;
    }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

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

解决这个问题的一个常见方法是,在  scanf  失败时清空输入缓冲区。例如,你可以在你的  default  case中添加代码以清空输入缓冲区:
default:    printf("输入有误!请重新输入!");    while ((ch = getchar()) != '\n' && ch != EOF);    break;
这段代码将读取并丢弃输入缓冲区中的所有字符,直到读取到换行符  \n  或文件结束符 EOF,这样就可以避免死循环问题了。在用户输入非整数时,程序会显示错误消息,并要求用户重新输入。

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

使用道具 举报

发表于 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;}
通过在每次输入后清空输入流,可以避免因输入非数字字符导致的死循环问题。

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

使用道具 举报

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

使用道具 举报

发表于 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;
    }
}
想知道小甲鱼最近在做啥?请访问 -> 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-11-21 19:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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