I'm trying to compile this piece of code from the book "The C Programming Language" (K & R). It is a bare-bones version of the UNIX program wc
:
#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("%d %d %d\n", nl, nw, nc);
}
And I'm getting the following error:
$ gcc wc.c
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token
The 2nd edition of this book is from 1988 and I'm pretty new to C. Maybe it has to do with the compiler version or maybe I'm just talking nonsense.
I've seen in modern C code a different use of the main
function:
int main()
{
/* code */
return 0;
}
Is this a new standard or can I still use a type-less main?
As you see there was a problem in macros.
GCC has option for stopping after pre-processing. (-E) This option is useful to see the result of pre-processing. In fact the technique is an important one if you are working with large code base in c/c++. Typically makefiles will have a target to stop after pre-processing.
For quick reference : The SO question covers the options -- How do I see a C/C++ source file after preprocessing in Visual Studio?. It starts with vc++, but also has gcc options mentioned down below.
Your problem is with your preprocessor definitions of
IN
andOUT
:Notice how you have a trailing semicolon in each of these. When the preprocessor expands them, your code will look roughly like:
That second semicolon causes the
else
to have no previousif
as a match, because you are not using braces. So, remove the semicolons from the preprocessor definitions ofIN
andOUT
.The lesson learned here is that preprocessor statements do not have to end with a semicolon.
Also, you should always use braces!
There is no hanging-
else
ambiguity in the above code.A simple way is to use brackets like {} for each
if
andelse
: