Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse string into argv/argc

Tags:

c

arguments

Is there a way in C to parse a piece of text and obtain values for argv and argc, as if the text had been passed to an application on the command line?

This doesn't have to work on Windows, just Linux - I also don't care about quoting of arguments.

like image 375
codebox Avatar asked Nov 10 '09 09:11

codebox


2 Answers

If glib solution is overkill for your case you may consider coding one yourself.

Then you can:

  • scan the string and count how many arguments there are (and you get your argc)
  • allocate an array of char * (for your argv)
  • rescan the string, assign the pointers in the allocated array and replace spaces with '\0' (if you can't modify the string containing the arguments, you should duplicate it).
  • don't forget to free what you have allocated!

The diagram below should clarify (hopefully):

             aa bbb ccc "dd d" ee         <- original string               aa0bbb0ccc00dd d00ee0        <- transformed string              |  |   |    |     |    argv[0] __/  /   /    /     /    argv[1] ____/   /    /     /    argv[2] _______/    /     /    argv[3] ___________/     /    argv[4] ________________/  

A possible API could be:

    char **parseargs(char *arguments, int *argc);     void   freeparsedargs(char **argv); 

You will need additional considerations to implement freeparsedargs() safely.

If your string is very long and you don't want to scan twice you may consider alteranatives like allocating more elements for the argv arrays (and reallocating if needed).

EDIT: Proposed solution (desn't handle quoted argument).

    #include <stdio.h>      static int setargs(char *args, char **argv)     {        int count = 0;         while (isspace(*args)) ++args;        while (*args) {          if (argv) argv[count] = args;          while (*args && !isspace(*args)) ++args;          if (argv && *args) *args++ = '\0';          while (isspace(*args)) ++args;          count++;        }        return count;     }      char **parsedargs(char *args, int *argc)     {        char **argv = NULL;        int    argn = 0;         if (args && *args         && (args = strdup(args))         && (argn = setargs(args,NULL))         && (argv = malloc((argn+1) * sizeof(char *)))) {           *argv++ = args;           argn = setargs(args,argv);        }         if (args && !argv) free(args);         *argc = argn;        return argv;     }      void freeparsedargs(char **argv)     {       if (argv) {         free(argv[-1]);         free(argv-1);       }      }      int main(int argc, char *argv[])     {       int i;       char **av;       int ac;       char *as = NULL;        if (argc > 1) as = argv[1];        av = parsedargs(as,&ac);       printf("== %d\n",ac);       for (i = 0; i < ac; i++)         printf("[%s]\n",av[i]);        freeparsedargs(av);       exit(0);     } 
like image 22
Remo.D Avatar answered Sep 17 '22 08:09

Remo.D


I'm surprised nobody has provided the simplest answer using standard POSIX functionality:

http://www.opengroup.org/onlinepubs/9699919799/functions/wordexp.html

like image 195
R.. GitHub STOP HELPING ICE Avatar answered Sep 17 '22 08:09

R.. GitHub STOP HELPING ICE