在C中是否有办法解析一段文本并获取argv和argc的值,就像文本已经在命令行中传递给应用程序一样?
这不一定适用于Windows,只需Linux - 我也不关心引用参数.
R..*_*R.. 29
我很惊讶没有人使用标准POSIX功能提供最简单的答案:
http://www.opengroup.org/onlinepubs/9699919799/functions/wordexp.html
小智 14
这是我的贡献.它很好而且很短,但需要注意的是:
代码:
enum { kMaxArgs = 64 };
int argc = 0;
char *argv[kMaxArgs];
char *p2 = strtok(commandLine, " ");
while (p2 && argc < kMaxArgs-1)
  {
    argv[argc++] = p2;
    p2 = strtok(0, " ");
  }
argv[argc] = 0;
您现在可以使用argc和argv,或将它们传递给声明为"foo(int argc,char**argv)"的其他函数.
Rem*_*o.D 12
如果glib解决方案对您的情况来说太过分了,您可以考虑自己编写一个.
然后你可以:
下图应该澄清(希望):
             aa bbb ccc "dd d" ee         <- original string
             aa0bbb0ccc00dd d00ee0        <- transformed string
             |  |   |    |     |
   argv[0] __/  /   /    /     /
   argv[1] ____/   /    /     /
   argv[2] _______/    /     /
   argv[3] ___________/     /
   argv[4] ________________/ 
可能的API可能是:
    char **parseargs(char *arguments, int *argc);
    void   freeparsedargs(char **argv);
您需要其他注意事项才能安全地实现freeparsedargs().
如果您的字符串很长并且您不想扫描两次,则可以考虑使用替代方法,例如为argv数组分配更多元素(如果需要,还可以重新分配).
编辑:提出的解决方案(des not handle引用的参数).
    #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);
    }
永远在线的精彩油嘴有g_shell_parse_args()这听起来像你以后.
如果你对引用甚至不感兴趣,这可能是过度的.您需要做的就是使用空格作为标记字符进行标记.写一个简单的例程来做到这一点不应该花很长时间,真的.
如果你对记忆并不吝啬,那么在没有重新分配的情况下一次性完成它应该很容易; 假设每个第二个字符都是空格的最坏情况,因此假设一串n字符最多包含(n + 1) / 2参数,并且(当然)最多n包含参数文本字节(不包括终结符).
这是Windows和Unix的解决方案(在Linux,OSX和Windows上测试).与Valgrind和记忆博士一起测试.
它使用wordexp用于POSIX系统,而CommandLineToArgvW用于Windows.
请注意,对于Windows的解决方案,大部分代码之间转换char **,并wchar_t **与美丽的Win32 API的,因为没有CommandLineToArgvA可用的(ANSI版本).
#ifdef _WIN32
#include <windows.h>
#else
#include <wordexp.h>
#endif
char **split_commandline(const char *cmdline, int *argc)
{
    int i;
    char **argv = NULL;
    assert(argc);
    if (!cmdline)
    {
        return NULL;
    }
    // Posix.
    #ifndef _WIN32
    {
        wordexp_t p;
        // Note! This expands shell variables.
        if (wordexp(cmdline, &p, 0))
        {
            return NULL;
        }
        *argc = p.we_wordc;
        if (!(argv = calloc(*argc, sizeof(char *))))
        {
            goto fail;
        }
        for (i = 0; i < p.we_wordc; i++)
        {
            if (!(argv[i] = strdup(p.we_wordv[i])))
            {
                goto fail;
            }
        }
        wordfree(&p);
        return argv;
    fail:
        wordfree(&p);
    }
    #else // WIN32
    {
        wchar_t **wargs = NULL;
        size_t needed = 0;
        wchar_t *cmdlinew = NULL;
        size_t len = strlen(cmdline) + 1;
        if (!(cmdlinew = calloc(len, sizeof(wchar_t))))
            goto fail;
        if (!MultiByteToWideChar(CP_ACP, 0, cmdline, -1, cmdlinew, len))
            goto fail;
        if (!(wargs = CommandLineToArgvW(cmdlinew, argc)))
            goto fail;
        if (!(argv = calloc(*argc, sizeof(char *))))
            goto fail;
        // Convert from wchar_t * to ANSI char *
        for (i = 0; i < *argc; i++)
        {
            // Get the size needed for the target buffer.
            // CP_ACP = Ansi Codepage.
            needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
                                        NULL, 0, NULL, NULL);
            if (!(argv[i] = malloc(needed)))
                goto fail;
            // Do the conversion.
            needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
                                        argv[i], needed, NULL, NULL);
        }
        if (wargs) LocalFree(wargs);
        if (cmdlinew) free(cmdlinew);
        return argv;
    fail:
        if (wargs) LocalFree(wargs);
        if (cmdlinew) free(cmdlinew);
    }
    #endif // WIN32
    if (argv)
    {
        for (i = 0; i < *argc; i++)
        {
            if (argv[i])
            {
                free(argv[i]);
            }
        }
        free(argv);
    }
    return NULL;
}