tags:

views:

660

answers:

3

When programming C for the command console, what happens when you have a function that tries to use SCANF to ask user input for a CHAR variable, and the user types CTRL+Z (EOF) and hits enter?

For example:

char promptChar()
{
    char c;
    printf("Enter a character: ");
    scanf("%c", &c);
    return c;
}

If the user types CTRL+Z and hits enter, what will promptChar() return? Because if I understand EOF, it's an int.

+4  A: 

From the Linux scanf(3) manpage:

"The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error."

Note that this passage concerns the return value of scanf, not the result parameters.

Michiel Buddingh'
A: 

It depends on the command shell you are using, but you really shouldn't be designing any program to expect to read control characters from an interactive prompt.

Most command shells will intercept some of the control characters and use them to tell the shell to do things. For instance ctrl-s and ctrl-q often start and stop the shell's diplay of output characters. ctrl-z on some shells will actually be taken as a command to shut the shell down.

T.E.D.
EOF isn't a control character. It's not a byte from the stream at all -- it's a value that lies *outside* the range of valid characters (by convention it's 0xffffffff on most platforms) that is returned when the underlying system call reports end of file.
Andy Ross
@Andy: EOF occurs when a read() on the file returns zero bytes of data. When you type Control-D (or Control-Z) at the terminal, it sends any pending characters to the programs reading from the terminal. If there are no pending characters, the read() returns 0, which is interpreted as EOF. And EOF is -1 on almost all platforms; that is not 0xFFFFFFFF on 64-bit platforms.
Jonathan Leffler
Jonathan: I know. I think you're vigorously agreeing with me. What EOF is **not** is a "control character". It's not part of the stream at all. And I said "most" platforms, so I don't understand the nit. I wrote it in hex to make the fact that it's not a char clear.
Andy Ross
Yup, ASCII defines EOT (End of Transmission, 04) ETX (End of Text, 03), even EM (End of Medium) but not EOF. There is an FS (File Seperator) though.
MSalters
+7  A: 

First things first:

SCANF is not defined by the language.
CHAR is not defined by the language.

Ok, with that out of the way ...

The scanf() function returns an integer. That integer is the number of input items assigned or the value of the macro EOF if an input failure occurs before the first conversion.
You didn't check the return value of the scanf() call, so you have no idea what happened. Everything might have worked ok, or the input stream might have ended before the first conversion, or (not for %c) there might have been a conversion failure.

Test the return value of scanf(). Indeed, always test the return value of all <stdio.h> functions.

char ch;
int result = scanf("%c", &ch);
if (result == 1) /* all ok */;
else if (result == 0) /* conversion failure: value of `ch` is indeterminate */;
else if (result == EOF) /* input failure; value of `ch` is indeterminate */;

When the result of the scanf() call is EOF, if you want more information about the reason for input failure, you can use feof() and/or ferror().

else if (result == EOF) {
    if (feof(stdin)) {
        /* no data in input stream */
    }
    if (ferror(stdin)) {
        /* error if input stream (media ejected? bad sector? ...?)
    }
}


To answer your question: what will promptChar() return?

It will return an indeterminate value of type char.
You could follow the example of library function that deal with characters and return an int from promptChar(). That would be the value of the character read cast to unsigned char or a negative int (EOF) in case of error. Read the description for fgetc(), for instance.

pmg
In addition, in the example, the return value will be indeterminate since he is returning a local var.
Patrice Bernassola
Thanks so much!
Thai-Duong Nguyen
@Patrice: not really, the value of `c` is returned not `c` itself or its address. Problems with returning local variables happen when you return pointers to them.
pmg