How to read from input until newline is found using scanf()?

brunoais picture brunoais · Nov 11, 2011 · Viewed 126.5k times · Source

I was asked to do a work in C when I'm supposed to read from input until there's a space and then until the user presses enter. If I do this:

scanf("%2000s %2000s", a, b);

It will follow the 1st rule but not the 2nd.
If I write:

I am smart

What I get is equivalent to:
a = "I";
b = "am";
But It should be:
a = "I";
b = "am smart";

I already tried:

scanf("%2000s %2000[^\n]\n", a, b);

and

scanf("%2000s %2000[^\0]\0", a, b);

In the 1st one, it waits for the user to press Ctrl+D (to send EOF) and that's not what I want. In the 2nd one, it won't compile. According to the compiler:

warning: no closing ‘]’ for ‘%[’ format

Any good way to solve this?

Answer

Jerry Coffin picture Jerry Coffin · Nov 11, 2011

scanf (and cousins) have one slightly strange characteristic: white space in (most placed in) the format string matches an arbitrary amount of white space in the input. As it happens, at least in the default "C" locale, a new-line is classified as white space.

This means the trailing '\n' is trying to match not only a new-line, but any succeeding white-space as well. It won't be considered matched until you signal the end of the input, or else enter some non-white space character.

One way to deal with that is something like this:

scanf("%2000s %2000[^\n]%c", a, b, c);

if (c=='\n')
    // we read the whole line
else
    // the rest of the line was more than 2000 characters long. `c` contains a 
    // character from the input, and there's potentially more after that as well.

Depending on the situation, you might also want to check the return value from scanf, which tells you the number of conversions that were successful. In this case, you'd be looking for 3 to indicate that all the conversions were successful.