2

我的问题只是“为什么我在第 10 行和第 11 行的代码不能正常运行?” 我的代码的预期目的是完全按照原始 K&R 代码的意图执行,但不计算 nc 任何时候 (getchar() == '\n') 请您赐教?

稍作修改的 K&R 代码:

/** K&R - 1.5.2 Character Counting **/
#include <stdio.h>

/* count characters in input; 1st version */
main(){
  long nc;

  nc = 0;
  while (getchar() != EOF){
    if (getchar() != '\n'){
      ++nc;
    }
  }
  printf("%ld\n", nc);
}

我使用 64 位 Windows 7、CodeBlocks10.05、GNU GCC 编译器。

我目前的进展和理解:

在示例运行中,我输入单词two并按 Enter,这等于 4 个输入,然后按 ctrl+Z 输入一个^Z或 EOF 字符。然后程序打印1. 我期待它打印3。我想唯一合乎逻辑的解释是它的行为与我的意图完全相反(它只计算换行符?)。事实证明,如果我输入单词two并按回车键,让我们说 4 次,它会打印4. 它似乎在计算nc输入的每个换行符,但是如果我单独按 Enter(在这种情况下为 4 次)然后按 EOF,它总是会打印0. 经过进一步的实验,在某些人看来,看不见的 4 可能是这个程序的一个神奇数字。如果我启动它并准确地按回车键(一个可被 4 整除的数字)然后 EOF 它会打印0. 但是,如果我按其他次数输入,EOF 什么都不做,我必须输入^Z两行,一个接一个,才能正确结束 while 循环,然后打印1。这让我大吃一惊!

4

3 回答 3

6

问题是您需要从getchar()- in an int- 中保存值,因为每次增加计数时都会读取两个字符。其中之一是在 EOF 测试中;第二个是在换行测试中。

int c;

while ((c = getchar()) != EOF)
{
    if (c != '\n')
        ++nc;
}

您需要将结果存储getchar()在 anint而不是 a 的char原因是它可以返回每个可能的char值以及一个不同的值 EOF。如果您不使用int(直接存储到 achar中),将会发生以下两种情况之一:

  1. 如果char是有符号类型,则合法字符(通常是 y-元音变音、ÿ、带分音符号的拉丁小写字母 Y、U+00FF — 至少在源自拉丁语 1 或 ISO 8859-1 的代码集中)将被解释为等效于 EOF,并且您的程序将提前终止。
  2. 如果char是无符号类型,则任何字符都不会等同于 EOF,因此程序永远不会停止循环。

这两种情况都不是可取的。将返回值存储getchar()在 an 中int可以防止这两个问题;这是“唯一”(或至少是最简单的)正确方法。

于 2012-08-24T21:32:10.530 回答
5

简而言之,您调用getchar()了两次,因此每次迭代都会消耗两个字符。

你应该明白调用getchar()从输入流中读取一个字符。如果要测试换行符,则应将该字符存储在变量中,然后测试该变量。

于 2012-08-24T21:31:36.537 回答
3
int c;

[...]

while ((c = getchar()) != EOF) {
    if (c != '\n') {
      ++nc;
    }
}

每次您调用时,getchar()您都在消耗stdin.

于 2012-08-24T21:30:56.520 回答