关于Stream以及getchar()和fgetc()

时间:2018-06-20 07:58:15

标签: c

#include<stdio.h>

int main(void)
{
    int ch1, ch2;

    ch1 = fgetc(stdin);
    ch2 = getchar();

    fputc(ch1, stdout);
    putchar(ch2);

    return 0;
}

今天我首先了解流。我了解什么是流。但是我无法理解该程序的打印结果。 我按了“ p”并输入键。并打印出该程序

p
p
按任意键继续...

在我读过的书中,它说:“输入密钥是一种ascii代码,因此您可以看到此结果。”但是在首页,它说getchar和fgetc是一个接收字符的函数。但是为什么它不会像这样打印

a b
一种 b

当我按下“ a”,空格键和“ b”时?

我是否可以了解流以及这两个函数(getchar()和fgetc())?

1 个答案:

答案 0 :(得分:0)

根据定义,这三个调用是相同的:

getchar()
getc(stdin)
fgetc(stdin)

所以您发布的程序完全等同于

ch1 = getchar();
ch2 = getchar();

putchar(ch1);
putchar(ch2);

如果您对该程序的工作方式感到困惑,那不是因为getchar / fgetcputchar / putc之间的任何区别。

如果您运行此程序,然后按 p 和Enter键,则我期望ch1最终包含'p',而ch2结束包含换行符。如果运行此程序并键入“ a b”并按Enter键,则我期望ch1最终包含'a',而ch2最终包含空格字符。我不希望该程序能够打印“ a b”,因为它只能读取和打印两个字符。

首先考虑逐个字符阅读总是很棘手的。这是因为在幕后,系统通常会在您键入内容时读取整个文本,然后仅在按Enter键之后才将字符提供给程序。

如果您打印出更多信息,则更容易看到正在发生的事情。例如,这是您的程序的修改:

#include <stdio.h>

int main()
{
    int ch1, ch2;

    ch1 = fgetc(stdin);
    ch2 = getchar();

    fprintf(stdout, "ch1 = '%c'\n", ch1);
    printf("ch2 = '%c'\n", ch2);
}

当我运行该程序并按 p 和Enter键时,我会看到

ch1 = 'p'
ch2 = '
'

如您所见,ch2最终包含换行符。

当我运行该程序并按下 a 和一个空格,并按下 b 和Enter键时,我看到了

ch1 = 'a'
ch2 = ' '

更确切地说,我看到的是

a b
ch1 = 'a'
ch2 = ' '

但是第一行a b就是我的计算机在键入字符时回显这些字符的地方。 (另请参见this web page,尤其是以“最后,不要失望”开头的段落。)

同样,此处fgetc(stdin)getchar之间没有重要区别。我本可以写

ch1 = getchar();
ch2 = getchar();

printf("ch1 = '%c'\n", ch1);
printf("ch2 = '%c'\n", ch2);

它会做同样的事情。

最后,如果您编写一个读取并打印整个 line 个字符的程序,它可能会帮助您更清楚地看到事物。您的第一个程序正好读取两个字符。这是一个不断读取和打印直到看到标记行尾的'\n'字符的程序:

#include <stdio.h>

int main()
{
    int c;

    c = getchar();
    while(c != '\n') {
        printf("c = '%c'\n", c);
        c = getchar();
    }
}

此程序读取一个字符。如果不是换行符\n,则将其打印并读取另一个字符。如果不是换行符,则将其打印并读取另一个字符。它会继续读取和打印,直到看到换行符,然后停止。如果运行此命令并输入“ a b c”,我会看到

c = 'a'
c = ' '
c = 'b'
c = ' '
c = 'c'

(我看不到为换行符打印的行,因为该程序在读取换行符之后并在打印之前立即停止读取。)

再次,我在屏幕上实际看到的是

a b c
c = 'a'
c = ' '
c = 'b'
c = ' '
c = 'c'

但是第一行a b c只是我在输入字符之前,程序有机会读取和打印其中的任何字符。

即使对于这样的简单测试,我也永远不会那样写程序。我将循环写为

while(c != '\n' && c != EOF) {
    ...

因为我还想确保该程序在看到文件结束条件(即getchar返回特殊代码EOF时)停止读取。