在C中优雅地解析查询字符串

时间:2012-03-12 03:45:32

标签: c refactoring c99

我正在尝试在C中解析URL查询字符串,但我看不出如何优雅地完成它。任何提示或建议将不胜感激:

static void readParams(char * string, char * param, char * value) {
    char arg[100] = {0};  // Not elegant, brittle
    char value2[1024] = {0};

    sscanf(string, "%[^=]=%s", arg, value2);
    strcpy(param, arg);
    strcpy(value, value2);
}
char * contents = "username=ted&age=25";
char * splitted = strtok (contents,"&");
char * username;
char * age;

while (splitted != NULL)
{
    char param[100]; // Not elegant, brittle
    char value[100];
    char * t_str = strdup(splitted);
    readParams(t_str, param, value);
    if (strcmp(param, "username") == 0) {
        username = strdup(value);
    }
    if (strcmp(param, "age") == 0) {
        age = strdup(value); // This is a string, can do atoi
    }
   splitted = strtok (NULL, "&");
 }

我一直存在的问题是,由于strtok函数,在最后一个strtok函数似乎打破while循环之前,似乎更聪明的事情。

4 个答案:

答案 0 :(得分:2)

您需要定制复杂而有效的解析器,或者与能够为您完成的库结算。

uriparser应该提供您所需要的一切(加上它支持unicode)。

答案 1 :(得分:1)

通常,strtok会破坏源字符串以供其他一些函数使用。这是使用strtok来标记字符串

的简单示例
  #include <stdlib.h>
  #include <string.h>
  #include <stdio.h>
  #define MX_SPLIT 128
    char **split( char **result, char *working, const char *src, const char *delim)
    {
        int i;

        strcpy(working, src); // working will get chppped up instead of src 
        char *p=strtok(working, delim);
        for(i=0; p!=NULL && i < (MX_SPLIT -1); i++, p=strtok(NULL, delim) )
        {
            result[i]=p;
            result[i+1]=NULL;  // mark the end of result array
        }
        return result;
    }

    void foo(const char *somestring)
    {
       int i=0;
       char *result[MX_SPLIT]={NULL};
       char working[256]={0x0}; // assume somestring is never bigger than 256 - a weak assumption
       char mydelim[]="!@#$%^&*()_-";
       split(result, working, somestring, mydelim);
       while(result[i]!=NULL)
          printf("token # %d=%s\n", i, result[i]);
    }

答案 2 :(得分:1)

我愿意:

    char querystring[]="a=1&b&c=3&d=&meh=5";
    int pc=0;
    char *tok;
    char *otok;
    for(tok=strtok(querystring,"&");tok!=NULL;tok=strtok(tok,"&")) {
        pc++;
        otok=tok+strlen(tok)+1;
        tok=strtok(tok,"=");
        fprintf(stderr,"param%d: %s ",pc,tok);
        tok=strtok(NULL,"=");
        fprintf(stderr,"value%d: %s\n",pc,tok);
        tok=otok;
    };

请记住strtok会破坏原始文件,因此在此之前只需复制查询字符串即可。

答案 3 :(得分:0)

通常情况下,假设并不是坏事,特别是在快速,健壮和保护性的代码中(例如,考虑输入字符串的格式无效)。

要获得大多数弹性代码,您需要为字符串手动分配(并在使用后释放!)内存,其大小应为输入字符串的总长度(在合理限制必须的情况下再多一次) ,因为它是未知的(通常)param和值字符串部分有多长。