【问题标题】:Scanf to accept the number just before EOF (not being separated with a white space)Scanf 接受 EOF 之前的数字(不被空格分隔)
【发布时间】:2013-11-16 15:58:39
【问题描述】:

我需要 scanf 来读取数字,包括在 EOF 之前输入的数字(没有空格或在输入这个数字后输入,只是 EOF - 比如“1 2 3 4EOF” - 4 不被读取)。我的代码如下所示:

for (i = 0; i < 100; i++)
    {
    if ((scanf ("%d", &number) != 1 && !feof(stdin)))
    {
        printf ("Wrong input.\n");
    return (0);
    }

    if (feof(stdin) && count == 0)  
    {
    printf("Empty input.\n");
    return 0;
    }

    if (feof(stdin)) break;

    field[i] = number;
    count++;
    }

需要调整以接受在 EOF 之前未分隔的最后输入的数字的部分在哪里?太感谢了,实在看不下去了。。

【问题讨论】:

    标签: c


    【解决方案1】:

    造成损害的是if (feof(stdin)) break;。如果你没有从scanf() 得到1,你应该只在EOF 上中断。在您的示例中,系统知道它已达到 EOF,但它也成功转换了一个值,并通过从 scanf() 返回 1 告诉您,但您继续忽略成功转换的值,因为也检测到 EOF .

    您可能应该使用:

    #include <stdio.h>
    
    int main(void)
    {
        int field[100];
        int count = 0;
        int n;
    
        for (int i = 0; i < 100; i++)
        {
            int number;
            if ((n = scanf("%d", &number)) != 1)
                break;
            printf("-- %d: %d (%d)\n", i, number, n);
            field[i] = number;
            count++;
        }
    
        if (n == 0)
        {
            printf("Wrong input.\n");
            return 1;
        }
        else if (ferror(stdin))
        {
            printf("I/O error on stdin\n");
            return 1;
        }
        else if (feof(stdin) && count == 0)
        {
            printf("Empty input.\n");
            return 1;
        }
    
        printf("Count: %d\n", count);
        for (int j = 0; j < count; j++)
            printf("%d: %d\n", j, field[j]);
        return 0;
    }
    

    【讨论】:

    • 我认为如果您在输入时输入1 2 3 4EOF (1 2 3 4^D),也会出现同样的问题。 C 的输入缓冲似乎在 4 之后立即“吞噬”了 EOF 作为分隔符。至少在使用 scanf 时。
    • +1 以获得好的答案和if(ferror(stdin))。不过,feof(stdin) &amp;&amp; 不是必需的。
    • @mbratch:我使用echo -n 1 2 3 4 &gt; data 创建的文件进行了测试,该文件在文件末尾没有换行符,还通过在我的终端输入(你必须输入 control-D两次,一次向程序发送“1 2 3 4”字符串,一次向程序发送任何内容,表示EOF)。两次,我都得到了我期望的输出:-- 0: 1 (1) -- 1: 2 (1) -- 2: 3 (1) -- 3: 4 (1) Count: 4 0: 1 1: 2 2: 3 3: 4
    • @chux:现在我把条件变成了if / else if链,我相信你是对的。它们是 3 个单独的 if 语句,有一段时间(可能是 30 秒);我当时没有注意到优化。
    • @JonathanLeffler 好的。我所做的只是从命令行运行它,然后输入1 2 3 4^D。这在某种程度上与末尾没有换行符的文件不同。但是OP并不清楚它是否是一个文件。可能我跑的案子有点反常。
    【解决方案2】:

    在循环结束时检查 !feof(stdin) 。读完最后一个值后它会为真,所以在这种情况下最后一个值不会被存储

    【讨论】:

    【解决方案3】:

    在通过scanf ("%d"... 成功读取最后一个数字后,调用feof() 可能会返回真假,这取决于是否有额外的空格,例如\n 跟在数字后面。因此feof() 不是停止循环的明确测试。更简单的代码是可能的。

    一般来说,避免在同一个解析例程中使用fscanf()feof()。而是使用来自 fscanf() 的返回值来了解 EOF 何时发生。

     while ((retval = fscanf(...)) == expected value) {
       // The happy path
       do_stuff();
     }
     if (retval == EOF) {
       Deal_with_EOF_or_IOerror();
     }
     else {
       Deal_with_unexpected_number_of_parameters_scanned();
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 2013-11-12
      • 2022-11-17
      相关资源
      最近更新 更多