一个面向对象的命令行解析器

这个类能解析如下格式的参数:
  • -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;
}


测试程序

posted on 2008-06-28 17:02  Phinecos(洞庭散人)  阅读(1029)  评论(0编辑  收藏  举报

导航