0

I read that

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

will print the value 0 or 1 depending on whether the next character is an EOF or not. Because != has a higher precedence than =.

But when I run this program in GCC, I get a character that looks like

|0 0|
|0 1|

as output when I press Enter.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Eipe
  • 10,922
  • 24
  • 72
  • 114
  • My understanding is that since the inequality checking happens first the variable c should get the value 0 which is equivalent to false. – John Eipe Mar 02 '11 at 13:38
  • Related: *[What is the printf format specifier for bool?](https://stackoverflow.com/questions/17307275/what-is-the-printf-format-specifier-for-bool)* – Peter Mortensen Aug 07 '23 at 19:24

4 Answers4

6

putchar prints a character. By printing the values 0 and 1, you're printing the null and start of heading (SOH) characters, both control characters. You'll need to convert the numbers 0 and 1 to something that's printable, either by calculating a printable value directly from the 0 or 1:

while (...) {
    // note: the C standard (§ 5.2.1-3 of C99) ensures '0'+1 is '1', which is printable
    putchar(c+'0');
}

or using c to decide what to print.

while (...) {
    if (c) {
        ...
    } else {
        ...
    }
    // or:
    //putchar(c ? ... : ...);
    // though feelings on the ternary operator vary.
}
outis
  • 75,655
  • 22
  • 151
  • 221
  • 1
    You can turn that into a macro for readability: #define BOOL_TO_ASCII(c) ((c) ? '1' : '0') – salezica Mar 02 '11 at 14:07
  • `'0' + 1` is `'1'`. The C Standard mandates all digits be sequential from '0' to '9'. There is no such guarantee for letters. – pmg Mar 02 '11 at 14:09
  • @pmg: I was not aware of that. Good to know. – outis Mar 02 '11 at 14:12
  • @Santiago: feelings on macros vary, too. – outis Mar 02 '11 at 14:12
  • @outis I didn't mean for my macro to hurt feelings! :( I was just addressing the OP, presenting the option, I didn't mean you should change the answer or anything :). – salezica Mar 02 '11 at 14:19
  • @Santiago: on the other hand, why should we care about feelings? We're programmers, after all. Maybe I *should* throw in that macro. – outis Mar 02 '11 at 14:24
  • @santiago-lezica - I think that's a very nice macro. Simple and concise and hopefully put somewhere easily accessible where someone can find it easily. – spade78 Mar 02 '11 at 15:58
  • thanks. So putchar parameter should be either a valid ascii code or a character(which is also converted to ascii code). – John Eipe Mar 03 '11 at 03:41
  • 1
    Character values are numbers, both in C ('char' is an integer type large enough to store the members of the basic character set) and in ASCII (which associates numeric code points and characters). What distinguishes chars from other numeric types in C is that chars have special display semantics. Also, the encoding doesn't need to be ASCII; it's whatever the platform uses (`putchar` simply writes the character to a stream, unconcerned with what the stream does with it). – outis Mar 03 '11 at 04:48
  • @John: it basically means rather than displaying a numeric representation of a character value when output (as with other numeric types), a graphic representation of the character that the numeric value encodes is displayed. For the full semantics, see [C99 §5.2.2](http://www.vmunix.com/~gabor/c/draft.html#5.2.2). The stream that putchar writes to interprets whatever numeric values it receives as character codes, mapping them to a graphic representation and outputting those. – outis Mar 03 '11 at 21:32
  • ... Co-founder of SO Joel Spolsky wrote an article on the topic of [encoding and character sets](http://joelonsoftware.com/articles/Unicode.html). It doesn't cover the char type in C, but it should prove enlightening. – outis Mar 03 '11 at 21:34
1

You are using a Unicode console. All non-printable characters (like the bytes with value 0 and 1) are converted to the 2x2-matrix displaying its Unicode value. (Also, for all printable characters for which you have no font installed.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bernd Elkemann
  • 23,242
  • 4
  • 37
  • 66
1

In addition to what everyone said about c being a nonprintable character, you would never print out a 0 for EOF anyway, since you're not going to go into the while loop in that case. You would need an extra putchar after the loop.

irritate
  • 7,350
  • 1
  • 17
  • 11
  • yes. But that's where the problem is. I'm running the program in a terminal (in Ubuntu). Pressing Ctrl+C is the only way to send the EOF value. But immediately the program quits so how do i print it?? – John Eipe Mar 03 '11 at 04:00
  • See this answer for more info http://stackoverflow.com/questions/1793616/why-doesnt-getchar-recognise-return-as-eof-in-windows-console – irritate Mar 03 '11 at 12:35
1

This is what happens in your program

int c;

reserve space for an int (call that space c) and don't worry about its contents.

while(c = getchar( ) != EOF)

The thing in parenthesis can be written as c = (getchar( ) != EOF) because the assignment operator has lower precedence than the inequality operator.

  • getchar() waits for a keypress and returns the value of the key pressed
  • That value is checked against EOF
  • As it's different, the result of the inequality operator is 1
  • and the value 1 gets put in the space with name c.

Then, inside the while loop

{
   putchar(c);
}

you're printing the character with value 1. As you've noticed, on your computer, the character with value 1 does not have a beautiful format when displayed :)


If you really want to print the values 0 or 1 with beautiful formats, try this

c = 0; /* or 1 */
putchar('0' + c);

If you want to print a value between 0 and 9 as a character, try this

c = 5; /* or 7, or 0, ... */
putchar('0' + c);
pmg
  • 106,608
  • 13
  • 126
  • 198
  • `getchar()` returns EOF only rarely. When it returns regular values they are different and the condition ( `getchar() != EOF` ) is true. – pmg Mar 03 '11 at 07:56
  • oh... yes my mistake. It's true. – John Eipe Mar 03 '11 at 10:51
  • I'm running the program in terminal. So ctrl+C is the way to send EOF, right? But my program also quits. So how do we print the last false value. – John Eipe Mar 03 '11 at 10:52
  • 1
    @John: you send EOF with `Ctrl+D` in *nix or `Ctrl+Z` in windows. `Ctrl+C` send a "quit" signal in both environments: no wonder the program quits :) – pmg Mar 03 '11 at 10:56