简体   繁体   中英

How to read input in C

I'm trying to read a line with scanf("%[^\\n]") ; right before it I'm reading an integer with "%d", was told to me that scanf doesn't erase the '\\n' after reading, so I have to call fflush() to avoid it, but even doing that 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 the scanf doesn't wait, it starts reading the input — doesn't matter what the integer value is, whether 5 or 10, the scanf reads all the strings to empty. Already tried with fgets and the result is almost the same, except that it reads some of the strings and skips others.

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:

  1. 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.
  2. 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 .
  3. 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.

BLUEPIXY in the comment answered my question:

try "%[^\\n]" change to " %[^\\n]"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM