使用getchar()和putchar()复制文件

时间:2018-09-10 23:53:30

标签: c eof getchar putchar

我知道这已经在前面讨论过了,但是我想确保我正确理解了该程序中发生的事情以及原因。在丹尼斯·里奇(Dennis Ritchie)的教科书 C编程语言的第20页上,我们看到了以下程序:

#include <stdio.h>

int main()
{

int c;

c = getchar();

while(c != EOF){
    putchar(c);
    c = getchar();
}

return 0;

}

执行后,程序将读取键入的每个字符,并在用户按下Enter键后以相同顺序将其打印出来。除非用户手动退出控制台,否则将无限期重复此过程。事件的顺序如下:

  1. getchar()函数读取键入的第一个字符,并将其值分配给c

  2. 由于c是整数类型,因此getchar()传递给c的字符值被提升为其对应的ASCII整数值。

  3. 现在c已被初始化为某个整数值,while循环可以测试该值是否等于文件尾字符。因为EOF字符的宏值为-1,并且因为所有可能键入的字符都不具有负十进制ASCII值,所以while循环的条件始终为true。

  4. 一旦程序验证c != EOF为真,就会调用putchar()函数,该函数将输出c中包含的字符值。

  5. getchar()被再次调用,因此它读取下一个输入字符,并将其值传递回while循环的开始。如果用户在执行之前仅键入一个字符,则程序将读取<return>值作为下一个字符并打印新行,并等待键入下一个输入。

其中任何一个远程正确吗?

2 个答案:

答案 0 :(得分:1)

是的,您基本上已经掌握了。但这甚至更简单:getcharputchar已经分别返回并接受int类型。因此,没有类型升级发生。您只需要输入字符并循环发送它们,直到看到EOF

您关于为什么应该使用int而不是某些char形式的直觉很可能是正确的:int类型允许哨兵EOF值超出该值任何可能的字符值的范围。

(K&R stdio函数目前非常很旧,它们不了解Unicode等,并且某些基本的设计原理即使不是很模糊,也不会相关。如今,没有太多实用的代码可以使用这些功能。这本书在很多方面都很出色,但是代码示例却是过时的。)

(此外,您的问题标题是“复制文件”,您仍然可以 这样操作,但还有更多规范的方法)

答案 1 :(得分:0)

好吧,这在思想上是正确的,但在细节上却不正确,那就是魔鬼所在的地方。

  • getchar()函数从标准输入中读取第一个字符,并将其作为提升为unsigned char的{​​{1}}返回(如果没有字符则返回特殊的int值)已被读取)

  • 返回值分配给EOF,其类型为c(应为if it were a char strange things could happen

  • 现在已经为int分配了一些整数值,c循环可以测试该值是否等于while宏的值。

  • 由于EOF宏具有实现指定的负值,并且由于字符被转换为EOF并被提升为unsigned char,它们都没有负值(至少在新手遇到的任何系统中都没有),int循环的条件将一直为真,直到文件结束条件发生读取标准输入时发生错误。

  • 一旦程序验证while为真,就会调用c != EOF函数,该函数将输出putchar()中包含的字符值。

  • c被再次调用,因此它将读取下一个输入字符,并将其值传递回while循环的开始。

  • 标准输入(如果连接到终端设备)通常是行缓冲的,这意味着该程序在用户完成该行并按<之前不会接收该行上的任何字符。 kbd>输入键。

我们使用的是执行字符集,而不是ASCII,如今,它们可能通常是UTF-8编码的Unicode字符的单个字节。 getchar()在二进制中也是负数,我们不需要考虑“其十进制值”。 EOFchar类型也都是数字,字符常量的类型也是unsigned char-例如,在执行字符集与ASCII 兼容的系统上,写int与写32是一样的事情,尽管对于那些不记得ASCII码的人来说显然更清楚。

最后,C对初始化的含义非常严格。是在声明初始值时将其设置为变量。

' '

具有初始化。

int c = getchar();

int c; c = getchar(); 未初始化,然后分配了一个值。知道这些区别后,当编译器错误消息引用 initialization assignment 时,便更易于理解。