Tomemos el siguiente programa:

# 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);
    }   
}

Ingresa un número: 2
Estado: 1. La suma actual es: 2. Ingrese otro número: 3
Estado: 1. La suma actual es: 5. Ingrese otro número: Estado: -1. La suma actual es: 8. Ingrese otro número: ^ C

Parece que Ctrl D (EOF) se reconoce como -1 pero Ctrl C jus hace que programa para salir. ¿Cómo se manejan normalmente estas dos secuencias de escape en C? ¿Y por qué scanf trata a ctrl-c y ctrl-d de manera diferente?

0
samuelbrody1249 23 ene. 2021 a las 08:55

1 respuesta

La mejor respuesta

La función scanf no trata estos caracteres de ninguna manera especial, ni siquiera ve esos caracteres. Lo que sucede es que el controlador de terminal (al menos en sistemas similares a UNIX (a) ) intercepta estas pulsaciones y las traduce en acciones especiales.

Para CTRL-d , cierra el archivo de entrada estándar para que cualquier código que lo lea obtenga un EOF; ese es el -1 que está viendo (lo que indica un error de algunos descripción en lectura).

Para CTRL-c , genera la señal SIGINT que, si no se detecta, terminará su programa.

Tenga en cuenta que estas son las combinaciones de teclas predeterminadas para esas acciones; se pueden cambiar con stty para usar otras diferentes. Los predeterminados (intr y eof) se muestran a continuación (^C y ^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

Y tenga en cuenta que esto probablemente no es lo que desea:

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

El ciclo solo saldrá cuando scanf devuelva cero, lo que sucederá si no se puede escanear un entero (como al ingresar el XYZZY no numérico). Continuará para cualquier valor distinto de cero, incluido el -1 que obtiene de nuevo en caso de error / final de archivo.

Un mejor bucle sería:

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

De hecho, dado que el ciclo solo debería alguna vez ejecutarse para un valor de estado de 1, tiene poco sentido usarlo (otro para una decisión final sobre lo que sucedió). Preferiría algo como:

#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, desde la memoria y por el contrario, solo reconoce CTRL-z al comienzo de una línea (y seguido de ENTER ) como el indicador de fin de archivo.

2
paxdiablo 23 ene. 2021 a las 09:54