【问题标题】:Redirecting empty file as input in C将空文件重定向为C中的输入
【发布时间】:2014-09-29 12:34:02
【问题描述】:

我正在阅读有关将输入文件重定向到 C 程序的内容,并在试验代码并使用空文件“inp”时遇到以下问题:

#include <stdio.h>
int main()
{
    int i=10;
    scanf("%d", &i);
    printf("%d", i);
    return 0;
}

输出:

$ ./a.out < inp
10

我无法理解为什么 scanf() 不停止程序读取输入,尽管重定向的文件是空的,但它会跳到 printf() 函数。

另外,当我修改代码以包含未初始化的 i 时:

#include <stdio.h>
int main()
{
    int i;
    scanf("%d", &i);
    printf("%d", i);
    return 0;
}

输出:

$ ./a.out < inp
0

它总是打印 0,但是根据上面的行为,它不应该打印已经存在于未初始化 i 中的垃圾值吗?

【问题讨论】:

  • 总是检查scanf的返回值,它会告诉你转换是如何进行的。至于第二个问题;零垃圾值。
  • 你的主要应该是:int main (int argc, char *argv[])
  • 我使用另一个变量来存储scanf的返回值并打印它,它打印0。这是否意味着没有扫描任何东西,因此它返回NULL?
  • 糟糕,我的意思是它打印出 -1,而不是 0,我意识到这是 EOF 字符,正如 @Yamakuzure 从手册页中解释的那样。
  • 如果您运行./a.out 并直接按 ctrl+d 结束标准输入,您将获得相同的行为。

标签: c io


【解决方案1】:

scanf() 不会在空输入上失败,而是什么都不做。您可能希望按照此处所述检查返回值:

man fscanf

这些函数返回成功匹配和分配的输入项的数量, 这可能比规定的要少,或者在早期匹配的情况下甚至为零 失败。

  The  value  EOF  is  returned if the end of input is reached before either the
  first successful conversion or a matching failure occurs.  EOF is also returned
  if a read error occurs, in which case the error indicator for the stream 
  (see ferror(3)) is set, and errno is set indicate the error.

关于未初始化的i:这是一个带0的隐式初始化。有人称之为特征。

但是,如果您没有使用 scanf(),您的编译器会警告您:

#include <stdio.h>
int main()
{
    int i, j;
    scanf("%d", &i);
    printf("%d / %d\n", i, j);
    return 0;
}

启用所有警告的编译:

$ cc -Wall -Wextra -Wpedantic test.c -o test
test.c: In function 'main':
test.c:6:11: warning: 'j' is used uninitialized in this function [-Wuninitialized]
     printf("%d / %d\n", i, j);
           ^

运行程序

 $ ./test < empty_file
0 / 0

你看,即使 j 打印出一个零。


我添加了另一个测试:

在scanf之后添加:

    int k = i;
    int l = j;

    printf("%d / %d\n", k, l);

结果:

 $ ./test < empty_file 
 1115201808 / 0

所以,当我运行 scanf 时,j 完全未初始化。
结果可以随意重现,k永远是随机的,l永远为零。

【讨论】:

  • 自动变量未初始化。
  • 正在打印值 0,因为 printf() 正在尝试打印整数,因此它首先将其输出值初始化为 0,然后检查传递变量中的字节。检查传递变量中的每个字节是否在 0x30 ... 0x39 范围内。如果字节在所需范围内,则将其合并到结果中。如果字节不在所需的范围内,则 printf 认为它已使用该变量完成。由于内部初始化,打印出来的值还是0。
  • 更新了答案,添加了无法在 cmets 中正确显示的内容。
  • @user3629249 我认为您将 printf 的工作原理颠倒了!使用 %d 格式,它将其对应的参数解释为整数(其字节可以具有任意值)并发出一串字符,其值介于 0x30 和 0x39 之间,偶尔添加 0x2d 以获取乐趣.当然,所有的假设都是 ASCII。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多