命令行解析函数,用于将 GetCommandLine() 返回的字符串解析为若干个参数,以便传递给 getopt 等需要 argcargv 形式参数的函数使用。

#include <vector>
#include <string>

// Parse the command line and split it into tokens.
std::vector<std::string> parse_command_line(const char *cmdline)
{
    std::vector<std::string> result;
    std::string token;
    int state = 0;

    while (*cmdline)
    {
        switch (state)
        {
        case 0:
            switch (*cmdline)
            {
            case ' ':
                if (token.size())
                {
                    result.push_back(token);
                    token.clear();
                }
                break;
            case '\"':
                state = 1;
                break;
            case '\\':
                state = 6;
                break;
            default:
                token += *cmdline;
            }
            break;
        case 1:
            switch (*cmdline)
            {
            case '\"':
                state = 3;
                break;
            case '\\':
                state = 7;
                break;
            default:
                token += *cmdline;
                state = 2;
            }
            break;
        case 2:
            switch (*cmdline)
            {
            case '\"':
                state = 4;
                break;
            case '\\':
                state = 7;
                break;
            default:
                token += *cmdline;
            }
            break;
        case 3:
            switch (*cmdline)
            {
            case ' ':
                result.push_back(token);
                token.clear();
                state = 0;
                break;
            case '\\':
                state = 6;
                break;
            case '\"':
            default:
                token += *cmdline;
                state = 0;
            }
            break;
        case 4:
            switch (*cmdline)
            {
            case '\"':
                state = 5;
                break;
            case ' ':
                result.push_back(token);
                token.clear();
                state = 0;
                break;
            case '\\':
                state = 6;
                break;
            default:
                token += *cmdline;
                state = 0;
                break;
            }
            break;
        case 5:
            switch (*cmdline)
            {
            case '\\':
                state = 7;
                break;
            default:
                token += *cmdline;
                state = 2;
            }
            break;
        case 6:
            switch (*cmdline)
            {
            case ' ':
                token += '\\';
                result.push_back(token);
                token.clear();
                break;
            case '\"':
                token += *cmdline;
                break;
            default:
                token += '\\';
                token += *cmdline;
            }
            state = 0;
            break;
        case 7:
            switch (*cmdline)
            {
            case '\"':
                token += *cmdline;
                break;
            default:
                token += '\\';
                token += *cmdline;
            }
            state = 2;
        }

        ++cmdline;
    }

    if (token.size())
        result.push_back(token);

    return result;
}

使用方法如下:

    int argc;
    char **argv;

    std::vector<std::string> args = parse_command_line(GetCommandLine());
    argv = new char *[(argc = args.size()) + 1];
    int i;
    for (i = 0; i < argc; ++i)
        argv[i] = (char *) args[i].c_str();
    argv[i] = NULL;