C++解析命令行参数(仿C语言args)

说好不造轮子的,就管不住这手

#include <cstdio>
#include <string>
#include <vector>


bool ParseChar( const std::string& buf, std::size_t& pos, char& ch, bool& escape )
{
    char c;

    if ( pos == buf.length() )
        return false;

    // Get the character to parse
    c = buf.at( pos++ );

    if ( c == '\' )
    {
        // Parse the escape character

        if ( pos != buf.length() )
        {
            // Get the character to escape
            c = buf.at( pos++ );

            if ( c == '\' || c == '"' )
            {
                ch = c;
                escape = true;
            }
            else
            {
                // Does not support the character, just hold the '\' character
                //  We need move the POS back to prepare for the character parsing
                pos--;
                ch = '\';
                escape = false;
            }
        }
        else
        {
            // We can't get the character to escape
            //  Just hold the '\' character
            ch = c;
            escape = false;
        }
    }
    else
    {
        // Copy the character

        ch = c;
        escape = false;
    }

    return true;
}

bool ParseToken( const std::string& buf, std::size_t& pos, std::string& token )
{
    char c {};
    bool escape {};
    bool quote {};        // True if parsing a string
    bool doing {};        // True if parsing has started

    // Skip blank characters, if any
    while ( pos != buf.length() )
    {
        c = buf.at( pos );

        if ( c != ' ' && c != '	' )
            break;

        pos++;
    }

    // Clean up the token
    token.clear();

    while ( ParseChar( buf, pos, c, escape ) )
    {
        if ( !doing )
        {
            // Parse the first character

            if ( c == '"' && !escape )
            {
                // Just mark the beginning of the string, don't copy it
                quote = true;
            }
            else
            {
                // Copy the first character of the token
                token.push_back( c );
            }

            // '
' is a single character token
            if ( c == '
' )
                return true;

            // We have parsed any one character, the parsing has started
            doing = true;
        }
        else
        {
            if ( quote )
            {
                // Copying the character of the string here

                if ( c == '"' && !escape )
                {
                    // Mark the ending of a string
                    return true;
                }
                else
                {
                    // Copy the character of the string
                    token.push_back( c );
                }
            }
            else
            {
                // Copying the character of the token here

                if ( c == '"' && !escape )
                {
                    // We accidentally encounter a string beginning mark before the token finished
                    //  We need to finish the token and move the POS back to prepare for the string parsing
                    pos--;
                    return true;
                }

                if ( c == '
' )
                {
                    // We accidentally encounter a '
' before the token finished
                    //  We need to finish the token and move the POS back to prepare for the '
' parsing
                    pos--;
                    return true;
                }

                if ( c == ' ' || c == '	' )
                {
                    // Mark the ending of a string
                    return true;
                }
                else
                {
                    // Copy the character of the token
                    token.push_back( c );
                }
            }
        }
    }

    // If no any characters are parsed, we are at the end of the buffer
    //  returns 'false' to finish the parsing

    return doing;
}

int main()
{
    std::string cmdline = R"(   connect
spawn  1
name "Billy Herrington"
flags          0xffff    ""
desc "boy \next" door"    )";

    std::size_t pos {};
    std::string token {};

    while ( ParseToken( cmdline, pos, token ) )
    {
        printf_s( "[%s]
", token == "
" ? "\n" : token.c_str() );
    }

    return 0;
}

输出如下

[connect]
[
]
[spawn]
[1]
[
]
[name]
[Billy Herrington]
[
]
[flags]
[0xffff]
[]
[
]
[desc]
[boy 
ext" door]

我对换行符做了点特殊处理,如果不需要可以删掉相关的判断代码

原文地址:https://www.cnblogs.com/crsky/p/10779692.html