当通过管道

时间:2015-08-06 12:50:38

标签: c loops pipe stdin getchar

我面前无法解释的事情。没有比给出一个例子更好的解释方式了:

#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"会向{strong> stdin 发送A,然后触发EOF 事件(我不确定EOF究竟是什么)一次,因此我的循环最多会迭代两次,然后等待中的新输入标准输入

但不,它迭代了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 然后返回时,我发送了A然后\n(0x0a)到stdin,所以二进制文件只是在它们的六进制表示中显示这些,41a

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

非常感谢您的阅读!

3 个答案:

答案 0 :(得分:5)

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

请注意,这与stdin附加到输入设备时的行为不同。在这种情况下,如果输入缓冲区为空,getchar将暂停,等待进一步输入。在{1}}从输入设备发送getcharEOF从Linux中的键盘发送EOF)之前,CTRL-D将不会返回EOF

答案 1 :(得分:5)

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);
}

答案 2 :(得分:2)

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

系统功能&#39; getchar()&#39;返回一个int,而不是一个char。

所以要进行任何比较,&#39; c&#39;必须是一个int,而不是一个char。

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

建议使用以下代码模型。

#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