C编程语言(scanf)

时间:2013-04-24 20:20:55

标签: c whitespace scanf

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

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

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

是否可以像这样读取带有空白区域的字符串?

5 个答案:

答案 0 :(得分:5)

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

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

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

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

答案 1 :(得分:4)

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

    matches a non-empty sequence of character from set of characters. 

If the first character of the set is ^, then all characters not
in the set are matched. If the set begins with ] or ^] then the ]
character is also included into the set. 

如果字符串在一行上,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()做这件事,因为编译器会抱怨。当然,程序员当然可以指定错误的大小,但至少他们不得不考虑它。

答案 2 :(得分:2)

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

  

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

     

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

假设stringVariableName的声明看起来像char stringVariableName[x];,那么&stringVariableName就是char (*)[x];,而不是char *。类型错了。行为未定义。 可能巧合地工作,但任何依赖巧合的东西都不能按照我的定义工作

使用char *形成&stringVariableName的唯一方法是stringVariableName字符!这意味着字符数组仅足以接受终止空字符。如果用户在按Enter键之前输入一个或多个字符,则scanf将写入超出字符数组的末尾并调用未定义的行为。如果用户只按Enter键,%[...]指令将失败,即使'\0'也不会写入字符数组


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

你真的应该检查返回值!!

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

'\n'将保持未读状态。这可能会导致问题。空字段将导致匹配失败。在这种情况下, no data 可能会被复制到您的阵列中(甚至不会终止'\0'个字符)。出于这个原因(和其他人),你真的需要检查返回值

哪个手册包含有关scanf返回值的信息? The scanf manual

答案 3 :(得分:0)

阅读scanf() ...

的手册页
  

[匹配来自的非空字符序列   指定的接受字符集;下一个指针必须是a   指向char的指针,并且必须有足够的空间容纳所有字符   在字符串中,加上一个终止空字节。通常的跳过   领先的白色空间被压制。字符串由。组成   特定集合中的字符(或不存在);该集由定义   开括号[字符和近括号]之间的字符   字符。如果第一个字符,该集合将排除这些字符   在开括号之后是一个回旋(^)。包括收盘价   在集合中的括号,使其成为打开括号后的第一个字符   或旋风;任何其他位置将结束该集。连字符   性格 - 也很特别;放在另外两个之间   字符,它将所有插入的字符添加到集合中。至   包含一个连字符,使其成为最终结束前的最后一个字符   托架。例如,[^] 0-9-]表示集合“除了之外的所有内容   关闭括号,从零到九,连字符“。字符串以。结尾   一个角色的外观不在(或者,有一个   在设置或当字段宽度用完时,使用抑制旋转。

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

答案 4 :(得分:0)

其他人已经解释了%[^\n]的含义。

这是 一种读取字符串的好方法。它和臭名昭着的不安全gets一样危险,并且出于同样的原因:它不知道stringVariableName的缓冲区有多大。

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