【问题标题】:"File Copying" section in K&RK&R 中的“文件复制”部分
【发布时间】:2013-06-29 16:51:58
【问题描述】:

我是编程新手,我似乎无法理解为什么我的代码中会出现以下情况,即:

#include <stdio.h>

/*copy input to output; 1st version */

main()
{
    int c;

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

所以在做了一些阅读之后,我收集了以下内容:

  1. 在我按 Enter 之前什么都不会执行,因为 getchar() 是一个保持函数。
  2. 在按 Enter 之前,我的所有击键都存储在缓冲区中
  3. getchar() 被调用时,它只是查看缓冲区中的第一个值,成为该值,然后从缓冲区中删除该值。

我的问题是,当我删除第一个 c = getchar() 时,生成的代码与原始代码具有完全相同的功能,尽管在我输入任何内容之前,屏幕上会立即出现一个笑脸符号。为什么会这样?是不是因为putchar(c) 没有保留代码,而是尝试显示尚未定义的c,因此它输出了一些随机符号?如果有帮助,我正在使用 Code::Blocks。

【问题讨论】:

  • 如果你删除第一个getchar,程序有未定义的行为。

标签: c getchar kernighan-and-ritchie


【解决方案1】:

您列出的功能只会将您输入的每个字符回显给您。确实,I/O 是“缓冲的”。执行此缓冲的是操作系统的键盘输入驱动程序。当它缓冲您按下的键时,它会将每个键回显给您。当您按下换行符时,驱动程序会将缓冲的字符传递给您的程序,getchar 然后会看到它们。

正如所写,该功能应该可以正常工作:

c = getchar();   // get (buffer) the first char

while (c != EOF) {  // while the user has not typed ^D (EOF)
    putchar(c);     // put the character retrieved
    c = getchar();  // get the next character
}

由于键盘驱动程序缓冲,它只会在您每次按换行符或使用 ^D (EOF) 退出时回显。

笑脸来自@YuHao 所描述的内容:您可能错过了您运行的第一个getchar,所以putchar 是在回响垃圾。可能是 0,在您的屏幕上看起来像一个笑脸。

【讨论】:

  • 是的,仍然不太清楚为什么不在循环内交换c = getchar();putchar(c); 并丢弃第一个c 声明?刚刚检查了一下,似乎垃圾从输出中消失了。我不明白在这种情况下什么是未定义的?
  • @user3081519 “第一个 c 声明”是指“第一个 c 赋值”吗?你可以稍微重构一下这个循环,但是如果你去掉第一个赋值,那么第一个while 检查c != EOF 变得毫无意义,当c 是@987654331 时你就有机会尝试putchar(c) @。您必须问自己:例如,如果c 的第一次阅读已经是 EOF 怎么办?循环可以重写为for 循环:for ( c = getchar(); c != EOF; c = getchar() ) putchar(c);
  • 哦!我懂了。因此,对于我的版本,它仍然会在 EOF 的情况下隐式运行一次,这可能是错误的定义。这很有启发性,谢谢!
【解决方案2】:

如果省略第一个getchar(),代码将如下所示:

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

这里,c 是未初始化的,所以第一次调用putchar(c) 会输出一个垃圾值,这就是你得到笑脸的地方。

【讨论】:

    【解决方案3】:

    “我是编程新手”

    不建议您使用 C 来学习编程(您遇到的困难是因为 C 语言)。例如,我的第一堂计算机科学课是帕斯卡。其他大学可能会使用 scheme 或 lisp,甚至结构化自然语言来教授编程。麻省理工学院的在线课程是用python给出的。

    C 不是您在编程的最初几个月想要使用的语言。您的情况的具体原因是由于语言允许您使用未初始化值的值。

    当您声明整数变量“c”时,它会在程序堆栈上获得一个隐式保留空间,但没有任何有意义的值:它是“垃圾”,该值是当时内存中已经存在的任何值。 C 语言要求程序员在使用变量之前隐含地知道他需要分配一些值。删除第一个 getchar 会导致在 while 条件 (c != EOF) 和 putchar(c) 中赋值之前使用,这两者都在 c 具有任何有意义的值之前。

    考虑用python重写相同的代码:

    import sys
    
    c = sys.stdin.read(1)
    while c != '':
        c = sys.stdin.read(1)
        sys.stdout.write(c)
    

    删除初始读取,您会收到以下错误:

    hdante@aielwaste:/tmp$ python3 1.py 
    Traceback (most recent call last):
      File "1.py", line 3, in <module>
        while c != '':
    NameError: name 'c' is not defined
    

    这是一个 NameError:您使用未分配的值导致语言错误。

    如需了解更多信息,请尝试在线课程,例如:

    http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/video-lectures/

    关于未初始化的值:

    http://en.wikipedia.org/wiki/Uninitialized_variable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-25
      • 1970-01-01
      • 2016-06-15
      • 1970-01-01
      • 2019-09-15
      • 2013-09-16
      • 2020-04-05
      • 1970-01-01
      相关资源
      最近更新 更多