Защита от неверного ввода массива в цикле - PullRequest
0 голосов
/ 05 ноября 2018

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

У меня есть функция, которая загружает значения в двумерный массив с плавающей точкой.

void load_val(
                     float matrix[MAX_SIZE][MAX_SIZE],
                     const int line_num,
                     const int column_num
                     )
{
    for (int i=0; i<line_num; ++i)
    {
        printf("Give number\n");
        for (int j=0; j<column_num; ++j)
        {
            scanf("%f", &matrix[i][j]);
        }
    }

}

И, очевидно, когда пользователь вводит букву, программа заходит в бесконечный цикл. Я использовал два решения этой проблемы, и ни один не работал. Во-первых, используется тот факт, что scanf возвращает 0 при неправильном вводе.

Так что вместо

scanf("%f", &matrix[i][j]);

Я написал

while (scanf("%f", &matrix[i][j])==1);

Но это все равно дает мне бесконечный цикл.

Другое решение было просто использовать функцию "isdigit".

int h = scanf("%f", &matrix[i][j]);
            if (isdigit(h)==0)
            {
                puts("INVALID");
                j--;
            }

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

Я даже попробовал это

float h;
if (scanf("%f", &h)==1)
       {
          matrix[i][j]=h;
       }
else
       {
          puts("INVALID");
          j--;
       };

Еще - бесконечный цикл. Как я могу проверить правильность ввода в этом loop-inside-a-loop до того, как программа сойдет с ума? Может, проблема с типом float?

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

fscanf ()

Для каждого спецификатора преобразования, отличного от n, самая длинная последовательность входных символов, которая не превышает какой-либо заданной ширины поля и которая либо точно соответствует ожидаемому спецификатору преобразования, либо является префиксом последовательности, которую следует ожидать, это то, что потребляется из поток. Первый символ, если таковой имеется, после этой использованной последовательности остается непрочитанным. Если использованная последовательность имеет нулевую длину или если использованная последовательность не может быть преобразована, как указано выше, сбой сопоставления происходит, если в конце файла, ошибка кодирования или ошибка чтения препятствовали вводу из потока, в этом случае это сбой ввода.

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

Чтобы этого не происходило, вы можете читать и отбрасывать символы из входного потока, пока не встретите новую строку:

float value;
if(scanf("%f", value) != 1) {
    int ch;
    while((ch = getchar()) != EOF && ch != '\n');
}
0 голосов
/ 05 ноября 2018

Если scanf встречает байты, которые не соответствуют формату ввода, то эти байты просто останутся во входном потоке. Повторные вызовы scanf просто застрянут на тех же недопустимых символах. Если вы хотите обработать недопустимый ввод, лучше прочитать все доступные входные данные в буфер (например, используя fgets), а затем использовать sscanf в буфере, возможно, в цикле, чтобы вы могли перемещать указатель буфера за недопустимым вводом. Смотри https://stackoverflow.com/a/5969401/982257

0 голосов
/ 05 ноября 2018

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

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

И проверка того, что scanf (или sscanf) возвращает - это правильный способ проверить, успешно это или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...