Reputation: 13
I am a budding C programmer and I wrote this program to count words for 2nd Edition K&R 1.5.4. Is there something wrong with my if statements? The code appears to increment a variable when it should not, because it doesn't meet the initial test.
#include <stdio.h>
#define IN 1
#define OUT 0
main()
{
int word, state, c;
word = state = OUT;
while((c = getchar()) != EOF)
{
if(c != ' ' || c != '\n' || c != '\t')
{
if(state == OUT)
{
word++;
state = IN;
}
/*else
{
state = IN;
}*/
}
if(c == ' ' || c == '\n' || c == '\t')
{
state = OUT;
}
printf("char: %c %x | state: %d | word: %d\n", c, c, state, word);
}
printf("\n//maniac: %d\n", word);
This results in:
>count_word_my.exe
Hello he he
char: H 48 | state: 1 | word: 1
char: e 65 | state: 1 | word: 1
char: l 6c | state: 1 | word: 1
char: l 6c | state: 1 | word: 1
char: o 6f | state: 1 | word: 1
char: 20 | state: 0 | word: 1
char: 20 | state: 0 | word: 2
char: h 68 | state: 1 | word: 3
char: e 65 | state: 1 | word: 3
char: 20 | state: 0 | word: 3
char: 20 | state: 0 | word: 4
char: 20 | state: 0 | word: 5
char: h 68 | state: 1 | word: 6
char: e 65 | state: 1 | word: 6
char:
a | state: 0 | word: 6
char:
a | state: 0 | word: 7
//maniac: 7
The K&R code which I have modified:
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
printf("char: %c %x | state: %d | word: %d\n", c, c, state, nw);
}
printf("%d %d %d\n", nl, nw, nc);
}
The K&R code results in:
>count_word_test.exe
Hello he he
char: H 48 | state: 1 | word: 1
char: e 65 | state: 1 | word: 1
char: l 6c | state: 1 | word: 1
char: l 6c | state: 1 | word: 1
char: o 6f | state: 1 | word: 1
char: 20 | state: 0 | word: 1
char: 20 | state: 0 | word: 1
char: h 68 | state: 1 | word: 2
char: e 65 | state: 1 | word: 2
char: 20 | state: 0 | word: 2
char: 20 | state: 0 | word: 2
char: 20 | state: 0 | word: 2
char: h 68 | state: 1 | word: 3
char: e 65 | state: 1 | word: 3
char:
a | state: 0 | word: 3
char:
a | state: 0 | word: 3
2 3 16
^C
How can my code be incrementing word/nw while it is processing the second space (0x20) after the 'Hello' when it doesn't meet the test in the first if statement? Even if it did reach the second if statement, I would assume that it would set the 'state' variable to 1(IN). I am missing something crucial here. I greatly appreciate any help that is given. Thank you.
Upvotes: 1
Views: 977
Reputation: 121599
You've already got (at least) one good answer (which I up-voted). But please let me elaborate "just in case":
if(c == ' ' || c == '\n' || c == '\t') ...
You clearly understand this: if "space" or "newline" or "tab", then "whitespace == true".
... but ...
if (c != ' ' || c != '\n' || c != '\t') ...
says "if not a space ... or not a newline .. or not a tab"
In other words, '\n' would evaluate to "whitespace == false" ... because '\n' isn't a blank, and it isn't a tab.
What you really mean is if (c &= ' ' && c != '\n' && c != '\t') ...
... or if (!(c == ' ' || c == '\n' || c == '\t')) ...
In other words, the problem is less "C syntax" than "boolean logic".
Here are two brief tutorials "heavy on theory" ... but which you might enjoy:
Upvotes: 1
Reputation: 137272
well, every char
will evaluate this as true if(c != ' ' || c != '\n' || c != '\t')
as no char is both ' '
, '\n'
and '\t'
.
It should probably be:
if(c != ' ' && c != '\n' && c != '\t')
Upvotes: 7