Остановка цикла while через EOF в C - PullRequest
0 голосов
/ 25 мая 2018

Я только изучаю C, и у меня возникла проблема с моим базовым пониманием.Я пытаюсь напечатать X столько раз, сколько введено.Все входные данные находятся на одной линии, и сейчас у меня это хорошо работает.

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

пример: вход 1 2 3

Выход:

X
XX
XXX

КОНЕЦ ПРОГРАММЫ

Прямо сейчас я нахожусь в цикле навсегда ...

Может кто-нибудь попытаться объяснить концепцию, которую я здесь упускаю?Я уверен, что это может быть синтаксис, но я действительно пытаюсь понять, где моя логика неверна.

Как работает EOF в этом случае?

    int main(void)

{

int i;

int n = 0;

while ( n  != EOF ) {

scanf( "%d",&n );

    if (n == EOF){

    break;

    }

        for ( i=0; i<n; i++){

        printf("X");
    }

    printf("\n");

}

}

1 Ответ

0 голосов
/ 25 мая 2018

Вы можете делать то, что вы пытаетесь сделать, но не так, как вы это делаете ...

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

  1. EOF возвращено - означает, что конец ввода был достигнут до того, как был обнаружен какой-либо ввод (это может быть вручную сгенерировано пользователем, нажав Ctrl + d (или Ctrl + z в окнах 1 ));

  2. меньше количества возвращаемых спецификаторов преобразованияуказывает на ошибку , соответствующую или input (когда это происходит, извлечение символов из потока прекращается, и you отвечает за удаление любых посторонних символов перед вашей следующей попыткой чтения);или

  3. возвращаемое значение равно количеству спецификаторов преобразования - указывает, что данные были преобразованы и сохранены в каждой предоставленной вами переменной;

Далее,Вы должны подтвердить, что полученные данные находятся в допустимом диапазоне.(Вы, вероятно, не хотите вводить отрицательных значений.

Для своего кода вы можете просто проверить (3) выше и выйти на EOF или , соответствующем или input fail - потому что вы читаете данные только 1-го типа (integers) и можете выйти при любом сбое.

Но это не решит вашу проблему. Правильноспособ решения этой проблемы - чтение строки данных за раз (с fgets или POSIX getline), а затем синтаксический анализ каждого целого значения из строки данных путем повторных обращений к strtol и использование его endptr параметр, чтобы пройти весь путь вниз (есть много примеров на SO о его правильном использовании)

Однако вы также можете делать то, что хотите, просто проверяя следующий символ после того, как прочитаете каждыйint с getchar() и если это '\n', то ваше чтение завершено, в противном случае вам нужно вернуть символ в stdin, используя ungetc, и проверка возврата была выполнена успешночем? (подсказка: проверка возврата - возврат каждой функции C-библиотеки четко описан в ней связанной man page - используйте их :)

В целом, вы можете сделать что-то вроде:

#include <stdio.h>

int main (void) {

    int i, n;

    printf ("input: ");

    while (scanf ("%d", &n) == 1) { /* validate the 'return' of scanf */
        if (n < 0) {    /* validate n not negative */
            fprintf (stderr, "error, input cannot be negative.\n");
            return 1;
        }
        for (i = 0; i < n; i++)     /* then loop that number of times   */
            putchar ('X');          /* don't printf 1-char, use putchar */
        putchar ('\n');             /* tidy up with newline */

        i = getchar();      /* read next char in stdin */
        if (i == '\n')      /* if end of line - break (done) */
            break;
        else if (ungetc (i, stdin) != i) {  /* validate putting it back */
            fprintf (stderr, "error: putting char back in stdin.\n");
            return 1;
        }
    }

    return 0;
}

Пример использования / Вывод

$ ./bin/output_x
input: 1 2 3
X
XX
XXX

или

$ ./bin/output_x
input: 7 1 1 5 1 1 1
XXXXXXX
X
X
XXXXX
X
X
X

Просмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

Сноски

  1. Но см .: CTRL + Z не генерирует EOF в Windows 10
...