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?
The main problem with this code is that it is not the code from K&R. It includes semicolons after the macros definitions, which were not present in the book, which as others have pointed out changes the meaning.
Except when making a change in an attempt to understand the code, you should leave it alone until you do understand it. You can only safely modify code you understand.
This was probably just a typo on your part, but it does illustrate the need for understanding and attention to details when programming.
The definitions of IN and OUT should look like this:
The semicolons were causing the problem! The explanation is simple: both IN and OUT are preprocessor directives, essentially the compiler will replace all occurrences of IN with a 1 and all occurrences of OUT with a 0 in the source code.
Since the original code had a semicolon after the 1 and the 0, when IN and OUT got replaced in the code, the extra semicolon after the number produced invalid code, for instance this line:
Ended up looking like this:
But what you wanted was this:
Solution: remove the semicolon after the numbers in the original definition.
There should not be any semicolons after the macros,
and it should probably be
Not exactly a problem, but the declaration of
main()
is also dated, it should be like something this.The compiler will assume an int return value for a function w/o one, and I'm sure the compiler/linker will work around the lack of declaration for argc/argv and the lack of return value, but they should be there.
As other answers pointed out, the problem is in
#define
and semicolons. To minimize these problems I always prefer defining number constants as aconst int
:This way you get rid of many problems and possible problems. It is limited by just two things:
Your compiler has to support
const
- which in 1988 wasn't generally true, but now it's supported by all commonly used compilers. (AFAIK theconst
is "borrowed" from C++.)You can't use these constants in some special places where you would need a string-like constant. But I think your program isn't that case.
Try adding explicit braces around code blocks. The K&R style can be ambiguous.
Look at line 18. The compiler is telling you where the issue is.