Control-D ends getchar but not program, prog continues with garbage value in receiving variable?

439 views Asked by At

I'm taking a user-inputted single character. The program continues getting characters with getchar until it encounters a non-space character, then uses that character to print a display.

If the user enters control-D instead of a character, the getchar input terminates and the program should too.

   char border;
   printf("Enter the character for the border: ");
   while ((border = getchar()) != EOF && border != '\n') {
     if (!isspace(border)){
        break;
     }
   }

Except if I enter control-D, the loop terminates...and the program allots the garbage character ▒▒ to border, then continues the program.

I've tried if (!border) { return 1; } and attempting to return 1 if border compared to ▒▒ is true, but no dice either way.

What's going on, and how can I handle this?

2

There are 2 answers

9
templatetypedef On BEST ANSWER

Pressing CTRL+D doesn't terminate the program. Instead, it closes the stdin input stream. Most command-line utilities are designed to do something and then terminate after this happens. Contrast this with CTRL+C, which sends a kill signal to the program.

Your code currently works by assigning the return value of getchar() to border, so if getchar returns EOF, it will assign EOF to border, then exit the loop. You can test for whether this happened by checking if border is equal to EOF after the loop.

As @Olaf pointed out, there's another issue here. Notice that border is a char and that getchar returns an integer. Change the type of border to int to prevent issues later on in your code.

Hope this helps!

0
too honest for this site On

There is a chain of problems actually:

  • getchar() returns int, not char.
  • Whether char is signed or unsigned is not fixed by the standard, but implementation dependend.
  • EOF is always a negative int.
  • A valid char returned by getchar() is returned non-negative (simplified: the character code is in the lower bits, the uppermost bits are 0). So it is actually unsigned char converted to int.
  • For comparisons, type promotion is applied first to a common type. As char has a lower rank than int, it is promoted to int (zero- or sign-extended).

In any case, the cast maps EOF to a valid character code from the extended character set (the base set is actually ASCII and in the range 0..127). This shadows the character, making both indistinguishable in the first place.

However, due to type promition, comparing with EOF yields different results for signed char and unsigned char:

  • signed char, CHAR_MIN <= EOF (always < 0): The compare will work, but the original char will be errorneously treated as EOF, too.
  • signed char, EOF < CHAR_MIN (e.g. -129): That is actually undefined behaviour, everything can happen. For the typical case (2s complemente, upper bits truncated, the result can very well be positive. Never compares equal to the (negative!) EOF.
  • unsigned char: promoted to positve integer, never equals the (negative) EOF.

Note also not to make any assumptions about EOF except for what the standard defines (it is negative). So, always asigngetchar()to anint, test forEOFand **then** convert tochar`.

Try this to see the values returned by getchar():

#include <stdio.h>

int main()
{
       int ch;
       do {
              ch = getchar();
              printf("0x%08X\n", ch);
       } while ( ch != EOF ) ;
}

Remember: input is line-buffered, so you have to press return to see the values.