C: Несколько scanf, когда я ввожу значение для одного scanf, он пропускает второй scanf
У меня есть этот блок кода (функции опущены, поскольку логика является частью домашнего задания):
#include <stdio.h>
int main()
{
char c = 'q';
int size;
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("Length:");
scanf("%d",&size);
while(c!='q')
{
switch(c)
{
case 'l': line(size); break;
case 's': square(size); break;
case 't': triangle(size); break;
}
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("\nLength:");
scanf("%d",&size);
}
return 0;
}
Первые два Scanf работают отлично, без проблем, когда мы попадаем в цикл while. У меня проблема, когда, когда вам предлагается ввести новую форму char, вместо этого она переходит в printf
длины и ждет ввода оттуда для char, а затем десятичного числа на следующей итерации цикла.
Итерация прелопа:
Scanf: Shape. Работает отлично
Scanf: длина. Нет проблем
Петля 1.
Scanf: Shape. Пропуски через это
Scanf: длина. Проблема, этот scanf отображает форму char.
Loop 2
Scanf: Shape. Пропуски через это
Scanf: длина. Проблема, этот scanf теперь сопоставляется с размером int.
Почему он это делает?
Ответы
Ответ 1
scanf("%c")
читает символ новой строки из клавиши ENTER.
Когда вы наберете let say 15
, введите a 1
, a 5
и нажмите клавишу ENTER. Таким образом, во входном буфере есть три символа. scanf("%d")
читает 1
и 5
, интерпретируя их как число 15
, но символ новой строки все еще находится во входном буфере. scanf("%c")
немедленно прочитает этот символ новой строки, и программа затем перейдет к следующему scanf("%d")
и дождитесь, пока вы введете номер.
Обычный совет - прочитать целые строки ввода с помощью fgets
и интерпретировать содержимое каждой строки на отдельном шаге. Более простым решением вашей непосредственной проблемы является добавление getchar()
после каждого scanf("%d")
.
Ответ 2
Основная проблема заключается в том, что scanf()
оставляет новую строку после номера в буфере, а затем читает ее с помощью %c
на следующем проходе. На самом деле, это хорошая демонстрация того, почему я не использую scanf()
; Я использую линейный ридер (fgets()
, например) и sscanf()
. Это легче контролировать.
Возможно, вы можете спасти его, используя " %c"
вместо "%c"
для строки формата. Заготовка приводит к тому, что scanf()
пропускает пробел (включая символы новой строки) перед чтением символа.
Но в долгосрочной перспективе будет проще отказаться от scanf()
и fscanf()
и использовать fgets()
или эквивалентный плюс sscanf()
. Все остальное, отчет об ошибках намного проще, если у вас есть целая строка для работы, а не данные, оставшиеся после scanf()
после его отказа.
Вы также должны всегда проверять, что вы получили значение, преобразованное из scanf()
. Вход не работает; обычно и ужасно. Не позволяйте этому разрушать вашу программу, потому что вы не проверяли.
Ответ 3
Используйте функцию
void fflushstdin( void )
{
int c;
while( (c = fgetc( stdin )) != EOF && c != '\n' );
}
чтобы очистить входной буфер.
Ответ 4
Попробуйте добавить пространство в scanf.
scanf(" %d", &var);
// ^
// there
Это приведет к тому, что scanf()
отбросит все пробелы перед сопоставлением целого числа.
Ответ 5
Когда вы вводите форму и ENTER, форма потребляется первым scanf, но ENTER не является! Второй scanf ожидает число так, ENTER пропускается, потому что считается пробелом, а scanf ожидает действительного ввода (числа), который, опять же, заканчивается нажатием ENTER. Ну, количество потребляется, но ENTER не так, поэтому первый scanf внутри него использует его, и ваше приглашение формы пропускается... этот процесс повторяется. Вы должны добавить еще один% c в scanfs, чтобы иметь дело с клавишей ENTER. Надеюсь, это поможет!
Ответ 6
Символ '\n'
по-прежнему остается во входном потоке после завершения первого вызова scanf
, поэтому второй вызов scanf()
читает его. Используйте getchar()
.
Ответ 7
Вы также можете использовать
scanf("%c%*c", &c);
для чтения двух символов и игнорирования последнего (в этом случае "\n" )