一个面向对象的命令行解析器
这个类能解析如下格式的参数:

#include <map>
#include <string>


#define UNKNOWN_PARAM "UNKNOWN_PARAM"
#define NO_VALUE_PARAM "PARAM_NO_VALUE"
#define GENERIC_ERROR "GENERIC_ERROR"

/**
    Interface that must be implemented by the objects that requires access to the
    command line arguments.
    @see CCommandLineParser
*/
class ICmdLineParam
{
public:
    /**
         Method called by the CCommandLineParser to pass the arguments and the values.
         The parser calls this method to indicate the name of the arguments and/or
         the values only when applicable. The '-' or '/' of the arguments are eliminated
         before reach this method.
         @return false only if the parser must stop, on a serious error.
                true when the argument is OK or is malformed, in this second case 
                the function GetError must return a description, see below.
    */
    virtual bool Parse(std::string argument,std::string value) = 0;

    /** Method called by the CCommandLineParser to retrieve the error description.
        // if an fail in command line occurs, this method must return a description of the error.
        // Ex: "Inaccesible input file", "invalid type of algorithm",..,etc.
        @retrun "" to indicate that no error was produced.
    */
    virtual std::string GetError() = 0;

};


class CCommandLineParser
{
public:
    CCommandLineParser(){m_defaultCommand = NULL;}
    /**
        Object that handle the default arguments. Only one can be specified.
    */
    void SetDefaultCommand(ICmdLineParam* e);
    /**
        Objects that handle the empty arguments. Can be called how many times as necesary.
        @param para name of the argument that this ICmdLineParam expect.
        @e ICmdLineParam
    */
    void PutEmptyCommand(std::string argument,ICmdLineParam* e);
    /**
        Entry that handle the values arguments. Can be called how many times as necesary.
        @param para name of the argument that this ICmdLineParam expect.
        @e ICmdLineParam
    */
    void PutValueCommand(std::string argument,ICmdLineParam* e);
    /**
        Entry that handle the errors of the CCommandLineParser. Only one can be specified.
    */
    void SetErrorCommand(ICmdLineParam* e);

    
    /**
        Inits the parse process.
        @param argn number of arguments passed to the application.
        @param argv array of string with the arguments passed to the application.
    */
    bool ParseArguments(int argn,char* argv[]);
private:
    ICmdLineParam* m_defaultCommand;
    ICmdLineParam* m_errorCommand;
    std::map<std::string,ICmdLineParam*> m_mapValueCommand;//值参数映射表
    std::map<std::string,ICmdLineParam*> m_mapEmptyCommand;//空参数映射表

    /**
        Deletes the '-', '--', '/' of the argument.
        @return <b>true</b> if the argument is not a value.
    */
    bool DeleteMinus(std::string& param);
};
void CCommandLineParser::SetDefaultCommand(ICmdLineParam* obj)
{
    m_defaultCommand = obj;
}
void CCommandLineParser::PutEmptyCommand(std::string argument,ICmdLineParam* obj)
{
    m_mapEmptyCommand[argument] = obj;
    
}
void CCommandLineParser::PutValueCommand(std::string argument,ICmdLineParam* obj)
{
    m_mapValueCommand[argument] = obj;
}
void CCommandLineParser::SetErrorCommand(ICmdLineParam* obj)
{
    m_errorCommand = obj;
}


bool CCommandLineParser::ParseArguments(int argn,char* argv[])
{
    bool bAllOK = true;
    int i = 1; // First paramter is discarded becouse it's the execution program path.
    
    while(i < argn )
    {
        
        std::string argument = argv[i];//当前待处理的参数

        if(DeleteMinus(argument))
        {
            //到值参数映射表中寻找待设置的值参数
            // Check if this argument requires a value.
            std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.find(argument);

            if(it != m_mapValueCommand.end())
            {//值参数表中存在
                if(argv[i + 1] == NULL)
                {//没有提供值
                    bAllOK &= m_errorCommand->Parse(NO_VALUE_PARAM,argument);
                    return false;
                }
                std::string paso = argv[i + 1];
                if(DeleteMinus(paso))
                {//没有提供值
                    bAllOK &= m_errorCommand->Parse(NO_VALUE_PARAM,argument);
                    return false;
                }
                else
                {
                    bAllOK &= it->second->Parse(argument,paso);//解析出值
                    i++;
                }
            }
            else
            {//值参数表中不存在
                it = m_mapEmptyCommand.find(argument);//到空参数表中寻找
                if(it != m_mapEmptyCommand.end())
                {//找到了
                    bAllOK &= it->second->Parse(argument,"");
                }
                else
                {//用户设置的格式是”参数:值“,对这种情况进行解析
                    // Try to split a ":"
                    std::string::size_type position = argument.find_first_of(":");
                    if(position != std::string::npos)
                    {
                        std::string command = argument.substr(0,position);
                        std::string value = argument.substr(position + 1);
                        //到值参数映射表中寻址
                        std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.find(command);
                        if(it != m_mapValueCommand.end())
                        {//找到
                            bAllOK &= it->second->Parse(command,value);
                        }
                        else
                        {//不存在
                            bAllOK &= m_errorCommand->Parse(UNKNOWN_PARAM,command);
                            return false;
                        }
                    }
                    else
                    {//未知参数
                        bAllOK &= m_errorCommand->Parse(UNKNOWN_PARAM,argument);
                        return false;
                    }
                }

            }    
        }
        else
        {//不是附加参数,而是默认参数
            if(m_defaultCommand != NULL)
            {
                bAllOK &= m_defaultCommand->Parse("",argument);
            }
            else
            {
                return false;
            }
        }
        i++;
    }
    //错误处理
    std::string error = m_defaultCommand->GetError();
    if(error != "")
    {
        m_errorCommand->Parse(GENERIC_ERROR,error);
        return false;
    }


    std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.begin();

    while(it != m_mapValueCommand.end())
    {
        error = it->second->GetError();
        if(error != "")
        {
            m_errorCommand->Parse(GENERIC_ERROR,error);
            return false;
        }
        it++;
    }

    std::map<std::string,ICmdLineParam*>::iterator it2 = m_mapEmptyCommand.begin();

    while(it2 != m_mapEmptyCommand.end())
    {
        error = it2->second->GetError();
        if(error != "")
        {
            m_errorCommand->Parse(GENERIC_ERROR,error);
            return false;
        }
        it2++;
    }


    return bAllOK;// Devuelve false si ha habido error.
}

bool CCommandLineParser::DeleteMinus(std::string& argument)
{//去掉参数前的分隔符
    switch(argument[0])
    {
    case '/':
        argument = &(argument.c_str()[1]);
        return true;
    case '-':
        if(argument[1] == '-')
        {
            argument = &(argument.c_str()[2]);
        }
        else
        {
            argument = &(argument.c_str()[1]);
        }
        return true;
    }


    return false;
}
测试程序
- -b
 - -h www.codeproject.com
 - stdafx.cpp
 - -temp:-7
 
除此以外,还可以解析以“—”或“/”打头的参数。
一般有三类参数需要解析:
- 作为标识的参数(例如“ls –l”),这叫空参数
 - 有其值的参数(例如“netstat –p tcp”),这叫值参数
 - 不带任何“-”的(例如“copy a.cpp b.cpp”),这叫默认参数。
 

#include <map>
#include <string>

#define UNKNOWN_PARAM "UNKNOWN_PARAM"
#define NO_VALUE_PARAM "PARAM_NO_VALUE"
#define GENERIC_ERROR "GENERIC_ERROR"
/**
    Interface that must be implemented by the objects that requires access to the
    command line arguments.
    @see CCommandLineParser
*/
class ICmdLineParam
{
public:
    /**
         Method called by the CCommandLineParser to pass the arguments and the values.
         The parser calls this method to indicate the name of the arguments and/or
         the values only when applicable. The '-' or '/' of the arguments are eliminated
         before reach this method.
         @return false only if the parser must stop, on a serious error.
                true when the argument is OK or is malformed, in this second case 
                the function GetError must return a description, see below.
    */
    virtual bool Parse(std::string argument,std::string value) = 0;
    /** Method called by the CCommandLineParser to retrieve the error description.
        // if an fail in command line occurs, this method must return a description of the error.
        // Ex: "Inaccesible input file", "invalid type of algorithm",..,etc.
        @retrun "" to indicate that no error was produced.
    */
    virtual std::string GetError() = 0;
};

class CCommandLineParser
{
public:
    CCommandLineParser(){m_defaultCommand = NULL;}
    /**
        Object that handle the default arguments. Only one can be specified.
    */
    void SetDefaultCommand(ICmdLineParam* e);
    /**
        Objects that handle the empty arguments. Can be called how many times as necesary.
        @param para name of the argument that this ICmdLineParam expect.
        @e ICmdLineParam
    */
    void PutEmptyCommand(std::string argument,ICmdLineParam* e);
    /**
        Entry that handle the values arguments. Can be called how many times as necesary.
        @param para name of the argument that this ICmdLineParam expect.
        @e ICmdLineParam
    */
    void PutValueCommand(std::string argument,ICmdLineParam* e);
    /**
        Entry that handle the errors of the CCommandLineParser. Only one can be specified.
    */
    void SetErrorCommand(ICmdLineParam* e);
    
    /**
        Inits the parse process.
        @param argn number of arguments passed to the application.
        @param argv array of string with the arguments passed to the application.
    */
    bool ParseArguments(int argn,char* argv[]);
private:
    ICmdLineParam* m_defaultCommand;
    ICmdLineParam* m_errorCommand;
    std::map<std::string,ICmdLineParam*> m_mapValueCommand;//值参数映射表
    std::map<std::string,ICmdLineParam*> m_mapEmptyCommand;//空参数映射表
    /**
        Deletes the '-', '--', '/' of the argument.
        @return <b>true</b> if the argument is not a value.
    */
    bool DeleteMinus(std::string& param);
};
void CCommandLineParser::SetDefaultCommand(ICmdLineParam* obj)
{
    m_defaultCommand = obj;
}
void CCommandLineParser::PutEmptyCommand(std::string argument,ICmdLineParam* obj)
{
    m_mapEmptyCommand[argument] = obj;
    
}
void CCommandLineParser::PutValueCommand(std::string argument,ICmdLineParam* obj)
{
    m_mapValueCommand[argument] = obj;
}
void CCommandLineParser::SetErrorCommand(ICmdLineParam* obj)
{
    m_errorCommand = obj;
}

bool CCommandLineParser::ParseArguments(int argn,char* argv[])
{
    bool bAllOK = true;
    int i = 1; // First paramter is discarded becouse it's the execution program path.
    
    while(i < argn )
    {
        
        std::string argument = argv[i];//当前待处理的参数
        if(DeleteMinus(argument))
        {
            //到值参数映射表中寻找待设置的值参数
            // Check if this argument requires a value.
            std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.find(argument);
            if(it != m_mapValueCommand.end())
            {//值参数表中存在
                if(argv[i + 1] == NULL)
                {//没有提供值
                    bAllOK &= m_errorCommand->Parse(NO_VALUE_PARAM,argument);
                    return false;
                }
                std::string paso = argv[i + 1];
                if(DeleteMinus(paso))
                {//没有提供值
                    bAllOK &= m_errorCommand->Parse(NO_VALUE_PARAM,argument);
                    return false;
                }
                else
                {
                    bAllOK &= it->second->Parse(argument,paso);//解析出值
                    i++;
                }
            }
            else
            {//值参数表中不存在
                it = m_mapEmptyCommand.find(argument);//到空参数表中寻找
                if(it != m_mapEmptyCommand.end())
                {//找到了
                    bAllOK &= it->second->Parse(argument,"");
                }
                else
                {//用户设置的格式是”参数:值“,对这种情况进行解析
                    // Try to split a ":"
                    std::string::size_type position = argument.find_first_of(":");
                    if(position != std::string::npos)
                    {
                        std::string command = argument.substr(0,position);
                        std::string value = argument.substr(position + 1);
                        //到值参数映射表中寻址
                        std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.find(command);
                        if(it != m_mapValueCommand.end())
                        {//找到
                            bAllOK &= it->second->Parse(command,value);
                        }
                        else
                        {//不存在
                            bAllOK &= m_errorCommand->Parse(UNKNOWN_PARAM,command);
                            return false;
                        }
                    }
                    else
                    {//未知参数
                        bAllOK &= m_errorCommand->Parse(UNKNOWN_PARAM,argument);
                        return false;
                    }
                }
            }    
        }
        else
        {//不是附加参数,而是默认参数
            if(m_defaultCommand != NULL)
            {
                bAllOK &= m_defaultCommand->Parse("",argument);
            }
            else
            {
                return false;
            }
        }
        i++;
    }
    //错误处理
    std::string error = m_defaultCommand->GetError();
    if(error != "")
    {
        m_errorCommand->Parse(GENERIC_ERROR,error);
        return false;
    }

    std::map<std::string,ICmdLineParam*>::iterator it = m_mapValueCommand.begin();
    while(it != m_mapValueCommand.end())
    {
        error = it->second->GetError();
        if(error != "")
        {
            m_errorCommand->Parse(GENERIC_ERROR,error);
            return false;
        }
        it++;
    }
    std::map<std::string,ICmdLineParam*>::iterator it2 = m_mapEmptyCommand.begin();
    while(it2 != m_mapEmptyCommand.end())
    {
        error = it2->second->GetError();
        if(error != "")
        {
            m_errorCommand->Parse(GENERIC_ERROR,error);
            return false;
        }
        it2++;
    }

    return bAllOK;// Devuelve false si ha habido error.
}
bool CCommandLineParser::DeleteMinus(std::string& argument)
{//去掉参数前的分隔符
    switch(argument[0])
    {
    case '/':
        argument = &(argument.c_str()[1]);
        return true;
    case '-':
        if(argument[1] == '-')
        {
            argument = &(argument.c_str()[2]);
        }
        else
        {
            argument = &(argument.c_str()[1]);
        }
        return true;
    }

    return false;
}
作者:洞庭散人
出处:http://phinecos.cnblogs.com/
本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。
posted on 2008-06-28 17:02 Phinecos(洞庭散人) 阅读(1035) 评论(0) 收藏 举报
                    
                
    
                
            
        
浙公网安备 33010602011771号