Чтение пользовательского ввода в массив до его максимального размера

Предположим, что max_size массива равен 100, я пытаюсь ввести scanf пользователя в массив до тех пор, пока не будет введен EOF. Когда функция обнаруживает EOF, scanf останавливается и возвращает количество введенных элементов.

int read_ints_from_stdin(int array[], int max_array_size) { 
    int i = 0, num;
    while ((scanf("%d", &num) != EOF) && i < max_array_size) {
        array[i++] = num;
        printf("value of i is: %d \n", i);
    }
    return i;
}

Однако i продолжает увеличиваться до max_array_size, и функция всегда возвращает 100, даже если я ввел EOF. Может ли кто-нибудь помочь мне в этом?

Редактировать: по-видимому, я храню случайные значения в своем массиве, а не то, что вводит пользователь.


person xiaozaiz    schedule 29.07.2020    source источник
comment
EOF определяется в stdio.h (обычно это -1). В Linux ctrl+d сигнализирует EOF, а в Windows это ctrl+z для стандартного ввода процесса через оболочку. ты сделал что-то из этого?   -  person nor    schedule 29.07.2020
comment
я на самом деле распечатал EOF в своей системе, и это дало мне -1. Итак, я использовал -1 как EOF в своих входах   -  person xiaozaiz    schedule 29.07.2020
comment
Я вошел в EOF Как? Что именно вы напечатали? Обратите внимание, что если вы введете не число, scanf вернет 0 и оставит неверный символ в потоке, поэтому он никогда не вернет EOF. Я предлагаю == 1 вместо != EOF здесь.   -  person n. 1.8e9-where's-my-share m.    schedule 29.07.2020


Ответы (2)


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

Если вы хотите убедиться, что то, что вы делаете, имеет смысл, взгляните на scanf справочная страница:

RETURN VALUE
   On success, these functions return the number of input items
   successfully matched and assigned; this can be fewer than provided
   for, or even zero, in the event of an early matching failure.

   The value EOF is returned if the end of input is reached before
   either the first successful conversion or a matching failure occurs.
   EOF is also returned if a read error occurs, in which case the error
   indicator for the stream (see ferror(3)) is set, and errno is set to
   indicate the error.

Читая выше, становится ясно, что scanf не только возвращает EOF при достижении конца файла. Кроме того, scanf может возвращать 0, если ошибки не произошло, но совпадения не произошло, и в этом случае также следует прекратить чтение.

Что вы хотите сделать в этом случае, так это использовать простой цикл for и проверить, вернул ли scanf 1, что является единственным приемлемым для вас значением. Если нет, то либо достигнут конец файла, либо произошла ошибка, либо ввод не соответствует строке формата: проверьте ошибку и действуйте соответственно. Не сжимайте всю логику проверки ошибок внутри условия while, это просто сбивает с толку и трудно понять правильно.

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

size_t read_ints_from_stdin(int array[], size_t max_array_size) { 
    size_t i;

    for (i = 0; i < max_array_size; i++) {
        int res = scanf("%d", &array[i]);
        
        if (res != 1) {
            if (res == EOF) {
                if (feof(stdin)) {
                    // End of file reached, not an error.
                } else {
                    // Real error, print that out to stderr.
                    perror("scanf failed"); 
                }
            } else {
                // Input matching failure.
                fputs("Input does not match requested format.\n", stderr);
            }
            
            break;
        }
    }
    
    return i;
}

Также обратите внимание на использование size_t там, где это необходимо, вместо int. Вы не хотите, чтобы в конечном итоге возникали ошибки, возникающие из-за отрицательных значений при работе с размерами или индексами.

person Marco Bonelli    schedule 29.07.2020

Вам нужно изменить условие цикла while примерно так:

int read_ints_from_stdin(int array[], int max_array_size) { 
    int i = 0, num;
    while ( i < max_array_size) {
        scanf("%d", &num);
        if(num == EOF) break;
        array[i++] = num;
        printf("value of i is: %d \n", i);
    }
    return i;
}

Вы должны сравнить значение числа с EOF, но не значение, возвращаемое scanf. Это связано с тем, что scanf возвращает количество назначенных успешных входов. В вашем коде на каждой итерации scanf всегда возвращает 1 (поскольку значение присваивается num), которое позже сравнивается с EOF (который расширяется до -1)

person Sai Raman Kilambi    schedule 29.07.2020