C:为什么fgets功能不起作用? [重复]

问题描述 投票:-1回答:1

这个问题在这里已有答案:

我正在编写一个程序来创建一个链表节点。之后,我添加了一些功能(插入,搜索,更新和打印)。链表包含手头的编号,名称和数量。

主函数提示用户输入操作代码,然后调用函数请求的操作。

    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

你能告诉我发生了什么吗,请问?

c
1个回答
4
投票

好吧,问题是fgets消耗了之前输入的stdin中留下的\n。简单的方法是使用虚拟getchar()或使用fgets,直到你获得非空白输入。

做一件事,在scanf放了一个getchar()

scanf("%c",&code);
getchar(); 
^^^^
Will consume the `\n`.

为了给你一个更清楚的解释,假设你输入iEnter

然后将i存储到变量code中。但是\n怎么样? fgets()开始阅读来自stdin的输入时发现\n并且它停止了。通过使用getchar()你消耗了\n。现在所有非空白字符都将由fgets消耗,直到它找到\nEOFbuffer变满为止。

冲洗标准输入的最便携和最干净的方法是(要正确的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(你输入2ENTER)仍在那里,fgets消耗它。所以我们需要在那里放置虚拟getchar()或上面显示的stdin冲洗技术。

scanf("%d",&new_node->number);
getchar();
^^^^
This consumes the stray `\n` 
© www.soinside.com 2019 - 2024. All rights reserved.