【问题标题】:Why is my second printf not called when expected?为什么我的第二个 printf 在预期的时候没有被调用?
【发布时间】:2013-11-10 14:17:01
【问题描述】:

我刚刚学习用 C 编程,对 scanfgetchar 发生的事情有点困惑。我知道使用scanf("%d", &i) 之类的东西会读取一个整数输入,但会在输入缓冲区中留下以下换行符(这就是为什么在@987654327 之后使用getchar 之前必须通过查找getchar() == '\n' 来清除输入缓冲区的原因@调用。

这是我的简单(不正确)程序,它读取一个整数,然后输入一个字符,并将它们打印回用户:

int main(void)
{
    int i;
    printf("Enter an integer: ");
    scanf("%d\n", &i);

    printf("Enter a char: ");
    char ch = getchar();

    printf("You entered integer: %d\nYou entered character: %c\n", i, ch);

    return 0;
}

如果我在我的scanf 格式字符串中保留换行符(所以只有"%d"),那么只要用户输入一个整数并点击输入,该整数就会被读取并存储在i,程序将继续执行(“输入一个字符:”立即打印,ch存储换行符)。

但是,使用 "%d\n" 的格式字符串时,我遇到了意外行为。当用户输入一个整数并按回车键时,我希望打印“输入一个字符:”。相反,您可以继续按 Enter 键,直到您决定输入不同的字符之前什么都不会发生。所以你可以输入“10”,按回车键 6 次,然后输入“d”,getchar() 会“正确”读取。整个程序的输出应该是这样的

Enter an integer: 10




d
Enter a char: You entered integer: 10
You entered character: d

为什么我的程序直到输入一个字符才会停止?我的第二个printf 函数似乎在调用getchar 之后被调用,这似乎很奇怪(因为读取的字符是在“输入字符:”打印之前输入的)。

任何帮助将不胜感激。我只是想进一步了解 C 中的这种细微差别。

【问题讨论】:

  • 不要使用scanf()。如果你不完全知道它是如何工作的,那就是为什么。如果您确实知道它是如何工作的,那么这就是原因。 We can have nicer things.
  • @H2CO3 明白了。这只是一个练习。我试图进一步了解scanf() 是如何处理空白的。在这种情况下,换行符。
  • 是的,这很好,我绝对想阻止你学习。正如人们应该了解 C++ 中的原始指针(尽管它通常不使用)一样,您也应该了解scanf()。我只是警告说,它通常不是在生产中使用的最佳选择。
  • @H2CO3 很公平,这也是我读过的(我相信我正在读的书中提到过)。但它肯定有它的用途(在一些非常罕见的情况下,goto 也是如此)。什么是更安全的替代品?我超越了我目前的理解,但我 认为 scanf 在与正则表达式混合时可以做一些花哨的输入格式。还有更安全的选择吗?
  • 我最喜欢的概念是:一个功能 - 一个目的。试图做不止一件事的功能本质上是有缺陷的。 scanf() 尝试同时进行 I/O 和解析。不太好。如果可以的话,最好将 I/O 部分(fgets()getchar()getline()fread()read() 等)与解析部分分开。对于解析,还有一些有用的标准库函数,例如strtok_r()str[r]chr()strstr(),也许最终是sscanf()

标签: c input scanf getchar


【解决方案1】:

scanf 格式字符串中,任何空白字符序列都将匹配输入中任意数量的空白。所以你的\n 将匹配任意数量的换行符,而scanf 只会在遇到非空格字符时返回。

【讨论】:

  • 好吧,这清楚了。不敢相信我错过了:-/ 非常感谢。
【解决方案2】:

我不确定,但您可以尝试以下方法:

printf("Enter an integer: ");
scanf("%d\n", &i);
fflush(stdin);

【讨论】:

    【解决方案3】:

    scanf docs (for linux) 说:

    “一系列空白字符(空格、制表符、换行符等;参见 isspace(3))。该指令匹配输入中任意数量的空白,包括无空白。”

    基本上 \n 不匹配逐字换行符,它匹配任意数量的空格,直到遇到非空格字符。

    所以你的scanf("%d\n", &i) 吃掉了所有的空白,直到它看到一个非空白字符才返回。使用scanf("%d\t", &i)scanf("%d ", &i) 将获得相同的效果

    【讨论】:

    • 感谢您的澄清。我正在阅读的参考资料提到了这一点,但它并没有点击第一眼或第二眼。该参考文献中的措辞要直截了当。
    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多