【问题标题】:Program doesn't execute gets() after scanf(), even using fflush(stdin)程序在 scanf() 之后不执行 gets(),即使使用 fflush(stdin)
【发布时间】:2014-04-09 05:01:46
【问题描述】:

在浪费了太多时间搜索为什么我的程序在使用 scanf() 后没有执行 gets() 之后,我找到了一个解决方案,即在 scanf() 之后使用 fflush(stdin) 来启用 gets() 获取字符串.

问题在于 fflush(stdin) 没有按照预期执行:程序继续跳过gets(),我无法在控制台中写入任何要读取的短语。

我的代码是下一个:

#include <string.h>
#include <stdio.h>

int main(){
    char nombre[10];
    char mensaje[80];

    printf("Type your name:\n");
    scanf("%s", nombre);

    fflush(stdin);

    printf("Now, type a message:\n");
    gets(mensaje);

    printf("3/%s:%s",nombre,mensaje);
    return 0;
}

【问题讨论】:

标签: c scanf gets fflush


【解决方案1】:

试试这个:

scanf("%s\n", nombre);

scanf 在读取部分时停止在空白处。读取直到第一个新行。所以会发生什么是 scanf 在缓冲区中留下一个换行符,它会立即看到并认为它被赋予了一个空行。

如果您使用原始代码并输入“名称消息”,两部分都在一行上,您可以看到这一点 - 获取仍然会立即返回,但它会看到第二部分。

scanf 中的 \n 告诉它继续消费它。

【讨论】:

  • 感谢您的回答,但这不是解决方案,因为在我输入名称后,按 enter 并保持空白,直到我输入内容并按 enter,然后控制台显示“现在,输入消息: "
  • 错误的解决方案。 scanf("%s\n", nombre);“告诉它继续消费它。”并继续阅读,直到检测到非白色景观。然后它返回。
【解决方案2】:

尝试gets(stdin); 而不是

fflush(stdin);

【讨论】:

  • 对不起,错字,我的错,使用 getc(stdin),而不是 fflush(stdin),fflush 函数不会从输入流中刷新数据;相反,它用于推送缓冲在输出流中的数据。
  • 谢谢你,史密特!使用 getc(stdin) 也可以完美运行。对不起,我先看到另一个答案并接受了它,但至少我会给你一个积极的投票。 ;)
【解决方案3】:

如果刷新 std 不起作用,请尝试读入多余的字符并丢弃,如建议的 here

这将起作用:

#include <string.h>
#include <stdio.h>

int main(){
    char nombre[10];
    char mensaje[80];
    int c;

    printf("Type your name:\n");
    scanf("%9s", nombre);

    while((c= getchar()) != '\n' && c != EOF)
            /* discard */ ;

    printf("Now, type a message:\n");
    gets(mensaje);

    printf("%s:%s",nombre,mensaje);
    return 0;
}

【讨论】:

  • 谢谢埃姆斯沃思!它运行完美! ;)
  • 没错,我继续删除它
【解决方案4】:

两个重大的问题:

  1. 请勿在输入流中使用fflushfflush 在输入流上的行为未定义。仅仅因为它看起来在这种情况下工作并不意味着它是正确的。

  2. NEVER NEVER NEVER NEVER NEVER NEVER NEVER 使用 gets - 它在 C99 标准中已被弃用,并已从 C2011 标准中完全删除。它(不是可能,)在您的代码中引入一个主要的故障点。

scanf 调用后跟gets 调用绝不是一个好主意,因为gets 不会跳过scanf 在输入流中留下的任何前导换行符。使用scanf 阅读两者 nombremesaje

printf("Type your name:\n");
scanf("%9s", nombre);

printf("Now, type a message:\n");
scanf("%79s", mensaje);

最好在scanf 调用%s%[ 中使用显式长度说明符,否则会引入与gets 相同的安全漏洞。

编辑

哦。我是个白痴。如果您尝试读取包含空格的字符串,则不能使用 %s 转换说明符。请改用%[ 转换说明符:

scanf( "%79[^\n]", mensage );

这将读取接下来的 79 个字符或换行符,以先到者为准,并将换行符留在输入流中。

【讨论】:

  • 我不知道为什么,但是如果我使用“%79s”或“%s”会发生同样的情况:scanf 只获取整个短语的第一个单词,所以我一直在使用获取()。
  • scanf( "%79[^\n]", mensage ); after scanf("%9s", nombre); 可以轻松读取任何内容,因为第一个字符可能是 '\n'scanf( " %79[^\n]", mensage ); 稍微好一点,但失去了前导空格。
【解决方案5】:
while (fgetc(stdin) != '\n'); // seems to work

【讨论】:

  • 欢迎来到 StackOverflow,用户 9816128。您想通过一些解释来增加您的纯代码答案吗?以目前的形式,它不太可能吸引赞成票。
猜你喜欢
  • 1970-01-01
  • 2015-06-26
  • 2012-09-19
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
相关资源
最近更新 更多