C, K&R Exercise 1-6, stuck, confused

Viewed 796

I am a noob teaching myself to program in C using The C Programming Language, Second Edition (by K&R). In Chapter 1 Section 1.5.1 File Copying, the authors touch very briefly on operational precedence when making comparison between values, underscoring the importance of using parenthesis, in this case, to ensure that assignment is made to the variable 'c' before the comparison is evaluated. They make the assertion that:

    c = getchar() != EOF

is equivalent to

    c = (getchar() != EOF)

Which "has the undesired effect of setting c to 0 or 1, depending on whether or not the call of getchar encountered end of file"

The authors then pose Excercise 1-6 - Verify that the expression getchar () != EOF is 0 or 1

Based on the author's previous assertion, this seemed almost trivial so I created this code:

#include <stdio.h>

main()
{
    int c;

    while (c = (getchar() != EOF))
        putchar(c);
}

Unfortunately, when I run the program, it simply outputs whatever characters I type in the command window rather than the expected string of 1 or 0 if EOF is encountered.

While I am a noob, I think I get the logic that the authors are trying to teach and yet I can not demonstrate this simple task. In this case, should not the variable c take on the value that the comparison expression evaluated to rather than whatever character getchar() happens to fetch, particularly because of the location of the parenthesis? If c is indeed taking on the value of the comparison, putchar() should only output 0 or 1 and yet, as formulated, it outputs what I type in the command window. What am I doing wrong? What do I not understand? Could it be my compiler? I am coding in in Visual Studio 2017 Community edition on Windows 10 on x64 architecture. I have Tiny C Compiler but have not tried executing from command prompt with TCC yet.

2 Answers

When you run the program, the characters that you see doesn't come from your program. It's the console (or terminal)'s echo funcion that shows whatever character you have typed (and you can even erase them before you hit Enter). Your program only outpus characters with ASCII code 0 or 1, both of which are invisible.

If you change putchar(c) to printf("%d", c) you'll be able to see a sequence of 1s. No zero will appear because when c becomes zero, the loop stops and it won't be printed.

Characters '0' and '1' have the ASCII code of 48 and 49, respectively, despite the fact that your terminal may use another encoding. If you want to output a literal number 0, use the character notation. You can also try putchar(48) but don't use this too much (You'll later find out that it's highly discouraged to use magic numbers in your program).

putchar('0');
        ^ ^

The assertion that

c = getchar() != EOF;

is equivalent to

c = (getchar() != EOF);

is because of operator precedence. The operator != (inequality) has a higher precedence over = (value assignment), so it gets evaluated prior to assignment.

Finally, it's extremely rare for someone to have written that. The correct intention is to write this:

while ( (c = getchar()) != EOF )

The thing is c = (getchar() != EOF) it will get one input character and then it compares. Result will be 1 in case it is not EOF. Then it is assigned. The value of assignment statement is the value that is being assigned. It enters the loop. Prints the character having ascii value 1. But that character is non-printable so you don't see anything.

Once it gets EOF it will break from the loop. So you never get to see anything other than the character which has ascii value of 1.(Even you don't see that also as it is non-printable). These are known as ascii-control characters. (Not belong to the printable class).

Also you said as c=0 or c=1 it should print 0 or 1. Then try this simple code

int c= 68;
putchar(c);

Check the output and you will get the idea what happens when we try to print. It's the character whose ascii code is 68, that is printed, not the value 68.

The right way to do it would be ((c = getchar()) != EOF).

Originally I mentioned that on some machines it prints some funny characters. The representation of the non-printable characters depend on the used charset. It might be some non-standard encoding (non-unicode) which assigns to the ascii code 1 some representation.(breaking the idea of nonprintables)

Related