在C中解析参数的简单但可靠的方法是什么?

时间:2012-04-13 07:08:31

标签: c parsing

我有一些输入参数,如:

  

参数1 = param1Value &安培;的 param2的 = param2Value &安培;的参数3 = param3Value ...

这些参数与字符“& ”相关联,参数及其值与“ = ”相关联。我想将它们解析为这样的键值映射:

[param1, param1Value], [param2, param2Value], [param3, param3Value],...

但是因为参数的值包含两个键字符,这将破坏参数解析过程。

我被告知参数传递者,他创建了这些参数格式以便于自定义,例如使用 sprintf 更改不同应用程序的参数值。因此很难说服他们在地图数组中分隔这些参数。

我原本打算使用yacc / lex,但要复杂到这样的小功能sscanf也可以解析像regexp这样的文本,但是为我的参数列表构建类似regexp的字符串似乎并不那么容易。

有没有简单但可靠的方法来解析它们而没有关键字?

3 个答案:

答案 0 :(得分:6)

您可以使用strtok'&'字符处的字符串进行标记,然后在'='拆分“标记”以获取参数名称和值。

'='分割也可以使用strtok(或更确切地说strtok_r)或使用strchrstrncpy/strcpy或{{3} }。

答案 1 :(得分:0)

如果您确保该模式可以使用简单的解析函数。

如果保证最大键/值长度,那么固定缓冲区+副本将是最简单的。否则你可以先找到分隔符的位置,然后找到malloc那个大小等等。

作为一个简单的 示例 /概念,固定大小为max 100,即:

#include <stdio.h>

int get_pair(char **p, char *key, char *val)
{
    int esc = 0;    /* escape level */
    char *cp = key; /* current target */

    *key = '\0';    /* if either is blank */
    *val = '\0';

    if (!*p || !**p)
        return 0;

    /* this could be done more elegant */
    while (**p) {
        if (**p == '=' && (esc & 1) == 0) {
            *cp = '\0'; /* terminate */
            cp = val;   /* change target */
            ++(*p);
            continue;
        } else if (**p == '&' && (esc & 1) == 0) {
            ++(*p);     /* skip & and break */
            break;
        }

        if (**p == '\\') {
            if((++esc & 1) == 0) /* if 2, 4, 6 ... \'s */
                *cp++ = **p;
        } else {
            esc = 0;
            *cp++ = **p;
        }
        ++(*p);
    }

    *cp = '\0';
    return 1;
}

int main(void)
{
    char *data = "ab=123&a\\=42&m\\\\ed\\=\\&do\\\\\\\\=mix";
    char key[100];
    char val[100];

    printf("Parse: %s\n", data);

    while (get_pair(&data, key, val))
        printf("key: %s\nval: %s\n\n", key, val);

    return 0;
}

输出:

Parse: ab=123&a\=42&m\\ed\=\&do\\\\=mix
key: ab
val: 123

key: a=42
val: 

key: m\ed=&do\\
val: mix

答案 2 :(得分:0)

是的,我已修复它们:虽然路人给我参数,他们应该使用\来逃避=&,但\本身不会需要逃避。在我提取这些参数时,我只需将\&替换为&,将\=替换为'='。如果实际值为\\=,则只需使用\\\=对其进行编码。我不需要分析\字符,只需将它们留在原处。