【问题标题】:getchar() loops over EOF when STDIN provided through a pipe当通过管道提供 STDIN 时,getchar() 在 EOF 上循环
【发布时间】:2015-08-06 12:50:38
【问题描述】:

我遇到了一些我无法解释的事情。没有比举个例子更好的解释方式了:

#include <stdio.h>

int main ()
{
    char c;
    while (1) {
        c = getchar();
        printf("%x\n", c);
    }
   return(0);
}

如果我执行这个命令,它只是以这种方式无限迭代:

$ echo -n "A" | ./binary
41
ffffffff
ffffffff
ffffffff
ffffffff
...

根据我所知道和读到的 (Confusion about how a getchar() loop works internally),我认为 echo -n "A" 会将 A 发送到 stdin,然后触发 EOF 事件 (我不确定 EOF 到底是什么)一次,因此我的循环最多会迭代两次,然后会休眠等待 stdin 中的新输入。 p>

但是不,它遍历 EOF,我不明白为什么。

我运行这个命令试图理解:

$ echo -n "A" | strace ./binary
read(0, "A", 4096)                      = 1
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7ff6000
write(1, "41\n", 341
)                     = 3
read(0, "", 4096)                       = 0
write(1, "ffffffff\n", 9ffffffff
)               = 9
read(0, "", 4096)                       = 0
write(1, "ffffffff\n", 9ffffffff
)               = 9
...

所以看起来 read() 没有读取任何内容,并返回 0,getchar() 将其解释为 EOF。但是为什么,哦,为什么它会这样迭代,而当我以正常方式执行这个二进制文件时,它会按预期工作:

$ ./binary
A
41
a
B
42
a
^C
$

(上面的输出可能有点混乱,但是当我输入 A 然后 Return 时,我将 A 然后 \n (0x0a) 发送到标准输入,所以二进制文件只是以它们的十六进制表示形式显示这些,41a)

有人可以向我解释一下吗?我错过了什么?

非常感谢阅读!

【问题讨论】:

    标签: c loops pipe stdin getchar


    【解决方案1】:

    一旦遇到EOFgetchar会立即返回,返回值EOF。流的流指针不会前进,它将停留在 EOF 标记上。对getchar 的后续调用也将立即返回,因为流仍在EOF 标记处。

    请注意,这与stdin 连接到输入设备时的行为不同。在这种情况下,getchar 将暂停,如果输入缓冲区为空,则等待进一步的输入。 getchar 不会返回 EOF,直到从输入设备发送 EOFCTRL-D 从 Linux 中的键盘发送 EOF)。

    【讨论】:

    • 好的,这很有帮助!感谢您的回答,已接受:)
    • 如果char 是无符号的,char c 永远不会等于EOF。如果 char 是为某些非 ASCII 字符签名的(那些将产生相应的负值 EOF 的字符),它将等于 EOF
    【解决方案2】:

    getchar() 返回一个 int,而不是一个 char。较大的返回值允许您查找返回值 EOF,即 -1。这是错误和文件结尾的返回值。将 c 的类型更改为 int 不会改变 printf 的行为。

    #include <stdio.h>
    
    int main ()
    {
        int c;
        while (1) {
            c = getchar();
            if ( c == EOF) {
                break;
            }
            printf("%x\n", c);
        }
       return(0);
    }
    

    【讨论】:

    • 感谢您的精确
    【解决方案3】:

    首先,EOF 为 -1,即 0xFFFFFFFF。

    系统函数“getchar()”返回一个 int,而不是一个 char。

    所以要进行任何比较,'c' 必须是 int,而不是 char。

    现在,要退出 while 循环,必须与某个条件进行比较,该条件必须为真才能继续循环。

    建议使用以下代码模型。

    #include <stdio.h>
    
    int main ( void )  //<< for main, better to use 'void' rather than empty braces
    {
        int c; //<< because getchar() returns an int, not a char
    
        // following loop has EOF as exit condition
        // note in C, && is lower presidence than = and != so is evaluated last
        // note in C, && is evaluated from left to right
        // note to help the compiler to catch errors,
        //      always place the literal on the left of a comparison
        while (c = getchar() && EOF != c) 
        {
            printf("%x\n", c);
        }
       return(0);
    } // end function: main
    

    【讨论】:

      猜你喜欢
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多