Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Let's take the following program:

# include<stdio.h>
int main(void)
{
    int status, current_number, sum=0;
    printf("Enter a number: ");
    while(status=scanf("%d", &current_number)) {
        sum += current_number;
        printf("Status: %d. The current sum is: %d. Enter another number: ", status, sum);
    }   
}

Enter a number: 2
Status: 1. The current sum is: 2. Enter another number: 3
Status: 1. The current sum is: 5. Enter another number: Status: -1. The current sum is: 8. Enter another number: ^C

It seems that CtrlD (EOF) is recognized as -1 but CtrlC jus causes the program to quit. How are these two escape sequences usually handled in C? And why does scanf treat ctrl-c and ctrl-d differently?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
2.6k views
Welcome To Ask or Share your Answers For Others

1 Answer

The scanf function does not treat these character in any special way, it doesn't even see those characters. What happens is that the terminal driver (at least under UNIX-like systems(a)) intercepts these keystrokes and translates them to special actions.

For CTRL-d, it closes the standard input file so that any code reading it will get an EOF - that's the -1 you're seeing (indicating an error of some description on read).

For CTRL-c, it raises the SIGINT signal which, if uncaught, will terminate your program.

Keep in mind these are the default key-bindings for those actions, they can be changed with stty to use different ones. The default ones (intr and eof) are shown below (^C and ^D):

pax> stty -a
speed 38400 baud; rows 37; columns 145; line = 0;
intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

And keep in mind this is probably not what you want:

while(status=scanf("%d", &current_number)) {

The loop will only exit when scanf returns zero, which will happen if an integer cannot be scanned (such as by entering the non-numeric XYZZY). It will continue for any non-zero value, including the -1 you get back on error/end-of-file.

A better loop would be:

while((status = scanf("%d", &current_number)) == 1) {

In fact, since the loop should only ever run for a status value of 1, it makes little sense to use it (other for a final decision on what happened). I'd prefer something like:

#include<stdio.h>
int main(void) {
    int stat, curr, sum = 0;
    printf("Enter a number: ");
    while ((stat = scanf("%d", &curr)) == 1) {
        sum += curr;
        printf("Entered %d, sum is %d, enter another number: ", curr, sum);
    }
    if (stat == -1) {
        prinf("
End of file or I/O error.
");
    } else {
        prinf("Non-numeric data.
");
    }
}

(a) Windows, from memory and by contrast, only recognises CTRL-z at the start of a line (and followed by ENTER) as the end-of-file indicator.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...