这个问题在这里已有答案:
我正在编写一个程序来创建一个链表节点。之后,我添加了一些功能(插入,搜索,更新和打印)。链表包含手头的编号,名称和数量。
主函数提示用户输入操作代码,然后调用函数请求的操作。
main()
{
char code;
int c;
for(;;)
{
printf("i: insert\ns: search\nu: update\np: print\n");
printf("Enter operation code: ");
scanf("%c",&code);
while((c=getchar() )!= '\n'&& c!=EOF);
switch(code)
{
case 'i': insert();
break;
case 's': search();
break;
case 'u': update();
break;
case 'p': print();
break;
case 'q':return 0;
default: printf("Illegal code\n");
break;
}
printf("\n");
}
}
所有功能都正常工作。但是,在insert函数中,我使用fgets语句来获取用户输入的字符串。 (NAME_LEN = 25)
void insert()
{
node *previous,*current,*new_node;
new_node = malloc(sizeof(node));
printf("Enter part number: ");
scanf("%d",&new_node->number);
for(current = inventory,previous=NULL;
current != NULL&& new_node->number > current->number;
previous = current,current = current -> next);
if(current != NULL && new_node ->number == current->number)
{
printf("Part already exists.\n");
free(new_node);
return;
}
printf("Enter name part: ");
fgets(new_node->Name,NAME_LEN+1,stdin); // i use fgets to input string name
printf("Enter quantity on hand: ");
scanf("%d",&new_node->on_hand);
new_node -> next = current;
// move to the next node
if(previous == NULL)
inventory =new_node;
else
previous->next = new_node;
}
不幸的是,这段代码不起作用。该计划表明
i: insert
s: search
u: update
p: print
Enter operation code: i
Enter part number: 2
Enter name part: Enter quantity on hand: 3
正如你所看到的那样,名字部分被遗漏了。
此外,在插入新节点后,程序会自动在交换机中显示默认情况。
i: insert
s: search
u: update
p: print
Enter operation code: i
Enter part number: 2
Enter name part: Enter quantity on hand: 3
i: insert
s: search
u: update
p: print
Enter operation code: Illegal code
你能告诉我发生了什么吗,请问?
好吧,问题是fgets
消耗了之前输入的stdin中留下的\n
。简单的方法是使用虚拟getchar()
或使用fgets
,直到你获得非空白输入。
做一件事,在scanf
放了一个getchar()
。
scanf("%c",&code);
getchar();
^^^^
Will consume the `\n`.
为了给你一个更清楚的解释,假设你输入i
Enter
然后将i
存储到变量code
中。但是\n
怎么样? fgets()
开始阅读来自stdin
的输入时发现\n
并且它停止了。通过使用getchar()
你消耗了\n
。现在所有非空白字符都将由fgets
消耗,直到它找到\n
或EOF
或buffer
变满为止。
冲洗标准输入的最便携和最干净的方法是(要正确的stdin
必须至少有\n
字符,否则它将继续吃其他charcaters(也许你的有效输入))。
int c;
while ((c = getchar()) != '\n' && c != EOF);
这可以在您遇到一些垃圾输入或清除标准输入时使用。
另外要真正了解fgets
功能是否有效,您需要检查它返回的内容。它会返回NULL
吗?如果没有,那么检查它,然后尝试理解。只是因为你在打印时没有看到任何输出缓冲区并不意味着fgets
失败了。
编辑
首先发布的问题提到在fgets
之后有scanf("%c",&code)
。在编辑中很明显scanf("%d",&new_node->number);
在fgets
之前存在,但这并没有改变场景。现在输入数字后的\n
(你输入2
ENTER)仍在那里,fgets
消耗它。所以我们需要在那里放置虚拟getchar()
或上面显示的stdin
冲洗技术。
scanf("%d",&new_node->number);
getchar();
^^^^
This consumes the stray `\n`