0

我使用以下scanf()语句读取了带有空格的字符串。

scanf("%[^\n]", &stringVariableName);

控制字符串的含义是什么[^\n]

可以这样读取带有空格的字符串吗?

4

5 回答 5

5

这意味着“阅读任何内容,直到找到'\n'”

这没关系,但最好这样做“读取任何内容,直到找到'\n',或者读取比我的缓冲区支持更多的字符”

char stringVariableName[256] = {}
if (scanf("%255[^\n]", stringVariableName) == 1)
    ...

编辑:从参数中删除 & ,并检查 scanf 的结果。

于 2013-04-24T20:25:18.140 回答
4

格式说明符"%[^\n]"指示scanf()最多读取但不包括换行符。从链接的参考页面:

    匹配字符集中的非空字符序列。

如果集合的第一个字符是 ^,那么所有字符都不是
在集合中匹配。如果集合以 ] 或 ^] 开头,则 ]
字符也包含在集合中。

如果字符串在单行上,则是另一种选择,但在将其写入输出缓冲区时fgets()必须删除换行符。还强制程序员指定可以读入缓冲区的最大字符数,从而降低发生缓冲区溢出的可能性:fgets()fgets()

char buffer[1024];
if (fgets(buffer, 1024, stdin))
{
    /* Remove newline. */
    char* nl = strrchr(buffer, '\n');
    if (nl) *nl = '\0';
}

可以通过以下方式指定要读取的最大字符数scanf()

scanf("%1023[^\n]", buffer);

但是不可能忘记这样做,fgets()因为编译器会抱怨。虽然,当然,程序员可以指定错误的大小,但至少他们被迫考虑它。

于 2013-04-24T20:22:44.550 回答
2

从技术上讲,这不能很好地定义。

匹配一组预期字符(扫描集)中的非空字符序列。

如果不存在 l 长度修饰符,则相应的参数应是指向字符数组的初始元素的指针,该元素数组的大小足以接受序列和终止空字符,它将自动添加。

假设stringVariableName看起来像的声明char stringVariableName[x];,那么&stringVariableName是 a char (*)[x];,而不是 a char *。类型不对。行为未定义。它可能是巧合,但任何依赖巧合的东西都不适用于我的定义。

形成char *using的唯一方法&stringVariableName是 if stringVariableNameis a char!这意味着字符数组仅大到足以接受终止空字符。如果用户在按下回车键之前输入了一个或多个字符,scanf 将写入字符数组的末尾并调用未定义的行为。如果用户只是按回车键,该%[...]指令将失败,甚至'\0'不会将 a 写入您的字符数组


现在,说了这么多,我假设你的意思是这样的:(scanf("%[^\n]", stringVariableName);注意省略的&符号

你真的应该检查返回值!

指令使 scanf 检索由方括号%[之间指定的字符组成的字符序列。集合开头的 A 表示所需的集合包含除括号之间的字符之外的所有字符。因此,告诉 scanf 尽可能多地读取非字符,并将它们存储到对应的 . 指向的数组中。[]^%[^\n]'\n'char *

'\n'未读。这可能会导致问题。空字段将导致匹配失败。在这种情况下,可能不会将任何数据复制到您的数组中(甚至不是终止'\0'字符)。出于这个原因(和其他原因),您确实需要检查返回值

哪本手册包含有关 scanf 的返回值的信息?scanf 手册

于 2013-04-24T20:40:49.230 回答
1

其他人已经解释了什么%[^\n]意思。

不是读取字符串的好方法。它与臭名昭著的 unsafe 一样危险gets,并且出于同样的原因:它不知道缓冲区的stringVariableName大小。

从文件中读取一整行的最佳方法是getline,但并非所有 C 库都有它。如果不这样做,您应该使用fgets,它知道缓冲区有多大,并注意您可能无法获得完整的行(如果该行对于缓冲区来说太长)。

于 2013-04-24T20:28:50.610 回答
0

从手册页中阅读scanf()...

[ 匹配指定的可接受字符集中的非空字符序列;next 指针必须是指向 char 的指针,并且必须有足够的空间容纳字符串中的所有字符,外加一个终止空字节。前导空白的通常跳过被抑制。字符串由特定集合中(或不在)中的字符组成;该集合由左括号 [ 字符和右括号 ] 字符之间的字符定义。如果左括号后的第一个字符是抑扬符 (^),则该集合排除这些字符。要在集合中包含右括号,请将其作为左括号或抑扬符之后的第一个字符;任何其他位置将结束该组。连字符 - 也很特殊;当放置在其他两个角色之间时,它将所有中间字符添加到集合中。要包含连字符,请将其设为最后一个右括号之前的最后一个字符。例如,[^]0-9-] 表示集合“除了右括号、0 到 9 和连字符之外的所有内容”。字符串以出现不在(或,带有抑扬符,in)集中的字符或字段宽度用完时结束。

简而言之, [^\n] 意味着从字符串中读取不是 a 的所有内容\n并将其存储在参数列表中的匹配指针中。

于 2013-04-24T20:22:59.037 回答