我之前有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]$
......你可以看到它不是。有时候计数是正确的,有时它会丢失一些,有时它会有太多。知道为什么吗?
答案 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)