2016-06-07 5 views
0

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

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() { 
    char operator[20]; 
    char valid_operator[4] = "+-*/"; 
    printf("Enter operator: "); 
    scanf("%s", operator); 
    printf("You entered: %s\n", operator); 
    while(strchr(valid_operator, (int)operator[0]) == NULL) { 
    printf("%s is not a valid operator. Enter +, -, /, or *: ", operator); 
    scanf("%s", operator); 
    } 

Код работает до настоящего момента. Эта следующая часть бросается в бесконечный цикл, если пользователь вводит ошибочный вход в первый раз. Повторного запроса никогда не происходит.

int input1; 
    int input2; 
    printf("Enter the two inputs (separated by whitespace): "); 
    int num_ints = 1; 
    num_ints = scanf("%d %d", &input1, &input2); 
    printf("Input 1: %d. Input 2: %d.\n", input1, input2); 
    while(num_ints < 2){ 
    printf("Invalid input. Enter two integers separated by whitespace: "); 
    num_ints = 0; 
    num_ints = scanf("%d %d", &input1, &input2); 
    printf("Input 1: %d. Input 2: %d.\n", input1, input2); 
    } 
    return 0; 
+0

Держу пари, это о .. новая строка –

+2

использовать fgets для чтения с клавиатуры, используйте sscanf, чтобы извлечь из строки –

+1

'strchr (valid_operator, ...)' не будет работать, потому что его определение отсутствует '\ 0' terminator, необходимый для строковых операций. Попробуйте 'char valid_operator [] =" + - */";' Поскольку вы ограничили свой размер '4', в массиве нет терминатора. –

ответ

0

Вам необходимо очистить stdin. Если вы вводите нецелое число в вашем примере «1 t», «t» не потребляется (осталось в потоке). Добавьте это в цикле:

while(num_ints < 2){ 
    while (fgetc(stdin) != '\n'); // clear input 
. . . 

См C program loops infinitely after scanf gets unexpected data для хорошего описания проблемы.

+0

ahh Я подозревал, что что-то подобное происходит. Это устраняет проблему. Я до сих пор не понимаю, почему в первом случае потребляется неправильный вход, но не во втором. –

1

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

Это согласуется с POSIX: http://pubs.opengroup.org/onlinepubs/009695399/functions/fscanf.html

если сравнение показывает, что они не эквивалентны, директива ослабеет, и отличаясь и последующие байты остаются непрочитанными.

Кроме того, возвращаемое значение из man scanf:

... возвращает количество входных элементов успешно подобранных и присвоенных, который может быть меньше, чем предусмотрено, или даже ноль в случае ранний сбой соответствия.

Итак, лучше сочетать fgets и sscanf.

do { 
    char buf[BUFSZ]; 
    printf("Enter the two inputs (separated by whitespace): "); 
    if(fgets(buf, BUFSZ, stdin) == NULL) 
    { 
     /* Error exit. */ 
     break; 
    } 
    num_ints = sscanf(buf, "%d %d", &input1, &input2); 
} while(num_ints != 2); 
+1

Результат 'fgets' должен быть проверен, но +1. –

+0

спасибо, добавил чек – fukanchik

Смежные вопросы