Reputation: 15
Just a quick question; I've been working through K&R and the code for the digit/whitespace/other counter works fine. However, whilst trying to get my head round the functionality of else
I've encountered something which doesn't work as expected.
The code from the book is as follows:
#include <stdio.h>
/* count digits, white space, others */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d", ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
If I then modify the while
loop so it reads:
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
It should still have the same functionality as the original code except for the fact it won't count 'other' characters. However what I actually get is in fact just the 'digit' part working, with 'nwhite' returning zero no matter what the input. I feel the disparity is perhaps due to a fundamental misunderstanding of how if
statements function.
Upvotes: 1
Views: 172
Reputation: 1757
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
Is equivalent to
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
}
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
Only the first statement that follows a looping or branch construct "belongs" to that construct. That is why the original if-else if-else chain works without braces. Each statement chains to the previous with the first if/else statement belonging to the while loop and the second if/else belonging to the first if/else. It is idiomatic to express the logic this way to avoid unnecessary indenting.
It may help to visualize the code with braces
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9') {
++ndigit[c-'0'];
}
else {
if (c == ' ' || c == '\n' || c == '\t') {
++nwhite;
}
else {
++nother;
}
}
}
Upvotes: 2
Reputation: 145829
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
The second if
statement is no longer in the loop. Use {
and }
to enclose the loop statements.
Upvotes: 10