"Keith Thompson" <
[email protected]>
I don't see any real problem with your program. I do have some
stylistic quibbles; I'll get to that later.
I compiled and ran the program myself, and it seems to work correctly.
Examining the code, I don't see any reason why it shouldn't. I
applaud you for showing us a complete compilable program that exhibits
the problem; far too many posters fail to do so, leaving us to guess
what the actual program looks like.
Unfortunately, you've left us to guess what the problem is. You say
that it behaves "except for the newline character". What exactly do
you mean by that? For a given input, what output are you actually
getting, and what output did you expect? (If I had to guess, I'd say
that the program is behaving correctly, and your expectation is
incorrect.)
As for style concerns, your indentation is too narrow and is not
consistent, and it's best to use more blanks (after commas and around
most operators). Here's a modified version of your program, changing
only indentation and spacing:
#include <stdio.h>
int main(int orange, char **apple)
{
int c, n1, n2, n3;
n1 = n2 = n3 = 0;
while ((c=getchar()) != EOF)
{
if (c == '\n')
++n1;
else if (c == '\t')
++n2;
else if (c == ' ')
++n3;
}
printf("%d %d %d\n", n1, n2, n3);
return (0);
}
I didn't add spacing around the "=" in "c=getchar()" so as to
emphasize the grouping.
Your use of "orange" and "apple" as the names of the arguments to main
is perfectly legal. It's also useless and annoying. The universal
convention is to use the names "argc" and "argv". By changing these
to "orange" and "apple", you make your code more difficult to read,
with no benefit whatsoever. For that matter, you don't use the
arguments, so you might as well use "int main(void)".
The parentheses around the argument to return are perfectly legal, but
unnecessary and potentially misleading. A return statement is not a
function call; your code is clearer if you don't make it look like
one. This isn't a big deal though; nobody reading your code is likely
to be confused.
I usually avoid declaring more than one variable on a line. If I'm
going to assign a value to the variable, I'd rather do it as an
initialization rather than as a separate assignment statement; it's
clearer and less error-prone.
If an "if" or other control statement controls only a single
statement, it doesn't have to be surrounded by curly braces. Strictly
speaking, since the "if ... else if ... else if" is a single
statement, the braces associated with the "while" are unnecessary.
Nevertheless, it's a very good idea to include them anyway. In fact,
I would go even farther; I *always* use braces in control statements,
even if they surround just a single simple statement (unless I put the
whole thing on one line, but that's rare). It gives the code a more
consistent look, and it avoids errors when I want to add another
statement. I suspect most C programmers would disagree with me on
this point. (It's a habit I picked up from Perl, which requires the
braces.)
(If I felt like being overly terse, I might write:
if (c == '\n') ++n1;
else if (c == '\t') ++n2;
else if (c == ' ') ++n3;
but that makes adding more statements even more difficult.)
The names n1, n2, and n3 are extremely unclear. It's not that
important for a tiny program like this, but for larger programs it
becomse extremely important to pick meaningful variable names.
Here's another version of your program, incorporating these points
(and using the brace style that I happen to prefer):
#include <stdio.h>
int main(void)
{
int c;
int newlines = 0;
int tabs = 0;
int blanks = 0;
while ((c=getchar()) != EOF) {
if (c == '\n') {
newlines ++;
}
else if (c == '\t') {
tabs ++;
}
else if (c == ' ') {
blanks ++;
}
}
printf("%d %d %d\n", newlines, tabs, blanks);
return 0;
}
Finally, I'd probably use a switch statement rather than a chain of if
statements.