K&R Exercise 1-6 & 1-7: working with EOF
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
I'm working through K&R at the moment and I've found my first exercise that seems to be a good use for my first CodeReview post.
Exercise 1-6 - Verify that the expression getchar() != EOF
is 0
or 1
.
Exercise 1-7 - Write a program to print the value of EOF
.
I've completed both of these together in the same file.
I think I've understood the question here, but let me know if I haven't. I wanted to post here before looking up any sort of "official" answer so that I could learn some stuff instead of just "going to the back of the book".
#include <stdio.h>
void main()
int c;
c = getchar();
while ((c = getchar()) != EOF == (0
Compiled with:
gcc putchar.c -o putchar
Sending EOF using:
<ctrl-d>
Runs through fine, and when I ctrl-d I get a -1
return code.
c io
 |Â
show 1 more comment
up vote
5
down vote
favorite
I'm working through K&R at the moment and I've found my first exercise that seems to be a good use for my first CodeReview post.
Exercise 1-6 - Verify that the expression getchar() != EOF
is 0
or 1
.
Exercise 1-7 - Write a program to print the value of EOF
.
I've completed both of these together in the same file.
I think I've understood the question here, but let me know if I haven't. I wanted to post here before looking up any sort of "official" answer so that I could learn some stuff instead of just "going to the back of the book".
#include <stdio.h>
void main()
int c;
c = getchar();
while ((c = getchar()) != EOF == (0
Compiled with:
gcc putchar.c -o putchar
Sending EOF using:
<ctrl-d>
Runs through fine, and when I ctrl-d I get a -1
return code.
c io
7
I don't see the exercise but(0 | 1)
isn't probably what you think it is.|
is bitwise OR then it's equivalent to1
. Now it then can be reduced togetchar() != EOF == 1
which is again equivalent togetchar() != EOF
(because==
returns 1 or 0 and it's mandated by the standard).
â Adriano Repetti
Jul 12 at 16:15
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
2
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
2
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
3
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39
 |Â
show 1 more comment
up vote
5
down vote
favorite
up vote
5
down vote
favorite
I'm working through K&R at the moment and I've found my first exercise that seems to be a good use for my first CodeReview post.
Exercise 1-6 - Verify that the expression getchar() != EOF
is 0
or 1
.
Exercise 1-7 - Write a program to print the value of EOF
.
I've completed both of these together in the same file.
I think I've understood the question here, but let me know if I haven't. I wanted to post here before looking up any sort of "official" answer so that I could learn some stuff instead of just "going to the back of the book".
#include <stdio.h>
void main()
int c;
c = getchar();
while ((c = getchar()) != EOF == (0
Compiled with:
gcc putchar.c -o putchar
Sending EOF using:
<ctrl-d>
Runs through fine, and when I ctrl-d I get a -1
return code.
c io
I'm working through K&R at the moment and I've found my first exercise that seems to be a good use for my first CodeReview post.
Exercise 1-6 - Verify that the expression getchar() != EOF
is 0
or 1
.
Exercise 1-7 - Write a program to print the value of EOF
.
I've completed both of these together in the same file.
I think I've understood the question here, but let me know if I haven't. I wanted to post here before looking up any sort of "official" answer so that I could learn some stuff instead of just "going to the back of the book".
#include <stdio.h>
void main()
int c;
c = getchar();
while ((c = getchar()) != EOF == (0
Compiled with:
gcc putchar.c -o putchar
Sending EOF using:
<ctrl-d>
Runs through fine, and when I ctrl-d I get a -1
return code.
c io
edited Jul 12 at 16:17
200_success
123k14143399
123k14143399
asked Jul 12 at 15:54
John Von Neumann
1335
1335
7
I don't see the exercise but(0 | 1)
isn't probably what you think it is.|
is bitwise OR then it's equivalent to1
. Now it then can be reduced togetchar() != EOF == 1
which is again equivalent togetchar() != EOF
(because==
returns 1 or 0 and it's mandated by the standard).
â Adriano Repetti
Jul 12 at 16:15
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
2
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
2
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
3
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39
 |Â
show 1 more comment
7
I don't see the exercise but(0 | 1)
isn't probably what you think it is.|
is bitwise OR then it's equivalent to1
. Now it then can be reduced togetchar() != EOF == 1
which is again equivalent togetchar() != EOF
(because==
returns 1 or 0 and it's mandated by the standard).
â Adriano Repetti
Jul 12 at 16:15
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
2
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
2
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
3
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39
7
7
I don't see the exercise but
(0 | 1)
isn't probably what you think it is. |
is bitwise OR then it's equivalent to 1
. Now it then can be reduced to getchar() != EOF == 1
which is again equivalent to getchar() != EOF
(because ==
returns 1 or 0 and it's mandated by the standard).â Adriano Repetti
Jul 12 at 16:15
I don't see the exercise but
(0 | 1)
isn't probably what you think it is. |
is bitwise OR then it's equivalent to 1
. Now it then can be reduced to getchar() != EOF == 1
which is again equivalent to getchar() != EOF
(because ==
returns 1 or 0 and it's mandated by the standard).â Adriano Repetti
Jul 12 at 16:15
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
2
2
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
2
2
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
3
3
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39
 |Â
show 1 more comment
1 Answer
1
active
oldest
votes
up vote
4
down vote
accepted
This is a nice, clear, short attempt at the exercise.
You've avoided a couple of common problems:
- You're correctly using
int
for the return value fromgetchar()
. A common mistake is to be misled by the name and to assign directly to achar
variable. That doesn't work, because truncating tochar
preventsEOF
from being distinguished from a validchar
value. - You've correctly matched the
%d
specifier to the type ofEOF
.
One simple way to improve your code is to get the compiler to point out weaknesses for you (by default, most C compilers are very lenient; you have to specifically ask for more warnings):
gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion putchar.c -o putchar
You can make it easier by writing a simple Makefile
that contains just:
CFLAGS = -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion
And you can then build simply with
make putchar
When you've enabled warnings, you'll see:
198374.c:3:6: warning: return type of âÂÂmainâ is not âÂÂintâ [-Wmain]
void main()
^~~~
The fix for that should be obvious.
Now to the meat of the program. Firstly, before the loop we have a statement
c = getchar();
This consumes and ignores one character. We probably didn't mean to throw that one away.
Now consider this expression:
(c = getchar()) != EOF == (0 | 1)
We're actually comparing (after the assignment) c != EOF
against 0|1
. But |
is the bitwise-or operator, so 0|1
evaluates to just 1
. When c
is not EOF
, then c!=EOF
is 1
, and the condition is satisfied. The last time around the loop (when c
becomes EOF
), then c!=EOF
is 0
, and the loop exits.
What we want to do is save the result of c != EOF
and compare that to 0
and to 1
separately. Or, even more simply for this exercise, just print it to standard output:
do
c = getchar();
printf("getchar() != EOF: %dn", c != EOF);
while (c != EOF);
NoteL given that we haven't been asked to copy the input to output, we shouldn't have the putchar()
call.
If we really want to prove that c != EOF
is always either 0
or 1
, we could test it automatically:
do
c = getchar();
if ((c != EOF) != 0 && (c != EOF) != 1)
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
You might choose to use a switch
statement instead of the if
; I think that's clearer:
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
Modified code
#include <stdio.h>
int main()
int c;
do
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
printf("%dn", c);
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. Thec = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!
â John Von Neumann
Jul 13 at 14:33
"That doesn't work, becauseEOF
is outside the range of any validchar
." --> Not quite.EOF
often has the value of -1 and a signedchar
typically has the range of -128 to 127. So having anEOF
inside thechar
range is common. The "doesn't work" is due togetchar()
retuning values in theunsigned char
range and the negativeEOF
and these typical 257 different values are not distinguishable with an 8-bitchar
.
â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with theto*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative thanCHAR_MIN
.
â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
 |Â
show 2 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
This is a nice, clear, short attempt at the exercise.
You've avoided a couple of common problems:
- You're correctly using
int
for the return value fromgetchar()
. A common mistake is to be misled by the name and to assign directly to achar
variable. That doesn't work, because truncating tochar
preventsEOF
from being distinguished from a validchar
value. - You've correctly matched the
%d
specifier to the type ofEOF
.
One simple way to improve your code is to get the compiler to point out weaknesses for you (by default, most C compilers are very lenient; you have to specifically ask for more warnings):
gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion putchar.c -o putchar
You can make it easier by writing a simple Makefile
that contains just:
CFLAGS = -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion
And you can then build simply with
make putchar
When you've enabled warnings, you'll see:
198374.c:3:6: warning: return type of âÂÂmainâ is not âÂÂintâ [-Wmain]
void main()
^~~~
The fix for that should be obvious.
Now to the meat of the program. Firstly, before the loop we have a statement
c = getchar();
This consumes and ignores one character. We probably didn't mean to throw that one away.
Now consider this expression:
(c = getchar()) != EOF == (0 | 1)
We're actually comparing (after the assignment) c != EOF
against 0|1
. But |
is the bitwise-or operator, so 0|1
evaluates to just 1
. When c
is not EOF
, then c!=EOF
is 1
, and the condition is satisfied. The last time around the loop (when c
becomes EOF
), then c!=EOF
is 0
, and the loop exits.
What we want to do is save the result of c != EOF
and compare that to 0
and to 1
separately. Or, even more simply for this exercise, just print it to standard output:
do
c = getchar();
printf("getchar() != EOF: %dn", c != EOF);
while (c != EOF);
NoteL given that we haven't been asked to copy the input to output, we shouldn't have the putchar()
call.
If we really want to prove that c != EOF
is always either 0
or 1
, we could test it automatically:
do
c = getchar();
if ((c != EOF) != 0 && (c != EOF) != 1)
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
You might choose to use a switch
statement instead of the if
; I think that's clearer:
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
Modified code
#include <stdio.h>
int main()
int c;
do
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
printf("%dn", c);
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. Thec = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!
â John Von Neumann
Jul 13 at 14:33
"That doesn't work, becauseEOF
is outside the range of any validchar
." --> Not quite.EOF
often has the value of -1 and a signedchar
typically has the range of -128 to 127. So having anEOF
inside thechar
range is common. The "doesn't work" is due togetchar()
retuning values in theunsigned char
range and the negativeEOF
and these typical 257 different values are not distinguishable with an 8-bitchar
.
â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with theto*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative thanCHAR_MIN
.
â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
 |Â
show 2 more comments
up vote
4
down vote
accepted
This is a nice, clear, short attempt at the exercise.
You've avoided a couple of common problems:
- You're correctly using
int
for the return value fromgetchar()
. A common mistake is to be misled by the name and to assign directly to achar
variable. That doesn't work, because truncating tochar
preventsEOF
from being distinguished from a validchar
value. - You've correctly matched the
%d
specifier to the type ofEOF
.
One simple way to improve your code is to get the compiler to point out weaknesses for you (by default, most C compilers are very lenient; you have to specifically ask for more warnings):
gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion putchar.c -o putchar
You can make it easier by writing a simple Makefile
that contains just:
CFLAGS = -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion
And you can then build simply with
make putchar
When you've enabled warnings, you'll see:
198374.c:3:6: warning: return type of âÂÂmainâ is not âÂÂintâ [-Wmain]
void main()
^~~~
The fix for that should be obvious.
Now to the meat of the program. Firstly, before the loop we have a statement
c = getchar();
This consumes and ignores one character. We probably didn't mean to throw that one away.
Now consider this expression:
(c = getchar()) != EOF == (0 | 1)
We're actually comparing (after the assignment) c != EOF
against 0|1
. But |
is the bitwise-or operator, so 0|1
evaluates to just 1
. When c
is not EOF
, then c!=EOF
is 1
, and the condition is satisfied. The last time around the loop (when c
becomes EOF
), then c!=EOF
is 0
, and the loop exits.
What we want to do is save the result of c != EOF
and compare that to 0
and to 1
separately. Or, even more simply for this exercise, just print it to standard output:
do
c = getchar();
printf("getchar() != EOF: %dn", c != EOF);
while (c != EOF);
NoteL given that we haven't been asked to copy the input to output, we shouldn't have the putchar()
call.
If we really want to prove that c != EOF
is always either 0
or 1
, we could test it automatically:
do
c = getchar();
if ((c != EOF) != 0 && (c != EOF) != 1)
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
You might choose to use a switch
statement instead of the if
; I think that's clearer:
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
Modified code
#include <stdio.h>
int main()
int c;
do
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
printf("%dn", c);
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. Thec = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!
â John Von Neumann
Jul 13 at 14:33
"That doesn't work, becauseEOF
is outside the range of any validchar
." --> Not quite.EOF
often has the value of -1 and a signedchar
typically has the range of -128 to 127. So having anEOF
inside thechar
range is common. The "doesn't work" is due togetchar()
retuning values in theunsigned char
range and the negativeEOF
and these typical 257 different values are not distinguishable with an 8-bitchar
.
â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with theto*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative thanCHAR_MIN
.
â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
 |Â
show 2 more comments
up vote
4
down vote
accepted
up vote
4
down vote
accepted
This is a nice, clear, short attempt at the exercise.
You've avoided a couple of common problems:
- You're correctly using
int
for the return value fromgetchar()
. A common mistake is to be misled by the name and to assign directly to achar
variable. That doesn't work, because truncating tochar
preventsEOF
from being distinguished from a validchar
value. - You've correctly matched the
%d
specifier to the type ofEOF
.
One simple way to improve your code is to get the compiler to point out weaknesses for you (by default, most C compilers are very lenient; you have to specifically ask for more warnings):
gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion putchar.c -o putchar
You can make it easier by writing a simple Makefile
that contains just:
CFLAGS = -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion
And you can then build simply with
make putchar
When you've enabled warnings, you'll see:
198374.c:3:6: warning: return type of âÂÂmainâ is not âÂÂintâ [-Wmain]
void main()
^~~~
The fix for that should be obvious.
Now to the meat of the program. Firstly, before the loop we have a statement
c = getchar();
This consumes and ignores one character. We probably didn't mean to throw that one away.
Now consider this expression:
(c = getchar()) != EOF == (0 | 1)
We're actually comparing (after the assignment) c != EOF
against 0|1
. But |
is the bitwise-or operator, so 0|1
evaluates to just 1
. When c
is not EOF
, then c!=EOF
is 1
, and the condition is satisfied. The last time around the loop (when c
becomes EOF
), then c!=EOF
is 0
, and the loop exits.
What we want to do is save the result of c != EOF
and compare that to 0
and to 1
separately. Or, even more simply for this exercise, just print it to standard output:
do
c = getchar();
printf("getchar() != EOF: %dn", c != EOF);
while (c != EOF);
NoteL given that we haven't been asked to copy the input to output, we shouldn't have the putchar()
call.
If we really want to prove that c != EOF
is always either 0
or 1
, we could test it automatically:
do
c = getchar();
if ((c != EOF) != 0 && (c != EOF) != 1)
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
You might choose to use a switch
statement instead of the if
; I think that's clearer:
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
Modified code
#include <stdio.h>
int main()
int c;
do
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
printf("%dn", c);
This is a nice, clear, short attempt at the exercise.
You've avoided a couple of common problems:
- You're correctly using
int
for the return value fromgetchar()
. A common mistake is to be misled by the name and to assign directly to achar
variable. That doesn't work, because truncating tochar
preventsEOF
from being distinguished from a validchar
value. - You've correctly matched the
%d
specifier to the type ofEOF
.
One simple way to improve your code is to get the compiler to point out weaknesses for you (by default, most C compilers are very lenient; you have to specifically ask for more warnings):
gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion putchar.c -o putchar
You can make it easier by writing a simple Makefile
that contains just:
CFLAGS = -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion
And you can then build simply with
make putchar
When you've enabled warnings, you'll see:
198374.c:3:6: warning: return type of âÂÂmainâ is not âÂÂintâ [-Wmain]
void main()
^~~~
The fix for that should be obvious.
Now to the meat of the program. Firstly, before the loop we have a statement
c = getchar();
This consumes and ignores one character. We probably didn't mean to throw that one away.
Now consider this expression:
(c = getchar()) != EOF == (0 | 1)
We're actually comparing (after the assignment) c != EOF
against 0|1
. But |
is the bitwise-or operator, so 0|1
evaluates to just 1
. When c
is not EOF
, then c!=EOF
is 1
, and the condition is satisfied. The last time around the loop (when c
becomes EOF
), then c!=EOF
is 0
, and the loop exits.
What we want to do is save the result of c != EOF
and compare that to 0
and to 1
separately. Or, even more simply for this exercise, just print it to standard output:
do
c = getchar();
printf("getchar() != EOF: %dn", c != EOF);
while (c != EOF);
NoteL given that we haven't been asked to copy the input to output, we shouldn't have the putchar()
call.
If we really want to prove that c != EOF
is always either 0
or 1
, we could test it automatically:
do
c = getchar();
if ((c != EOF) != 0 && (c != EOF) != 1)
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
You might choose to use a switch
statement instead of the if
; I think that's clearer:
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
Modified code
#include <stdio.h>
int main()
int c;
do
c = getchar();
switch (c != EOF)
case 0: /* okay */
case 1: /* okay */
break;
default:
fprintf(stderr, "(c != EOF) was neither 0 nor 1n");
return 1;
while (c != EOF);
printf("%dn", c);
edited Jul 13 at 14:50
answered Jul 13 at 9:26
Toby Speight
17.2k13486
17.2k13486
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. Thec = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!
â John Von Neumann
Jul 13 at 14:33
"That doesn't work, becauseEOF
is outside the range of any validchar
." --> Not quite.EOF
often has the value of -1 and a signedchar
typically has the range of -128 to 127. So having anEOF
inside thechar
range is common. The "doesn't work" is due togetchar()
retuning values in theunsigned char
range and the negativeEOF
and these typical 257 different values are not distinguishable with an 8-bitchar
.
â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with theto*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative thanCHAR_MIN
.
â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
 |Â
show 2 more comments
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. Thec = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!
â John Von Neumann
Jul 13 at 14:33
"That doesn't work, becauseEOF
is outside the range of any validchar
." --> Not quite.EOF
often has the value of -1 and a signedchar
typically has the range of -128 to 127. So having anEOF
inside thechar
range is common. The "doesn't work" is due togetchar()
retuning values in theunsigned char
range and the negativeEOF
and these typical 257 different values are not distinguishable with an 8-bitchar
.
â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with theto*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative thanCHAR_MIN
.
â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. The
c = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!â John Von Neumann
Jul 13 at 14:33
Cheers for the awesome reply! Means a lot, and the Makefile stuff I had no clue about, thanks for that, works like a charm. The
c = getchar()
throwing away the first character I didn't know about, but I had noticed that it was happening, had no clue why though!â John Von Neumann
Jul 13 at 14:33
"That doesn't work, because
EOF
is outside the range of any valid char
." --> Not quite. EOF
often has the value of -1 and a signed char
typically has the range of -128 to 127. So having an EOF
inside the char
range is common. The "doesn't work" is due to getchar()
retuning values in the unsigned char
range and the negative EOF
and these typical 257 different values are not distinguishable with an 8-bit char
.â chux
Jul 13 at 14:36
"That doesn't work, because
EOF
is outside the range of any valid char
." --> Not quite. EOF
often has the value of -1 and a signed char
typically has the range of -128 to 127. So having an EOF
inside the char
range is common. The "doesn't work" is due to getchar()
retuning values in the unsigned char
range and the negative EOF
and these typical 257 different values are not distinguishable with an 8-bit char
.â chux
Jul 13 at 14:36
Oh yes - I hate these conversions between plain and unsigned char (such as with the
to*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative than CHAR_MIN
.â Toby Speight
Jul 13 at 14:49
Oh yes - I hate these conversions between plain and unsigned char (such as with the
to*()
family of functions). EOF does have to have a negative value, and I mistakenly assumed that it just had to be more negative than CHAR_MIN
.â Toby Speight
Jul 13 at 14:49
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
Why do we do this? ` case 0: /* okay / case 1: / okay */` And not assign a success for the case statements? Except for the 1 of course.
â John Von Neumann
Jul 13 at 15:03
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
EDIT: Ignore me, I know why now haha. Because 0 is success so we just continue checking until EOF or an issue, hence the break on exit code 1.
â John Von Neumann
Jul 13 at 15:09
 |Â
show 2 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f198374%2fkr-exercise-1-6-1-7-working-with-eof%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
7
I don't see the exercise but
(0 | 1)
isn't probably what you think it is.|
is bitwise OR then it's equivalent to1
. Now it then can be reduced togetchar() != EOF == 1
which is again equivalent togetchar() != EOF
(because==
returns 1 or 0 and it's mandated by the standard).â Adriano Repetti
Jul 12 at 16:15
Ahhhhh right yeah I've definitely misused it then! Cheers for that, I'll have a look over my code and make an edit! Thanks.
â John Von Neumann
Jul 12 at 16:28
2
I think (but I may be wrong) that someone considers the question off-topic because code does not work as intended. I don't agree because close reason says (emphasis is mine) "...working correctly, to the best of the author's knowledge" then this is a perfectly fine question.
â Adriano Repetti
Jul 12 at 16:40
2
@AdrianoRepetti While that may have been true at the time of posting, it is no longer true (as the OP is now aware of the bug). It is also what might be considered an obvious bug (at least obvious after having encountered it many times before). OP, you can (almost) always edit your question to make it on-topic, once you have the correct solution. The only exception to that is if you have received answer (so as not to invalidate them).
â Graipher
Jul 12 at 17:23
3
@Graipher The code works, just not for the reason that the author thought. That misconception is perfect material to be discussed in a Code Review answer â no need to edit the question.
â 200_success
Jul 12 at 18:39