Let us look at this step by step:
"... read a line with scanf("%[^\n]");".
scanf("%[^\n]", buf)
does not read a line. It almost does - sometimes. "%[^\n]"
directs scanf()
to read any number of non-'\n'
char
until one is encountered (that '\n'
is then put back into stdin
) or EOF occurs.
This approach has some problems:
- If the first
char
is '\n'
, scanf()
puts it back into stdin
without changing buf
in anyway! buf
is left as is - perhaps uninitialized. scanf()
then returns 0.
- If at least one non-
'\n'
is read, it is saved into buf
and more char
until a '\n'
occurs. A '\0'
is appended to buf
and the '\n'
is put back into stdin
and scanf()
returns 1. This unlimited-ness can easily overfill buf
. If no char
was saved and EOF
or input error occurs, scanf()
returns EOF
.
- Always check the return value of
scanf()
/fgets()
, etc. functions. If your code does not check it, the state of buf
is unknown.
In any case, a '\n'
is still usually left in stdin
, thus the line was not fully read. This '\n'
often is an issue for the next input function.
... scanf doesn't erase the '\n' after reading
Another common misconception. scanf()
reads a '\n'
, or not, depending on the supplied format. Some formats consume '\n'
, others do not.
... call fflush() to avoid it
fflush(stdin)
is well defined in some compilers but is not in the C standard. The usual problem is code wants to eliminate any remaining data in stdin
. A common alternative, when the end of the line had not yet occurred, is to read and dispose until '\n'
is found:
int ch; // Use int
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);
I still have the same problems
The best solution, IMO, is to read a line of user input and then scan it.
char buf[sizeof lines[i]];
if (fgets(buf, sizeof buf, stdin) == NULL) return NoMoreInput();
// If desired, remove a _potential_ trailing \n
buf[strcspn(buf, "\n")] = 0;
strcpy(lines[i], buf);
I recommend that a buffer should be about 2x the size of expected input for typical code. Robust code, not this snippet, would detect if more of the line needs to be read. IMO, such excessively long lines are more often a sign of hackers and not legitimate use.