1

Задача:
Считать положительные вещественные числа в массив, вывести максимальный элемент и его номер.

Обработать ошибки ввода, т.е.
1)проверить, является ли введенный элемент числом;
2)проверить, является ли введенное число отрицательным.
Проблема: В интернете вычитал способ выявления неверно введенного типа

if (!scanf(...))

Применил его в программе, хотя очень сомневаюсь в правильности данного метода (код ниже), однако при вводе любого символа, отличного от числового, функция scanf перестает "работать", следующие значения попросту не считываются, и бесконечно выводится "Ошибка ввода" . В чем проблема? Использую встроенный в Xcode компилятор. Код программы:

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

int main(void) {
    int N, num;
    float max = 0;
    num = 0;

    printf("Введите количество элементов\n");
    scanf("%d", &N);

    float arr[N];

    printf("Введите элементы последовательности\n");
    for (int i = 0; i < N; i++)
    {
        if (!scanf("%f", &arr[i]))
        {
            printf("Ошибка ввода, повторите попытку\n");
            i--;
            continue;
        }

        if (arr[i] <= 0)
        {
            printf("Введено отлицательное значение, пожалуйста повторите ввод\n");
            i--;
            continue;
        }

        if (arr[i] > max)
        {
            max = arr[i];
            num = i + 1;
        }
    }

    printf("Максимальный элемент - %f, номер - %d\n", max, num);

    return 0;
}
Harry
  • 221,325
  • Можно вводить по %s как строку символов и преобразовывать функцией strtof (пожалуй, у нее больше возможностей для обработки ошибок) – avp Jul 04 '18 at 18:09

1 Answers1

1

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

Функция прекращает чтение на первом же символе, который не соответствует спецификатору. И опять же - чтение %d из, скажем, 25.12 будет корректным... но остановится на точке. И если вы захотите считать очередное целое число - то будет ошибка: точка в целом числе быть не может.

Поэтому после ошибки ввода лучше сбросить буфер чтения - все до конца строки, чтоб начать "с чистого листа", проигнорировав все введенное. например, так -

while(fgetc(stdin) != '\n');

(подробнее смотрите тут):

    if (!scanf("%f", &arr[i]))
    {
        printf("Ошибка ввода, повторите попытку\n");
        while(fgetc(stdin) != '\n');
        i--;
        continue;
    }

или

    if (!scanf("%f", &arr[i]))
    {
        printf("Ошибка ввода, повторите попытку\n");
        scanf("%*[^\n]");
        i--;
        continue;
    }
Harry
  • 221,325