C程序没有收集合适的权利吗?

时间:2010-10-21 21:33:26

标签: c

我之前有general question并得到了很好的回复,但现在(尽管这是相同的练习)我有一个更具体的问题,并认为它应该是它自己的Q& A页面。

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

#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]$ 

......你可以看到它不是。有时候计数是正确的,有时它会丢失一些,有时它会有太多。知道为什么吗?

2 个答案:

答案 0 :(得分:4)

我认为你需要在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然后评估状态来确定的。如果该条件成功,则代码进入成功块(2)。问题是你在else子句中分配state = OUT,但是需要再次计算条件,这意味着你将调用getchar,然后看到state == OUT。实际上,您跳过处理您使用的角色。

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

int foo = 0;
int bar == 1;

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

由于foo为假(0),因此无需评估bar,因为错误的值会导致&amp;&amp;无论其他条件如何,评估为假。同样,如果我们写道:

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

然后没有必要评估foo,因为bar为真,而真值导致||无论其他条件如何,评估为真。跳过评估其余条件的能力称为短路。

在您的情况下,如果您已将while循环条件的顺序交换为

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

然后状态!= OUT将评估为false,这将阻止由于短路而对c = getchar()进行评估。 Here's a tutorial如果您想了解更多,请点击它。希望有所帮助。

答案 1 :(得分:3)

在while循环中更改条件的顺序:

没有

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

是:

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