为什么会出现死循环?
代码如下:
#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:
很正常,然后我们再输入一个字母:
就出现了死循环
死循环问题是因为你在读取输入时使用了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 失败,我们就知道输入是无效的,然后可以给出错误提示。 在你的代码中,死循环的原因是在输入非数字字符时,输入流中保留了非数字字符,导致下一次循环读取时继续读取到非数字字符,从而进入死循环。
为了解决这个问题,你可以在每次读取输入后,清空输入流中的内容,以确保下一次读取不会受到影响。
可以使用以下代码来清空输入流:
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;
}
通过在每次输入后清空输入流,可以避免因输入非数字字符导致的死循环问题。
希望这可以解决你的问题! @夏季的春秋 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;
}
} 个人倾向于用fflush yinda_peng 发表于 2023-7-16 20:54
个人倾向于用fflush
{:10_275:}
页:
[1]