Parse string into argv/argc

前端 未结 13 881
生来不讨喜
生来不讨喜 2020-11-28 07:45

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\'

13条回答
  •  萌比男神i
    2020-11-28 08:04

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

提交回复
热议问题