#c #escaping
#c #экранирование
Вопрос:
Давайте возьмем следующую программу:
# include<stdio.h>
int main(void)
{
int status, current_number, sum=0;
printf("Enter a number: ");
while(status=scanf("%d", amp;current_number)) {
sum = current_number;
printf("Status: %d. The current sum is: %d. Enter another number: ", status, sum);
}
}
Введите число: 2
Статус: 1. Текущая сумма составляет: 2. Введите другое число: 3
Статус: 1. Текущая сумма равна: 5. Введите другое число: Статус: -1. Текущая сумма равна: 8. Введите другое число: ^C
Кажется, что CtrlD(EOF) распознается как -1
, но CtrlCпросто приводит к завершению программы. Как эти две escape-последовательности обычно обрабатываются в C? А почему же scanf
лечат ctrl-c
и ctrl-d
по-разному?
Комментарии:
1. Зависит от терминала. Обычно
ctrl-d
отправляетEOF
символ иctrl-c
отправляетSIGINT
сигнал. Сигнальное действие по умолчаниюSIGINT
для завершения программы.
Ответ №1:
scanf
Функция не обрабатывает эти символы каким-либо особым образом, она даже не видит эти символы. Происходит то, что драйвер терминала (по крайней мере, в UNIX-подобных системах (a)) перехватывает эти нажатия клавиш и преобразует их в специальные действия.
Для CTRL-dэтого он закрывает стандартный входной файл, так что любой код, считывающий его, получит EOF
— это то, что -1
вы видите (указывает на ошибку некоторого описания при чтении).
Для CTRL-cэтого возникает SIGINT
сигнал, который, если он не будет перехвачен, завершит вашу программу.
Имейте в виду, что это привязки клавиш по умолчанию для этих действий, их можно изменить, stty
чтобы использовать другие. Значения по умолчанию ( intr
и eof
) показаны ниже ( ^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
И имейте в виду, что это, вероятно, не то, что вы хотите:
while(status=scanf("%d", amp;current_number)) {
Цикл завершится только тогда, когда scanf
вернет ноль, что произойдет, если целое число не может быть отсканировано (например, путем ввода нечислового XYZZY
). Это будет продолжаться для любого ненулевого значения, включая -1
возвращаемое значение error / end-of-file.
Лучшим циклом было бы:
while((status = scanf("%d", amp;current_number)) == 1) {
На самом деле, поскольку цикл должен выполняться только для значения состояния 1
, нет смысла его использовать (другое для окончательного решения о том, что произошло). Я бы предпочел что-то вроде:
#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", amp;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, из памяти и, напротив, распознает только CTRL-zначало строки (и за ней следуетENTER) в качестве индикатора конца файла.