2010-09-21 2 views
26

У меня есть это, но как только он достигает предполагаемого EOF, он снова повторяет цикл и scanf.Как вы читаете scanf, пока EOF в C?

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

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

     return 0; 
} 
+0

Какой ввод вы используете? Вы перенаправляете файл на 'stdin' или печатаете на консоли? Если последний, какую ОС вы используете и как вы печатаете в EOF? –

ответ

0

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

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

14

Try:

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

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

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

char words[16]; 
+3

Это НЕ. scanf возвращает количество успешно проверенных полей ввода, NEVER EOF (-1). Поэтому ваш цикл while является избыточным, он будет прерываться в первый раз. – user411313

+2

@ user411313 no, scanf может вернуть EOF, поскольку он сравнивает использование! = Он не будет ломаться в первый раз. Однако в общем случае вам нужно также количество назначенных элементов, чтобы вы могли выполнить некоторую проверку. – nos

+1

@ user411313: И [man scanf] (http://www.google.com/search?q=man+scanf) и C99 §7.19.6.2/16 говорят, что он может вернуть EOF. – 2010-09-22 06:01:51

3

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; 
} 
+0

Да, это * много * проще, чем 'for (char buf [1024]; scanf ("% 1023s ", buf) == 1;) printf ("% s \ n ", buf);', за исключением того, поведение в некоторых случаях ведущего, конечного и смежного пробелов. – 2010-09-21 20:30:31

+0

В реальной жизни я бы написал цикл над отдельными символами именно с тем, что я хотел (что могло или не могло быть то, что хотел OP), но это было бы слишком утомительно для примера. Если вы используете scanf, вы все равно не должны заботиться о поведении кейсов или об устранении ошибок. – zwol

+0

... вы знаете, что это, но не слишком утомительно. Повторите пример. – zwol

3

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

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

Если вы хотите, чтобы цикл до тех пор, как вы можете прочитать слово, использовать во время:

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

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

char word[16]; 

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

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

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

+0

Привет, спасибо за ответ, но вы попробовали это? Я понял, что я положил «! =» На мой оригинальный пост, но я имел в виду ==, и это дает мне то, что я хочу, когда я печатаю предложение при вызове scanf, затем он петли и печатает слова, как это предполагается , то он снова вызывает scanf, который я не хочу. Это называет это, оставляя меня без возможности вырваться из цикла. Может быть, мой компилятор? но единственная проблема заключается в том, что он печатает все слова, которые он не сломал. – JJRhythm

+2

@ user315903: Вот почему лучшая идея - опубликовать код, который не работает, а не пытаться ввести что-то подобное. Если ваш код не работает, по причинам, которые вы не понимаете, тогда вы не понимаете, что не так, и не можете доверять себе, чтобы сохранить суть проблемы. –

-3

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

while (gets(str) != NULL) 
+9

-1 Для использования 'gets'. –

+2

Чтобы быть ясным, проблема с 'gets' заключается в том, что он может писать за пределами выделенного буфера. –

-2

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

int main() 
{ 
    char str[100]; 
    scanf("[^EOF]",str); 
    printf("%s",str); 
    return 0;  
} 
Смежные вопросы