Scanf возвращает 0 без ожидания ввода

Я никогда не программировал в C и сегодня я должен написать небольшой код. Программа очень проста-я хочу добавить два целых числа.
Но когда я пытаюсь проверить, является ли данный вход числом, и первый scanf возвращает 0,второй тоже возвращает 0, не дожидаясь ввода.
Код:

int main()
{
    int a = 0;
    int b = 0;
    printf("Number a:n");
    if (scanf("%d", &a) != 1)
    {
        printf("Not a number. a=0!n");
        a = 0;
    }
    printf("Number b:n");
    if (scanf("%d", &b) != 1)
    {
        printf("Not a number. b=0!n");
        b = 0;
    }
    printf("%dn", a+b);
    return 0;
}

4 ответа

  1. Это происходит потому, что после первого scanf()сбоя, это, вероятно, из-за сбоя сопоставления, и вход, который вызвал сбой сопоставления, остается внутри входного буфера, ожидая, чтобы быть потребленным следующим вызовом.

    Таким образом, следующий вызов scanf()также пытается использовать тот же самый недопустимый вход, находящийся во входном буфере немедленно, не дожидаясь явного ввода внешнего пользователя, поскольку входной буфер не пуст.

    Решение: после первого сбоя вводаscanf(), вы должны очистить входной буфер, для тривиального примера, что-то вроде while (getchar() != '\n');должно сделать работу.

  2. Это связано с тем, что вход и выход не синхронизированы в C. программа может выводить некоторые строки после ввода пользователя, пока вход не был прочитан. Попробуйте запустить этот код:

    char token;
    
    scanf("%c", &token);
    printf("%c\n", token);
    printf("line 1\n");
    
    scanf("%c", &token);
    printf("%c\n", token);
    printf("line 2\n");
    
    scanf("%c", &token);
    printf("%c\n", token);
    printf("line 3\n");
    

    И input abc в одной строке.

    Вы можете представить себе, что есть две отдельные консоли, одна для ввода и другая для вывода.


    Например, вы хотите ввести asd for aи 3 for b. В этом случае первый scanfне найдет никакого числа и вернет 0. Но он также не будет ничего читать из ввода. Из-за этого второй scanfтоже увидит asd.

    Чтобы очистить вход, если aэто не число, вы должны ввести все оставшиеся символы в строке до '\n'(посмотрите на решение @Sourav)

  3. Входные данные, которые не удалось преобразовать в число для первогоfscanf(), все еще находятся в ожидании в буфере стандартных входных данных и вызывают fscanf()сбой второго. Попробуйте отбросить оскорбительные входные данные и повторно запросить пользователя:

    #include <stdio.h>
    
    int main(void) {
        int a = 0;
        int b = 0;
        int c;
        printf("Number a:\n");
        while (scanf("%d", &a) != 1) {
            printf("Not a number, try again:\n");
            while ((c = getchar()) != EOF && c != '\n')
                continue;
            if (c == EOF)
                exit(1);
        }
        printf("Number b:\n");
        while (scanf("%d", &b) != 1) {
            printf("Not a number, try again:\n");
            while ((c = getchar()) != EOF && c != '\n')
                continue;
            if (c == EOF)
                exit(1);
        }
        printf("%d\n", a + b);
        return 0;
    }
    

    Факторизация кода с помощью функции утилиты делает его более понятным:

    #include <stdio.h>
    
    int get_number(const char *prompt, int *valp) {
        printf("%s:\n", prompt);
        while (scanf("%d", valp) != 1) {
            printf("Not a number, try again:\n");
            while ((c = getchar()) != EOF && c != '\n')
                continue;
            if (c == EOF)
                return 0;
        }
        return 1;
    }
    
    int main(void) {
        int a, b;
    
        if (!get_number("Number a", &a) || !get_number("Number b", &b)) {
             return 1;
        }
        printf("%d\n", a + b);
        return 0;
    }
    
  4. Вы можете сделать то же самое, используя строки без проблем с scanf. Просто возьмите пользовательский ввод в виде строки и преобразуйте его в целое число. Затем преобразуйте строку обратно в целое число, чтобы проверить, совпадают ли они. Если они одинаковы, рассматривайте a и b как целые числа, если нет, делайте то, что вы делаете (вам нужно будет включить строку.ч.) Вот рабочий код:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
    int a;
    int b;
    char str1[100];
    char str2[100];
    
    printf("Number a:\n");  
    scanf("%s", &str1); //take input as a string
    a = atoi(str1); //convert string to integer
    snprintf(str2, 100, "%d", a); //convert integer back to string
    
    //if the integer converted to string is not the same as the string converted to integer
    if (strcmp(str1, str2)!= 0)
    {
    printf("Not a number. a=0!\n");
    a = 0;
    }
    printf("Number b:\n");
    scanf("%s", &str1);
    b = atoi(str1);
    snprintf(str2, 100, "%d", b);
    
    if (strcmp(str1, str2)!= 0)
    {
    printf("Not a number. b=0!\n");
    b = 0;
    }
    printf("%d\n", a+b);
    
    return(0);
    }