【问题标题】:C query string parsingC查询字符串解析
【发布时间】:2019-05-03 16:06:05
【问题描述】:

我有以下查询字符串

address=1234&port=1234&username=1234&password=1234&gamename=1234&square=1234&LOGIN=LOGIN

我正在尝试将其解析为不同的变量:地址、端口、用户名、密码、游戏名、方块和命令(将保存 LOGIN)

我正在考虑使用 strtok,但我认为它不会起作用。如何解析字符串以捕获变量?

P.S - 某些字段可能是空的 - 没有提供游戏名称或正方形

【问题讨论】:

  • 使用strtok
  • 使用strtok分割&,然后使用strchr在token中找到=。你真的是J Doe吗?
  • 如果可能存在空字段(例如"&&"),则不能使用strtok(它将连续分隔符视为单个分隔符)。但是,您可以使用strsep、strcspn 或strpbrk 通过定位分隔符来处理空字段。在这里,您可以将strtok 嵌套在strsep 调用中,以使用"&\n" 作为strsep 的分隔符,然后调用strtok,使用"=\n" 作为分隔var=value 部分的分隔符。

标签: c string parsing query-string


【解决方案1】:

在解析可能包含分隔符之间的空字段的字符串时,不能使用strtok,因为strtok 会将任意数量的连续分隔符视为单个分隔符。

因此,在您的情况下,如果 variable=values 字段还可能在 '&' 分隔符之间包含一个空字段,则您必须使用 strsep 或其他函数,例如 strcspn , strpbrk 或简单的 strchr 和几个指针,可以沿着字符串向下工作。

strsep 函数是一个 BSD 函数,可能不包含在您的 C 库中。 GNU 包含strsep,它被设想为strtok 的替代品,仅仅是因为strtok 不能处理空字段。

(如果您没有可用的strsep,您只需保留一个start 和end 指针并使用strchr 之类的函数来定位每个发生'&' 将end 指针设置为分隔符前1,然后从start 和var=value 信息em>end 指针,然后将两者都更新为指向分隔符并重复。)

在这里,您可以使用带有"&\n" 分隔符的strsep 来定位每个'&'(假设该行是从具有面向行的文件中读取的,则包含'\n' 字符> 输入函数如fgets 或POSIX getline)。然后,您可以简单地调用 strtok 来解析 strsep 返回的每个令牌中的 var=value 文本,使用 "=" 作为分隔符('\n' 已经从最后一个令牌中删除使用strsep解析时)

在"...gamename=1234&&square=1234..." 之间插入特定空字段以进行处理的示例如下:

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

int main (void) {

    char array[] =  "address=1234&port=1234&username=1234&password=1234"
                    "&gamename=1234&&square=1234&LOGIN=LOGIN",
        *query = strdup (array),  /* duplicate array, &array is not char** */
        *tokens = query,
        *p = query;

    while ((p = strsep (&tokens, "&\n"))) {
        char *var = strtok (p, "="),
             *val = NULL;
        if (var && (val = strtok (NULL, "=")))
            printf ("%-8s    %s\n", var, val);
        else
            fputs ("<empty field>\n", stderr);
    }

    free (query);
}

(注意: strsep 将 char** 参数作为其第一个参数,并将修改参数以指向分隔符之后,因此您必须保留对原始开头的引用分配的字符串(query 以上))。

使用/输出示例

$ ./bin/strsep_query
address     1234
port        1234
username    1234
password    1234
gamename    1234
<empty field>
square      1234
LOGIN       LOGIN

(注意:将"1234" 转换为数值的工作由您完成)

检查一下,如果您还有其他问题,请告诉我。

【讨论】:

  • hmm 你为什么要单独strduping 数组?也许你的意思是char *query = strdup(getenv("QUERY_STRING")) 或类似的
  • 哎呀..好问题。我将不得不尝试回忆我的思考过程。我相信目的是从问题中获取查询字符串并以strsep 可用的形式复制它——我不确定问题是否涉及当前用户的信息(至少这是我能记得的最好的)
  • 另外,我认为通常不会有空的名称-值对,但没有foo=1&amp;bar&amp;baz=2 的名称是可能的,foo=42&amp;bar=&amp;baz=2 也是可能的;并且同名出现多次。
  • 是的,这是有道理的。我确实记得问题中的"PS - some of the fields might be empty..." 是strsep 的原因——如果OP 的意思是"...&amp;gamename=&amp;square..." 而不是"...&amp;&amp;...",那么strtok 就可以了。很好地抓住了歧义,我从未想到过另一种解释。 (到现在)
猜你喜欢
  • 2011-02-27
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 2020-01-07
  • 1970-01-01
  • 2011-05-21
  • 2011-07-20
  • 2010-12-12
相关资源
最近更新 更多