I want to count the number of characters, words and newlines in a program. My code look like this:
#include <stdio.h>
int main() {
int nw, nl, nc, c;
nw = nc = nl = 0;
for (c = getchar(); c != EOF; c = getchar()) {
if (c == '\n')
nl;
if (c != '\n' || c != '\t' || c != ' ') {
for (c = getchar(); c == '\n' || c == '\t' || c == ' '; c = getchar()) {
nc;
}
nw;
nc;
if (c == '\n')
nl;
} else
nc;
}
printf("%d %d %d", nc, nw, nl);
return 0;
}
Input:
smith book
c c
bug
Output: 9 0 13
What's wrong with this program?
I am a beginner. Forgive if I made any mistake.
CodePudding user response:
There are multiple problems in your code:
the test
c != '\n' || c != '\t' || c != ' '
is always true. You mean to test ifc
is either' '
,'\t'
or'\n'
, ie: a word separator, but the expression should bec == '\n' || c == '\t' || c == ' '
or more generallyisspace(c)
.you count the number of newline characters
'\n'
but you should add 1 if the last line does not end with a newline.similarly, you count a word for each sequence of white space, but you should ignore leading white space.
A simpler way to handle these corner cases is to keep the last character and test for transitions:
#include <ctype.h>
#include <stdio.h>
int main() {
int nw, nl, nc, c, lastc;
nw = nc = nl = 0;
for (lastc = '\n'; (c = getchar()) != EOF; lastc = c) {
nc ;
if (c == '\n')
nl ;
if (isspace(lastc) && !isspace(c))
nw ;
}
if (lastc != '\n')
nl ;
printf("%d %d %d\n", nc, nw, nl);
return 0;
}
Since boolean expressions evaluate to 0
or 1
, this code can be simplified as:
#include <ctype.h>
#include <stdio.h>
int main() {
int nw, nl, nc, c, lastc;
nw = nc = nl = 0;
for (lastc = '\n'; (c = getchar()) != EOF; lastc = c) {
nc ;
nl = (c == '\n');
nw = (isspace(lastc) && !isspace(c));
}
nl = (lastc != '\n');
printf("%d %d %d\n", nc, nw, nl);
return 0;
}
CodePudding user response:
As @erik258 mentioned, enable compiler warnings & read them all.
You should add -Wall -Wextra
to your compiling flags.
c==('\n'||'\t'||' ');
(you seem to have edited this from your original post) is in essence doing a boolean comparison. i.e. c
is true
if \n
, \t
or
is true
, which all three of those technically are in this case.
What you end up with here can be represented as c==(true||true||true)
or c==true
or more accurately c==1
no matter what the value of c
actually is, which isn't what you seem to be after.
Just thought that you might appreciate that clarification.
Another thing you might like to know... The declaration of your loop:
for(c=getchar();c!=EOF;c=getchar())
Can be declared more simply as while((c = getchar()) != EOF)