How to read input in C
I am trying to read a line from scanf("%[^\n]")
; right before that I read an integer with "% d", I was told that scanf does not erase "\ n" after reading, so I need to call fflush () to avoid it, but even doing this I still have the same problems, so here is my code:
scanf("%d", &n);
fflush(stdin);
lines = (char**)malloc(sizeof(char*)*n);
for(i = 0; i < n; i++){
lines[i] = (char*)malloc(sizeof(char)*1001);
}
for(i = 0;i < n;i++){
scanf("%[^\n]", linhes[i]);
}
I read an integer and then scanf didn't wait, it starts reading the input - it doesn't matter what the integer value is, no matter 5 or 10, scanf reads all lines to empty. Already tried with fgets and the result is pretty much the same except that it reads some lines and skips others.
source to share
Let's take a look at this step by step:
"... read the line with scanf ("% [^ \ n] ");".
scanf("%[^\n]", buf)
does not read the line. It is almost always - sometimes. "%[^\n]"
directs scanf()
to read any number '\n'
char
until it is encountered (which '\n'
then goes back to stdin
) or an EOF occurs.
This approach has some problems:
- If the first
char
is equal'\n'
,scanf()
puts it back instdin
, without changing itbuf
in any way!buf
remains as is - possibly uninitialized .scanf()
then returns 0. - If at least one is not read
'\n'
, it is stored inbuf
or morechar
until it happens'\n'
. A is'\0'
added tobuf
, and'\n'
returned back tostdin
, andscanf()
returns 1. This unlimited number can easily overflowbuf
. If not savedchar
andEOF
or input error,scanf()
returnsEOF
. - Always check the return value
scanf()
/fgets()
etc. functions . If your code does not validate it, the state isbuf
unknown.
In any case, a '\n'
still remains in stdin
, so the line was not fully read. This is '\n'
often a problem for the next input function.
... scanf does not remove '\ n' after reading
Another common misconception. scanf()
reads a '\n'
, or not, depending on the supplied format. Some formats are consuming '\n'
, others are not.
... call fflush () to avoid this
fflush(stdin)
is well defined in some compilers, but not in the C standard. A common problem is that the code wants to delete any leftover data in the stdin
. A common alternative, when the end of the line hasn't been there yet, is to read and delete until found '\n'
:
int ch; // Use int
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);
I still have the same problems
The best solution, IMO, is to read the user's input line 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 the buffer be about 2x the size of expected input for typical code. The reliable code, not this snippet, will determine whether more line needs to be read. IMO, such excessively long lines are most often a sign of hackers and not legitimate use.
source to share