为什么%[^ ]s 不能循环工作?

问题描述 投票:0回答:3

我正在编写一段代码,在循环之间多次采用空格分隔的字符串输入。我看到

%[^\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;
}
c string loops
3个回答
6
投票

格式说明符

%[^\n]
表示 “读取包含任何字符的字符串,直到找到换行符”。换行符本身不会被消耗。当找到换行符时,它将保留在输入流中以供下一次转换。

格式说明符

%*c
的意思是“精确读取一个字符并丢弃它”

所以组合

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

的意思是“读取一个字符串直到换行符,将字符串放入str

指向的内存中,然后丢弃换行符”
.


鉴于格式

%[^\n]s

s
 不是转换说明符的一部分。该格式表示“读取字符直到找到换行符,然后下一个字符应该是 
s
。但下一个字符永远不会是 
s
,因为下一个字符始终是换行符。因此,该格式中的
s
没有任何作用。
    


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 语言中稳健的字符串输入很困难!


-1
投票

© www.soinside.com 2019 - 2024. All rights reserved.