为什么%[^ \ n] s在循环中不起作用?

时间:2015-08-07 04:16:27

标签: c string loops

我正在编写一个代码,在循环之间多次使用空格分隔的字符串输入。我看到%[^\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;
}

2 个答案:

答案 0 :(得分:6)

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

格式说明符%*c表示“只读取一个字符并将其丢弃”

所以组合

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

表示“读取字符串直到换行符,将字符串放入str指向的内存中,然后丢弃换行符

鉴于格式%[^\n]ss不是转化说明符的一部分。该格式表示“读取字符,直到找到换行符,然后下一个字符应为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中很难输入强大的字符串输入!