Rio
Rio

Reputation: 14882

Elegant parsing of query string in C

I'm trying to parse a URL query string in C and I don't see how to do it elegantly. Any hints or suggestions would be greatly appreciated:

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, "&");
 }

The problem I kept on having is that because of the strtok function anything that was seemed more intelligent to do before the last strtok function seemed to break the while loop.

Upvotes: 7

Views: 8225

Answers (4)

Zibri
Zibri

Reputation: 9847

I do:

    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;
    };

remember that strtok destroys the original so before this just make a copy of the querystring.

Upvotes: 2

Tomas Pruzina
Tomas Pruzina

Reputation: 8887

You either need to tailor complex and effective parser or settle with libraries that will do it for you.

uriparser should provide all you need (plus it supports unicode).

Upvotes: 2

pabdulin
pabdulin

Reputation: 35225

Assumptions is not a bad thing, in general, and especially in fast, robust and protective code (consider, for example, that your input string have invalid format).

To reach most elastic code however, you need to manually allocate (and deallocate after usage!) memory for strings, the size of which should be to total lenght of an input string (one more time where reasonable limit is a must), since it's unknown (in general) how long is param and value string parts.

Upvotes: 0

jim mcnamara
jim mcnamara

Reputation: 16389

In general strtok breaks the source string for use by some other functions. Here is a bare bones example of using strtok to tokenize a string

  #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]);
    }

Upvotes: 1

Related Questions