Как вы читаете scanf до EOF в C? - PullRequest
       19

Как вы читаете scanf до EOF в C?

30 голосов
/ 22 сентября 2010

У меня есть это, но как только он достигает предполагаемого EOF, он просто повторяет цикл и снова сканирует.

int main(void)
{
        char words[16];

        while(scanf("%15s", words) == 1)
           printf("%s\n", words);

        return 0;
}

Ответы [ 6 ]

20 голосов
/ 22 сентября 2010

Попробуйте:

while(scanf("%15s", words) != EOF)

Вам нужно сравнить scanf вывод с EOF

Поскольку вы указываете ширину 15 в строке формата, вы будете читать не более 15 символов. Таким образом, массив слов char должен иметь размер 16 (15 +1 для null char). Так объявите это как:

char words[16];
4 голосов
/ 22 сентября 2010

Scanf почти всегда доставляет больше хлопот, чем стоит.Вот два лучших способа сделать то, что вы пытаетесь сделать.Этот первый - более или менее прямой перевод вашего кода.Это длиннее, но вы можете посмотреть на него и ясно увидеть, что он делает, в отличие от scanf.

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    char buf[1024], *p, *q;
    while (fgets(buf, 1024, stdin))
    {
        p = buf;
        while (*p)
        {
            while (*p && isspace(*p)) p++;
            q = p;
            while (*q && !isspace(*q)) q++;
            *q = '\0';
            if (p != q)
                puts(p);
            p = q;
        }
    }
    return 0;
}

А вот еще одна версия.При осмотре немного сложнее увидеть, что это делает, но оно не прерывается, если строка длиннее 1024 символов, поэтому этот код я бы использовал в производстве.(Ну, на самом деле я бы использовал на производстве tr -s '[:space:]' '\n', но именно так вы реализуете что-то подобное.)

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    int ch, lastch = '\0';
    while ((ch = getchar()) != EOF)
    {
        if (!isspace(ch))
            putchar(ch);
        if (!isspace(lastch))
            putchar('\n');
        lastch = ch;
    }
    if (lastch != '\0' && !isspace(lastch))
        putchar('\n');
    return 0;
}
3 голосов
/ 22 сентября 2010

Ваш код зацикливается, пока не прочитает одно слово, а затем завершится. Так что, если вы дадите ему несколько слов, он прочитает первое и завершится, а если вы дадите ему пустой ввод, он зациклится навсегда. В любом случае, он будет печатать только случайный мусор из неинициализированной памяти. Это, видимо, не то, что вы хотите, но что вы хотите? Если вы просто хотите прочитать и напечатать первое слово (если оно существует), используйте if:

if (scanf("%15s", word) == 1)
    printf("%s\n", word);

Если вы хотите зациклить, пока можете прочитать слово, используйте while:

while (scanf("%15s", word) == 1)
    printf("%s\n", word);

Также, как уже отмечали другие, вам нужно дать массиву слов размер, достаточно большой для вашего scanf:

char word[16];

Другие предложили тестировать EOF вместо проверки того, сколько элементов соответствует scanf. Это хорошо для этого случая, когда scanf не может не соответствовать, если нет EOF, но не так хорош в других случаях (например, при попытке чтения целых чисел), где scanf может ничего не совпадать, не достигнув EOF (если input isn t число) и вернуть 0.

редактировать

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

0 голосов
/ 05 декабря 2013

Думаю, лучший способ сделать это ...

int main()
{
    char str[100];
    scanf("[^EOF]",str);
    printf("%s",str);
    return 0;     
}
0 голосов
/ 21 января 2013

Для пользователей C это также будет работать

while ( gets(str) != NULL )
0 голосов
/ 22 сентября 2010

Вам нужно проверить возвращаемое значение по EOF, а не по 1.

Обратите внимание, что в вашем примере вы также использовали два разных имени переменных, words и word, толькообъявляется words и не объявляется его длина, которая должна составлять 16, чтобы соответствовать 15 прочитанным символам плюс символ NUL.

...