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 != '\t' )
            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 );
            }

            // '\n' is a single character token
            if ( c == '\n' )
                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 == '\n' )
                {
                    // We accidentally encounter a '\n' before the token finished
                    //  We need to finish the token and move the POS back to prepare for the '\n' parsing
                    pos--;
                    return true;
                }

                if ( c == ' ' || c == '\t' )
                {
                    // 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]\n", token == "\n" ? "\\n" : token.c_str() );
    }

    return 0;
}

输出如下

[connect]
[\n]
[spawn]
[1]
[\n]
[name]
[Billy Herrington]
[\n]
[flags]
[0xffff]
[]
[\n]
[desc]
[boy \next" door]

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

 

原文链接: https://www.cnblogs.com/crsky/p/10779692.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

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

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/294291

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月15日 下午3:42
下一篇 2023年2月15日 下午3:42

相关推荐