我正在编写一个代码,在循环之间多次使用空格分隔的字符串输入。我看到%[^\n]s
在循环中没有工作但%[^\n]%*c
没有。我的问题是为什么%[^\n]s
不起作用。这是我的代码:
#include<stdio.h>
main(){
while(1){
char str[10];
scanf("%[^\n]s",str);
printf("%s\n",str);
}
return 0;
}
答案 0 :(得分:6)
格式说明符%[^\n]
表示“读取包含任何字符的字符串,直到找到换行符”。换行本身不会被消耗掉。找到换行符后,它将保留在输入流中以进行下一次转换。
格式说明符%*c
表示“只读取一个字符并将其丢弃”。
所以组合
scanf( "%[^\n]%*c", str );
表示“读取字符串直到换行符,将字符串放入str
指向的内存中,然后丢弃换行符。
鉴于格式%[^\n]s
,s
不是转化说明符的一部分。该格式表示“读取字符,直到找到换行符,然后下一个字符应为s
”。但下一个字符永远不会是s
,因为下一个字符将永远是换行符。因此,该格式的s
没有用处。
答案 1 :(得分:2)
%[^\n]
不会查找以空格分隔的字符串。它读取整行直到(但不包括)换行符。
如果您的行包含超过9个字符,则会因溢出缓冲区而导致未定义的行为。
可以通过编写%9[^\n]
来阻止缓冲区溢出,但是你有一个新问题:在更长的行上,%*c
将丢弃第10个字符,下一次扫描将继续从同一行读取
另一个复杂因素是,如果您的文件包含空行,则%[
会将其视为匹配失败。这意味着scanf
停止,因此不会继续处理%*c
。在这种情况下,不会消耗换行符,并且根本不会写入输出缓冲区。
您的代码也会进入无限循环,因为您永远不会突破while(1)
。
此代码显示正确使用^[
:
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);
}
如果您确实想要阅读以空格分隔的文字,那么您可以在我上面的示例中使用%9s
代替%9[^\n]
。这引入了一个新的差异:%s
跳过一个空行。
如果可以,那就没关系。如果你不想跳过空行,那么你可以使用我上面的代码,但最后添加:
char *p = strchr(str, ' ');
if ( p )
*p = '\0';
C中很难输入强大的字符串输入!