C 程序不收集计数,对吗?

标签 c

我有一个 general question早些时候得到了很好的回应,但现在(即使是同一个练习)我有一个更具体的问题,我认为它应该有自己的问答页面。

这是我的程序(未完成,但编译和运行正常):

#include <stdio.h>

#define IN  1 // inside a word
#define OUT 0 // outside a word

// #define MAXWORDLENGTH 10

// print a histogram of the length of words in input. horizontal bar version

int main(void)
{
  int c, state, length;
  int one, two, three, more;

  length = 0;
  one = two = three = more = 0;

  state = OUT;
  while ((c = getchar()) != EOF) {
    if (c == ' ' || c == '\t' || c == '\n')
      state = OUT;
    else state = IN;
    if (state == IN) {
      ++length;
      while ((c = getchar()) != EOF && state != OUT) { // get next character in word
        if (c != ' ' && c != '\t' && c != '\n') // if character is not whitespace...
          ++length; // ...add one to length
        else state = OUT; // otherwise word is over
      }
    if (length != 0) {
      if (length == 1)
        ++one;
      if (length == 2)
        ++two;
      if (length == 3)
        ++three;
      if (length > 3)
        ++more;
    }
    length = 0;
    }
  }

  printf("----------------------------------------------------------------\n");
  // print histogram
  printf("ONE: %d\tTWO: %d\tTHREE: %d\tMORE: %d\n", one, two, three, more); // just making sure program collects data right, which it isn't...
  printf("----------------------------------------------------------------\n");

  return 0;
}

这应该是不言自明的评论。我目前使用整数(将切换到数组)并且只打印计数以确保它正确收集数据。

这是正在编译、运行和测试的实际程序...

[matt@localhost 1.6]$ cc -Wall e-1-13.c
[matt@localhost 1.6]$ ./a.out 
1 22 333 4444 55555
----------------------------------------------------------------
ONE: 2  TWO: 1  THREE: 1    MORE: 1
----------------------------------------------------------------
[matt@localhost 1.6]$ ./a.out 
1 1 1 1 1 1
----------------------------------------------------------------
ONE: 3  TWO: 0  THREE: 0    MORE: 0
----------------------------------------------------------------
[matt@localhost 1.6]$ ./a.out 
22 22 22 22 22
----------------------------------------------------------------
ONE: 4  TWO: 1  THREE: 0    MORE: 0
----------------------------------------------------------------
[matt@localhost 1.6]$ 

... 如您所见,事实并非如此。有时计数是正确的,有时会丢失一些,有时会太多。知道为什么吗?

最佳答案

我认为当您在 while 循环中点击 else state = OUT; 时,您需要立即跳出循环。您正在消耗一个额外的字符。

尝试将 else state = OUT; 更改为

else {
    state = OUT;
    break;
}

编辑为了详细说明为什么会这样,让我们​​评估一下这段代码:

  // 1. while loop conditional
  while ((c = getchar()) != EOF && state != OUT) { // get next character in word
    // 2. conditional succeeded
    if (c != ' ' && c != '\t' && c != '\n') // if character is not whitespace...
      ++length; // ...add one to length
    else state = OUT; // otherwise word is over
  }

while 循环条件 (1) 是通过调用 getchar 然后评估 state 来确定的。如果此条件成功,则代码进入成功 block (2)。问题是您在 else 子句中分配了 state = OUT,但要求再次计算条件,这意味着您将调用 getchar,然后看到 state == OUT。实际上,您跳过了对您消耗的字符的处理。

短路处理评估条件的顺序。举个简单的例子:

int foo = 0;
int bar == 1;

if (foo && bar) { ... }

由于 foo 为假 (0),因此无需评估 bar,因为无论其余条件如何,假值都会导致 && 评估为假。同样,如果我们写:

if (bar || foo) {...}

那么就不需要计算 foo 因为 bar 是真的,一个真值会导致 ||无论其余条件如何,都评估为真。跳过评估其余条件的能力称为短路。

在您的例子中,如果您将 while 循环条件的顺序交换为

while (state != OUT && (c = getchar()) != EOF) {

然后 state != OUT 将评估为 false,这将阻止由于短路而评估 c = getchar()Here's a tutorial如果你想了解更多,就可以了。希望对您有所帮助。

关于C 程序不收集计数,对吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3992157/

相关文章:

创建一个字符串数组来保存长字符串中的分割标记?

C 中的常量数组类型,标准中的缺陷?

c - 段错误,不知道为什么

c - 如何将字符串转换为int并将结果放入数组

c - Getopt 不抓取并将我的输入存储在 C 中

c++ - 如何知道自己进程打开的各种文件是什么

c - 如何让 C 程序等待(在 Linux 上)?

c - 调用 C 中的函数后值发生变化

c - 使用 getchar() 计算空格、制表符和换行符

c - 多项式指针程序错误,扫描仪跳过输入