sscanf可变长度字符串解析

时间:2013-03-31 02:00:05

标签: c++ c string parsing

我有一个可能相当常见的问题,可能有一个我不知道的美丽黑客。如果有人能开导我,我将不胜感激!

我使用C的sscanf()函数来解析输入,格式是     “%d%d%d%s%d%s%d ...”     其中前两个%d是字符串的随机ID整数(无意义),第三个是要跟随的%d%s组合数的计数。

例如,“12 34 2 3是2否”可以是一个字符串,其中12和34随机是ID(对问题不重要),2指定'3 yes'和'2 no'之后的两个组合。前面的3是'yes'指定后面的字符串的长度,对于前面带有2的'no'也是如此。我们可以在下面使用可变数量的这些组合,我们希望用sscanf捕获它们。

有没有人知道用sscanf做任何事情?

非常感谢!

4 个答案:

答案 0 :(得分:3)

只需在两次(或多次)传递中解析字符串。这使用%n格式说明符来写入处理的字节数,因此我们知道在后续传递中的位置:

int a, b, n, pos;
const char *buf = "12 34 2 3 yes 2 no";

assert(sscanf(buf, "%d %d %d %n", &a, &b, &n, &pos) == 3);
for(int i=0; i<n; i++) {
    int cur;

    int x;
    char y[20];

    assert(sscanf(buf+pos, "%d %19s %n", &x, y, &cur) == 2);
    printf("%d %s\n", x, y);
    pos += cur;
}

输出

3 yes
2 no

答案 1 :(得分:1)

仅使用sscanf没有方便的方法。在将格式字符串传递给sscanf之前,您需要动态生成格式字符串

您可能要考虑为此编写专门的解析例程,在循环中调用sscanf,或者更优选地(因为您指定C ++标记)在循环中使用std::istringstream。< / p>

答案 2 :(得分:0)

首先,ssprintf()用于生成字符串,而不是解析它。你应该使用sscanf。我不知道在一个sscanf()中完成它。但你可以在循环中做到:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    int choice_id, count;
    char choice[20],id_1[20],id_2[20], count_str[20], choice_id_str[20];
    int index;
    char *input = "12 34 2 3 yes 2 no";

    sscanf(input, "%s %s %s", id_1, id_2, count_str);
    input += strlen(id_1)+strlen(id_2)+strlen(count_str)+2;
    count = atoi(count_str);
    for(index = 0; index< count; ++index){
        sscanf(input, " %s %s", choice_id_str, choice );
        choice_id = atoi(choice_id_str);
        // Process or store the record
        printf("%d: %s\n",choice_id, choice);
        input += strlen(choice_id_str) + strlen(choice) + 2;
    }
    return 0;
}

使用gcc(GCC)4.1.2编译,并使用Linux运行。输出是:

-bash-3.2$ ./a.out
3: yes
2: no

答案 3 :(得分:0)

初始“%d%d%d”标题后面的%d%s对的数量是否有最大值? 必须有,因为你把价值放在某个地方,也许是在 struct {int i; char s [j]; a [n]; 适当的j和n尺寸。

(顺便说一句,你的例子使用“%d%d%d%s%d%s%d ...”当描述表明它应该是“%d%d%d%d%s%d%s %d%s ...“,3位小数,后跟小数/字符串对)

如果有最大值,只需创建一个最大化模板并测试来自sscanf的返回码,它应指示成功匹配和分配的输入项的数量,是第3个值减去3个标题项。 如果与第3个int相比返回代码不正确,则报告格式错误的行。

我曾经做过类似这样的函数,所以a [n]自动离开堆栈,然后函数从堆中为sscanf-ed项分配了一个链表,并返回指向第一项的指针。