简体   繁体   English

ctrl-d, ctrl-c 是如何被 C/scanf 处理的

[英]How ctrl-d, ctrl-c is handled by C/scanf

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输入一个数字:2
Status: 1. The current sum is: 2. Enter another number: 3状态:1.当前总和为:2.输入另一个数字:3
Status: 1. The current sum is: 5. Enter another number: Status: -1.状态:1。当前总和为:5。输入另一个数字:状态:-1。 The current sum is: 8. Enter another number: ^C当前总和为:8。输入另一个数字:^C

It seems that Ctrl D (EOF) is recognized as -1 but Ctrl C jus causes the program to quit.似乎Ctrl D (EOF) 被识别为-1Ctrl C jus 会导致程序退出。 How are these two escape sequences usually handled in C?这两个转义序列在 C 中通常是如何处理的? And why does scanf treat ctrl-c and ctrl-d differently?为什么scanf对待ctrl-cctrl-d方式不同?

The scanf function does not treat these character in any special way, it doesn't even see those characters. scanf function没有以任何特殊方式处理这些字符,甚至看不到这些字符。 What happens is that the terminal driver (at least under UNIX-like systems (a) ) intercepts these keystrokes and translates them to special actions.发生的情况是终端驱动程序(至少在类 UNIX 系统(a)下)截获这些击键并将它们转换为特殊操作。

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).对于CTRL-d ,它会关闭标准输入文件,以便任何读取它的代码都会得到一个EOF - 这就是您看到的-1 (表示读取时某些描述的错误)。

For CTRL-c , it raises the SIGINT signal which, if uncaught, will terminate your program.对于CTRL-c ,它会引发SIGINT信号,如果未被捕获,它将终止您的程序。

Keep in mind these are the default key-bindings for those actions, they can be changed with stty to use different ones.请记住,这些是这些操作的默认键绑定,可以使用stty更改它们以使用不同的键绑定。 The default ones ( intr and eof ) are shown below ( ^C and ^D ):默认值( intreof )如下所示( ^C^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 ).循环只会在scanf返回零时退出,如果无法扫描 integer (例如通过输入非数字XYZZY ),就会发生这种情况。 It will continue for any non-zero value, including the -1 you get back on error/end-of-file.对于任何非零值,它将继续,包括您在错误/文件结束时返回的-1

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).事实上,由于循环只应在状态值为1时运行,因此使用它几乎没有意义(其他用于最终决定发生的事情)。 I'd prefer something like:我更喜欢这样的东西:

#include<stdio.h>

int main(void) {
    int stat, curr, sum = 0;

    // Prompt and loop while user enters valid numbers.

    printf("Enter a number: ");
    while ((stat = scanf("%d", &curr)) == 1) {
        // Accumulate number to sum, output details and ask for next.

        sum += curr;
        printf("Entered %d, sum is %d, enter another number: ", curr, sum);
    }

    // Final status -1 if EOF/error, 0 if item couldn't be scanned.

    if (stat == -1) {
        prinf("\nEnd of file or I/O error.\n");
    } else {
        prinf("Non-numeric data.\n");
    }
}

(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. (a) Windows,来自 memory,相比之下,仅将行首的CTRL-z (后跟ENTER )识别为文件结束指示符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM