tags:

views:

189

answers:

4

I have this but once it reaches the supposed EOF it just repeats the loop and scanf again.

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

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

        return 0;
}
A: 

You need to check the return value against EOF, not against 1.

Note that in your example, you also used two different variable names, words and word, only declared words, and didn't declare its length, which should be 16 to fit the 15 characters read in plus a NUL character.

Brian Campbell
+1  A: 

Try:

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

You need to compare scanf output with EOF

Since you are specifying a width of 15 in the format string, you'll read at most 15 char. So the words char array should be of size 16 ( 15 +1 for null char). So declare it as:

char words[16];
codaddict
This is NOT right. scanf returns the number of input fields successfully scanned, NEVER EOF (-1). Therefore your while loop is redundant, it will break at first time.
@user411313 no, scanf can return EOF , as he's comparing using != it won't break the first time. However, in the general case, you'd want the number of assigned items as well so you can do some validation.
nos
@user411313: Both [man scanf](http://www.google.com/search?q=man+scanf) and C99 §7.19.6.2/16 say it can return EOF.
Roger Pate
This produces the same output,[I am a sentence][I][am][a][sentence]then scanf starts again... which I want it to break here.
A: 

Scanf is pretty much always more trouble than it's worth. Here are two better ways to do what you're trying to do. This first one is a more-or-less direct translation of your code. It's longer, but you can look at it and see clearly what it does, unlike with 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;
}

And here's another version. It's a little harder to see what this does by inspection, but it does not break if a line is longer than 1024 characters, so it's the code I would use in production. (Well, really what I would use in production is tr -s '[:space:]' '\n', but this is how you implement something like that.)

#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;
}
Zack
Yeah, that's *much* simpler than `for (char buf[1024]; scanf("%1023s", buf) == 1;) printf("%s\n", buf);`, except you changed the behavior in certain cases of leading, trailing, and adjacent whitespace.
Roger Pate
In real life I would write a loop over individual characters with exactly the whitespace behavior I wanted (which might or might not be what the OP wanted - they didn't say), but that would be much too tedious for an example. If you're using scanf you must not care about edge case behavior or error recovery, anyway.
Zack
... you know what, it's *not* much too tedious. Rewrote example.
Zack
Your new example is better, but isn't it now exactly equivalent to my one line of code above? And if so, why replace one line (or two, more likely) with 15 lines?
Roger Pate
Well, mainly because I *know* that my 15 lines of code does exactly what I want, whereas I do not trust scanf *ever* to do what I want. There are just too many weird corner cases of its behavior, especially when error handling is involved.
Zack
-1 this code is *much* less clear than using scanf.
Chris Dodd
You come back here and say that after you've had to debug a complicated scanf-based parser that couldn't handle even slightly malformed input. :-P
Zack
I've done that -- if it gets too complex for scanf to handle, you're generally better off going to an actual parser like flex+bison or antlr
Chris Dodd
A: 

Your code loops until it reads a single word, then exits. So if you give it multiple words it will read the first and exit, while if you give it an empty input, it will loop forever. In any case, it will only print random garbage from uninitialized memory. This is apparently not what you want, but what do you want? If you just want to read and print the first word (if it exists), use if:

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

If you want to loop as long as you can read a word, use while:

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

Also, as others have noted, you need to give the word array a size that is big enough for your scanf:

char word[16];

Others have suggested testing for EOF instead of checking how many items scanf matched. That's fine for this case, where scanf can't fail to match unless there's an EOF, but is not so good in other cases (such as trying to read integers), where scanf might match nothing without reaching EOF (if the input isn't a number) and return 0.

edit

Looks like you changed your question to match my code which works fine when I run it -- loops reading words until EOF is reached and then exits. So something else is going on with your code, perhaps related to how you are feeding it input as suggested by David

Chris Dodd
Hey thanks for the reply, but did you try this? I realized I put "!=" on my original post but I meant ==, and this is giving me what I want where I type a sentence when the scanf is called, then it loops and prints out the words like it is supposed too, then it calls the scanf again which I do not want. It calls it leaving me with no way to break out of the loop. Maybe my compiler? but the only problem is after it prints all the words it doesn't break.
@user315903: That's why the best idea is to post the code that's not working, rather than try to type in something similar. If your code isn't working, for reasons you don't understand, then you don't understand what's wrong and can't trust yourself to preserve the essence of the problem.
David Thornley