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

问题描述 投票:0回答:2

我知道这已经讨论过了,但我想确保我理解正确,这个程序中发生了什么,以及为什么。在Dennis Ritchie的教科书The C Programming Language的第20页,我们看到了这个程序:

#include <stdio.h>

int main()
{

int c;

c = getchar();

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

return 0;

}

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

  1. getchar()函数读取键入的第一个字符并将其值分配给c
  2. 因为c是一个整数类型,所以getchar()传递给c的字符值被提升为它对应的ASCII整数值。
  3. 现在c已经初始化为某个整数值,while循环可以测试该值是否等于End-Of-File字符。因为EOF字符具有-1的宏值,并且因为没有可能键入的字符具有负的十进制ASCII值,所以while循环的条件将始终为真。
  4. 一旦程序验证c != EOF为真,则调用putchar()函数,该函数输出c中包含的字符值。
  5. 再次调用getchar(),因此它读取下一个输入字符并将其值传递回while循环的开头。如果用户在执行前只键入一个字符,则程序将<return>值作为下一个字符读取并打印一个新行并等待下一个输入键入。

这是否远程正确?

c eof getchar putchar
2个回答
1
投票

是的,你基本上得到了它。但它更简单:getcharputchar已分别返回并接受int类型。所以没有类型推广发生。你只是接受角色并将它们发送出去,直到你看到EOF

你对为什么那些应该是int而不是某些char形式的直觉可能是正确的:int类型允许一个超出任何可能的字符值的值范围的sentinel EOF值。

(此时K&R stdio功能非常陈旧,他们不了解Unicode等等,并且一些基本的设计原理如果不是模糊的,只是不相关。现在没有很多实用的代码会使用这些功能那本书很适合很多东西,但代码示例相当陈旧。)

(另外,fwiw,你的问题标题是指“复制文件”,你仍然可以这样做,但有更多的规范方法)


0
投票

嗯,这是正确的想法,但不是详细的,这就是魔鬼的所在。

  • getchar()函数从标准输入读取第一个字符并将其作为unsigned char提升为int(如果没有读取字符,则返回特殊的EOF值)
  • 返回值被分配到c,其类型为int(因为它应该为if it were a char strange things could happen
  • 现在已经为c分配了一些整数值,while循环可以测试该值是否等于EOF宏的值。
  • 因为EOF宏具有实现指定的负值,并且因为字符被转换为unsigned char并被提升为int,所以它们都没有负值(至少在你遇到的任何系统中都没有),条件while循环始终为真,直到文件结束条件发生或读取标准输入时发生错误。
  • 一旦程序验证c != EOF为真,则调用putchar()函数,该函数输出c中包含的字符值。
  • 再次调用getchar(),因此它读取下一个输入字符并将其值传递回while循环的开头。
  • 标准输入(如果它连接到终端设备)通常是行缓冲的,这意味着在用户完成该行并按Enter键之前,程序不会接收该行上的任何字符。

我们说的是执行字符集,而不是ASCII,现在可能通常是UTF-8编码的Unicode字符的单个字节。 EOF也是二进制的负数,我们不需要考虑“它的十进制值”。 charunsigned char类型也是数字,字符常量是int类型 - 即在执行字符集与ASCII兼容的系统上,写' '将与写32相同,但当然更清楚不记得ASCII码。

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

int c = getchar();

有一个初始化。

int c;
c = getchar();

c未初始化,然后分配一个值。了解这种区别使得在引用初始化或赋值时更容易理解编译器错误消息。

© www.soinside.com 2019 - 2024. All rights reserved.