Элегантный разбор строки запроса в C - PullRequest
7 голосов
/ 12 марта 2012

Я пытаюсь разобрать строку запроса URL в C и не вижу, как это сделать элегантно. Любые советы или предложения будут с благодарностью:

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.

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Вам нужно либо настроить сложный и эффективный синтаксический анализатор, либо использовать библиотеки, которые сделают это за вас.

uriparser должен предоставить все, что вам нужно (плюс он поддерживает Unicode).

1 голос
/ 12 марта 2012

В общем случае 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]);
    }
0 голосов
/ 12 марта 2012

Допущения - это неплохая вещь, в общем, особенно в быстром, надежном и защитном коде (учтите, например, что ваша строка ввода имеет недопустимый формат).

Однако, чтобы достичь наиболее эластичного кода, вам необходимо вручную выделить (и освободить после использования!) Память для строк, размер которых должен быть равен общей длине входной строки (еще один раз, когда необходим разумный предел) , поскольку неизвестно (в общем случае), как долго будут строки параметров и значений.

...