Why does% [^ \ n] s not work in a loop?

I wrote code to enter string input, separated by a space, for several loops between loops. I saw that %[^\n]s did not work in the loop, but %[^\n]%*c did. My question is why %[^\n]s not working. Here is my code:

 #include<stdio.h> main(){ while(1){ char str[10]; scanf("%[^\n]s",str); printf("%s\n",str); } return 0; } 
+4
source share
2 answers

The format specifier %[^\n] means "read a line containing any characters until a new line is found." The new line itself is not consumed. When a new line is found, it remains in the input stream for the next conversion.

The format specifier %*c means "read exactly one character and discard it."

So the combination

 scanf( "%[^\n]%*c", str ); 

means "read the line before the newline character, put the line in the memory pointed to by str , and then cancel the new line."


Given the format %[^\n]s , s not part of the conversion specifier. This format says "read the characters until a new line is found, and then the next character must be s ". But the next character will never be s , because the next character will always be a newline character. So s in this format has no purpose.

+6
source

%[^\n] does not search for lines separated by spaces. It reads the entire line before (but not including) a new line.

If your string contains more than 9 characters, this causes undefined behavior by overflowing the buffer.

Buffer overflows can be prevented by writing %9[^\n] , but then you have a new problem: on the longer line, %*c will drop the 10th character, and the next scan will continue reading from the same line.

Another complicating factor is that if your file contains an empty line, then %[ considers it inappropriate. This means that scanf stops, so it does not go to %*c processing. In this case, a new line is not consumed, and the output buffer is not written at all.

Your code also goes into an infinite loop, because you never exit while(1) .

This code shows the correct use of ^[ :

 while (1) { str[0] = '\0'; // In case of matching failure scanf("%9[^\n]", str); // read as much of the line as we can scanf("%*[^\n]"); // discard the rest of the line if ( getchar() == EOF ) // discard the newline break; // exit loop when we finished the input printf("%s\n", str); } 

If you really want to read text separated by spaces, you can use %9s instead of %9[^\n] in my example above. This makes a new difference: %s skips an empty line.

If it is OK, then it is OK. If you don't want to skip blank lines, you can use my code above, but add to the end:

 char *p = strchr(str, ' '); if ( p ) *p = '\0'; 

Reliable string input is difficult in C!

+2
source

All Articles