Search code examples
ckernighan-and-ritchie

K&R 1-7 is it solvable by using putchar() instead of printf?


There are many questions about this exercise all over the internet, but I couldn't find any solution (nor any hint) on how to solve this exercise using 'putchar'.

Write a program to print the value of EOF.

I can easily get a working answer to this:

printf("%d", EOF);

I'd like to know if there are any known (or logical) answers using 'putchar' (as I guess that was the whole purpose of the exercise, being located at the end of a paragraph on 'getchar' and 'putchar')

Writing:

putchar(EOF);

or

int c;
c = EOF;
putchar(c);

the program just launches and closes itself without showing any text.


Solution

  • putchar converts its argument to unsigned char before it's outputted (and it's a character which is written, not the result of a decimal conversion). As EOF is negative, this conversion isn't value-preserving. Commonly, EOF has the value -1, with 8-bit char, that conversion results in 255, that is, putchar(EOF) is equivalent to putchar('\xff'), which isn't a printable character (assuming an ASCII system). Piping the output to hexdump -C would make the output visible.

    Without using printf and friends, a function outputting a decimal number for an int can be written. Basically,

    print a '-' if the value is negative
    for every decimal digit, starting from the highest-valued:
        convert the digit's value to a character (e.g. 7 should become '7')
        try to print the result (with putchar, for example)
        if that fails, return an error indicator
    

    Hint: The division and modulus operators, / and %, will be useful.

    The digits '0' ... '9' are ascending (and contiguous); so for the conversion from the digit's value to a character, adding '0' yields the desired result (3 + '0' is '3', for example).

    Care must be taken to avoid integer overflow, even if corner cases like INT_MIN are passed to the function. -INT_MIN may result in an overflow (and in fact does on pretty much every system), a positive number, on the other hand, can always be negated. A value of 0 may need special handling.

    (Alternatively, the number can be converted to a string first which then can be outputted. A char array of size 1 + sizeof(int)*CHAR_BIT/3+1 + 1 is big enough to hold that string, including minus sign and 0-terminator.)

    If you get stuck, the (non-standard) itoa function does something similar, looking for example implementations may give some ideas.