我正在编写一段代码,在循环之间多次采用空格分隔的字符串输入。我看到
%[^\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;
}
格式说明符
%[^\n]
表示 “读取包含任何字符的字符串,直到找到换行符”。换行符本身不会被消耗。当找到换行符时,它将保留在输入流中以供下一次转换。
格式说明符
%*c
的意思是“精确读取一个字符并丢弃它”。
所以组合
scanf( "%[^\n]%*c", str );
的意思是“读取一个字符串直到换行符,将字符串放入str
指向的内存中,然后丢弃换行符”.
%[^\n]s
,
s
不是转换说明符的一部分。该格式表示“读取字符直到找到换行符,然后下一个字符应该是
s
”。但下一个字符永远不会是
s
,因为下一个字符始终是换行符。因此,该格式中的 s
没有任何作用。%[^\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 语言中稳健的字符串输入很困难!