Вы можете делать то, что вы пытаетесь сделать, но не так, как вы это делаете ...
Для начала, вы всегда должны проверять возвращение scanf
.Необходимо защитить от трех случаев:
EOF
возвращено - означает, что конец ввода был достигнут до того, как был обнаружен какой-либо ввод (это может быть вручную сгенерировано пользователем, нажав Ctrl + d (или Ctrl + z в окнах 1 ));
меньше количества возвращаемых спецификаторов преобразованияуказывает на ошибку , соответствующую или input (когда это происходит, извлечение символов из потока прекращается, и you отвечает за удаление любых посторонних символов перед вашей следующей попыткой чтения);или
возвращаемое значение равно количеству спецификаторов преобразования - указывает, что данные были преобразованы и сохранены в каждой предоставленной вами переменной;
Далее,Вы должны подтвердить, что полученные данные находятся в допустимом диапазоне.(Вы, вероятно, не хотите вводить отрицательных значений.
Для своего кода вы можете просто проверить (3) выше и выйти на EOF
или , соответствующем или input fail - потому что вы читаете данные только 1-го типа (integers
) и можете выйти при любом сбое.
Но это не решит вашу проблему. Правильноспособ решения этой проблемы - чтение строки данных за раз (с fgets
или POSIX getline
), а затем синтаксический анализ каждого целого значения из строки данных путем повторных обращений к strtol
и использование его endptr
параметр, чтобы пройти весь путь вниз (есть много примеров на SO о его правильном использовании)
Однако вы также можете делать то, что хотите, просто проверяя следующий символ после того, как прочитаете каждыйint
с getchar()
и если это '\n'
, то ваше чтение завершено, в противном случае вам нужно вернуть символ в stdin
, используя ungetc
, и проверка возврата была выполнена успешночем? (подсказка: проверка возврата - возврат каждой функции C-библиотеки четко описан в ней связанной man page
- используйте их :)
В целом, вы можете сделать что-то вроде:
#include <stdio.h>
int main (void) {
int i, n;
printf ("input: ");
while (scanf ("%d", &n) == 1) { /* validate the 'return' of scanf */
if (n < 0) { /* validate n not negative */
fprintf (stderr, "error, input cannot be negative.\n");
return 1;
}
for (i = 0; i < n; i++) /* then loop that number of times */
putchar ('X'); /* don't printf 1-char, use putchar */
putchar ('\n'); /* tidy up with newline */
i = getchar(); /* read next char in stdin */
if (i == '\n') /* if end of line - break (done) */
break;
else if (ungetc (i, stdin) != i) { /* validate putting it back */
fprintf (stderr, "error: putting char back in stdin.\n");
return 1;
}
}
return 0;
}
Пример использования / Вывод
$ ./bin/output_x
input: 1 2 3
X
XX
XXX
или
$ ./bin/output_x
input: 7 1 1 5 1 1 1
XXXXXXX
X
X
XXXXX
X
X
X
Просмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.
Сноски
- Но см .: CTRL + Z не генерирует EOF в Windows 10