c中的sscanf函数用法

use*_*346 2 c scanf

我正在尝试xxxxxx(xxxxx)使用sscanf以下方法解析格式字符串:

sscanf(command, "%s(%s)", part1, part2)
Run Code Online (Sandbox Code Playgroud)

但似乎sscanf不支持这种格式,因此,part1实际上包含整个字符串.

任何人都有这方面的经验请分享...

谢谢

Jon*_*ler 7

将代码转换为程序:

#include <stdio.h>

int main(void)
{
    char part1[32];
    char part2[32];
    char command[32] = "xxxxx(yyyy)";
    int n;

    if ((n = sscanf(command, "%s(%s)", part1, part2)) != 2)
        printf("Problem! n = %d\n", n);
    else
        printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

运行时,它会产生' Problem! n = 1'.

这是因为第一个%s转换说明符跳过前导空格,然后扫描"非空白"字符直到下一个空格字符(或者,在本例中为字符串结尾).

您需要使用(否定的)字符类或扫描集来获得所需的结果:

#include <stdio.h>

int main(void)
{
    char part1[32];
    char part2[32];
    char command[32] = "xxxxx(yyyy)";
    int n;

    if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
        printf("Problem! n = %d\n", n);
    else
        printf("Part1 = <<%s>>; Part2 = <<%s>>\n", part1, part2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这会产生:

Part1 = <<xxxxx>>; Part2 = <<yyyy>>
Run Code Online (Sandbox Code Playgroud)

注意31的格式; 他们防止溢出.


我想知道%31是如何运作的.它是否有效%s并防止溢出或仅防止溢出?

使用给定的数据,这两行是等效的,并且足够安全:

    if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
    if ((n = sscanf(command, "%[^(](%[^)])", part1, part2)) != 2)
Run Code Online (Sandbox Code Playgroud)

%[...]表示法是转换规范; 也是%31[...].

C标准说:

每个转换规范由字符%引入.在%之后,以下顺序出现:

  • 可选的赋值抑制字符*.
  • 大于零的可选十进制整数,指定最大字段宽度(以字符为单位).
  • 一个可选的长度修饰符,用于指定接收对象的大小.
  • 转换说明符字符,指定要应用的转换类型.

31是(可选)最大字段宽度的示例.该[...]部分是一个扫描集,可能被视为s转换说明符的特例.的%s转换指定约等于%[^ \t\n].

31比字符串的长度少一个; 最后的空值不计入该长度.由于part1part2每个都是32的数组char,因此%31[^(]%31[^)]转换说明符可防止缓冲区溢出.如果第一个字符串之前超过31个字符,则(由于文字左括号不匹配,因此返回值为1.同样,第二个字符串将限制为31个字符,但您不能轻易判断它是否)在正确的位置.