Search code examples
cprintfputchar

putchar and printf not behaving as expected


I'm working through some of the exercises in K&R. Exercise 1-6 asks for verification that the expression getchar() != EOF is either 0 or 1. I understand why it is, but the code I wrote to prove it didn't work as expected. I wrote the following two snippets:

Version 1:

int main(void)
{
    int c;

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

    printf("%d at EOF\n", c);

    return 0;
}

Version 2:

int main(void)
{
    int c;

    while (c = getchar() != EOF)
    {
         printf("%d\n", c);
    }

    printf("%d at EOF\n", c);

    return 0;
}

My questions:

  1. When I type in a character and hit enter with version one, why do I not see either a 0 or 1 on the screen? Instead, my cursor moves to the first position on next line, which is otherwise empty. I though putchar would send c to stdout.

  2. While the use of printf in the second version does produce a 0 or 1 appropriately, it duplicates the 1 for each non-EOF character (I see the number 1 on two consecutive lines for each character I input). Why?

Many thanks in advance for your thoughts. If there is a reference that you think would help, please send a link.

CLARIFICATION:

I know I'm assigning c a value of either 0 or 1. That's what I want to do, and it's what the exercise wants. That's also why I don't have parentheses around c = getchar(). My question deals more with understanding why the output isn't what I had expected. Sorry for any confusion.


Solution

  • The assignment operator = has lower precedence than the inequality operator !=.

    So this:

    while (c = getchar() != EOF)
    

    Is parsed as:

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

    So then c is assigned the boolean value 1 if getchar is not EOF and 0 if it does return EOF.

    As a result, the first program print the character for the ASCII code 1, which is a non-printable character. That's why you don't see anything. The second program, using the %d format specifier to printf, converts the number 1 to its string representation.

    You need parenthesis to have the result of getchar assigned to c:

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

    EDIT:

    To further clarify the output you're getting, in both programs the variable c has the value 1 inside of each while loop. The difference here is that putchar is printing the character with the ASCII value of 1 (an unprintable character), while printf with %d print the textual representation of the value 1, i.e. 1.

    If you changed the printf call to this:

    printf("%c", c);
    

    You would get the same output as using putchar.

    As for the printing of 1 twice for each character, that is because you're actually entering two characters: the key you press, plus the enter key. When reading from the console, the getchar function doesn't return until the enter key is pressed.