我有一个 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/