Подтвердить что ты не робот

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.

Почему он это делает?

4b9b3361

Ответ 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" )