2

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

sscanf(command, "%s(%s)", part1, part2)

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

谁有这方面的经验请分享...

谢谢

4

3 回答 3

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;
}

运行时,它会产生' 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;
}

这会产生:

Part1 = <<xxxxx>>; Part2 = <<yyyy>>

注意格式中的 31;它们防止溢出。


我想知道 %31 是如何工作的。它是起到%s防止溢出的作用还是只是防止溢出?

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

    if ((n = sscanf(command, "%31[^(](%31[^)])", part1, part2)) != 2)
    if ((n = sscanf(command, "%[^(](%[^)])", part1, part2)) != 2)

%[...]符号是转换规范;也是%31[...]

C标准说:

每个转换规范都由字符 % 引入。在 % 之后,依次出现以下内容:

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

31 是(可选)最大字段宽度的示例。该[...]部分是一个scansets ,它也许可以被视为转换说明符的一个特例。转换说明%s符大致等价于%[^ \t\n]

31 比字符串的长度小一;最后的 null 不计入该长度。因为part1andpart2都是 32 的数组char,所以%31[^(]or%31[^)]转换说明符防止缓冲区溢出。如果第一个字符串在 之前超过 31 个字符(,您将获得 1 的返回值,因为文字左括号不匹配。同样,第二个字符串将被限制为 31 个字符,但您无法轻易判断 是否)在正确的位置。

于 2012-09-13T04:05:04.897 回答
2

如果您确切知道“命令”的各个部分有多长,那么最简单的选择是:

sscanf(command, "%6s(%5s)", part1, part2);

这假设“part1”始终为 6 个字符,“part2”始终为 5 个字符(如您的代码示例中所示)。

于 2012-09-13T04:07:07.087 回答
1

试试这个:

#include <stdio.h>

int main(void)
{
  char str1[20];
  char str2[20];
  sscanf("Hello(World!)", "%[^(](%[^)])", str1, str2);
  printf("str1=\"%s\", str2=\"%s\"\n", str1, str2);
  return 0;
}

输出(ideone):

str1="Hello", str2="World!"
于 2012-09-13T04:10:06.657 回答