【问题标题】:Question about scanf function in C关于C中scanf函数的问题
【发布时间】:2011-04-22 19:28:37
【问题描述】:

我有一个关于 scanf 函数如何工作的问题。在这个程序中:

#include <stdio.h>

int main(void) {

    int x;
    char y;

    printf("Write a number: ");
    scanf("%d", &x);

    printf("Write a character: ");
    scanf(" %c", &y);

    printf("%d", x);
    printf("%c", y);

    return 0;
}

如果用户输入一个数字然后按回车键,那么 scanf 函数将从格式字符串中看到应该是一个数字。当用户点击输入时,它不会读取换行符并将其放回缓冲区中。然后,由于我接下来要读取一个字符,因此我需要在格式字符串中包含一个空格,因为 scanf 函数会采用换行符并放入 y 变量。

但是我只是好奇如果用户写了类似的东西会发生什么

j344lk4fjk388

它会把所有东西都放回缓冲区吗?缓冲区中“放回”的所有内容都会被我程序中的下一个 scanf 函数自动读取吗?

我正在阅读:C Programming A Modern Approach 2nd Edition

【问题讨论】:

  • 为什么不编译程序,然后输入它来找出答案?如果您需要查看目前尚不可见的情况,请添加日志记录语句或使用调试器。

标签: c


【解决方案1】:

您应该始终检查来自scanf() 的返回值,以确保您预期的所有转换都成功。

给定样本输入:

j344lk4fjk388

第一个 scanf() 将失败,因为 j 无法转换为整数 - 返回 0 表示成功转换的次数。第二次调用会成功,返回 'j' 作为字符。

如果您需要将字符串视为整数,请使用fgets() 或相对(可能是POSIX getline())来读取字符串,然后使用strtoul()(或适当的相对 - strtol()、@987654329 @、strtoull()strtoimax()strtoumax()),指定基数至少为 21 以转换 'j',或 23 以获取 'l' 和 'k'。

【讨论】:

    【解决方案2】:

    错误处理

    scanf 通常用于情况 当程序不能保证 输入是预期的格式。 因此,一个健壮的程序必须检查 scanf 调用是否成功以及 采取适当的行动。如果输入 格式不正确, 错误的数据仍将在 输入流并且必须被读取并且 在新的输入可以被丢弃之前 读。另一种阅读方法 避免这种情况的输入是使用 fgets 然后检查读取的字符串 最后一步可以通过 例如 sscanf。

    http://en.wikipedia.org/wiki/Scanf

    【讨论】:

      【解决方案3】:

      它会将所有与 scanf 不匹配的内容放回缓冲区中。例如:scanf("%i %i",...) 给定输入“12 qwe”将在缓冲区中留下qwe,而不是12。 (spec 表明它不会放回空间,并且快速测试确认。)也就是说,文档相当不清楚,如果不做大量测试就依赖它可能是个坏主意。

      【讨论】:

      • 严格来说,它将留下q作为下一个要读取的字符——它甚至不会看到w,更不用说e了。 scanf() 将返回 1(一次成功转换)。空间不会被放回去;与格式字符串中的空格成功匹配。
      • @Jonathan 但是为了清楚起见,如果格式字符串是"%i%i",空间会被放回,对吗?
      • @Null Set:我认为即使格式字符串不包含空格,那么空格仍然不会被放回,因为scanf()最多使用一个推回字符,而空格是第二个数字的有效开始;被推回的字符是导致转换失败的字符,在此示例中为“q”。我想我应该编写测试来证明这一点——但我觉得太懒了,它只会表明至少有一个实现有(或没有)这种行为,而不是标准规定了这种行为。跨度>
      • @Null Set,测试表明它甚至不会。
      • @Jonathan 再阅读规范后,我相信它不会放回空间。它首先跳过空格,然后寻找匹配的输入,并留下第一个不匹配的字符未读。
      猜你喜欢
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多