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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介:
这个类能解析如下格式的参数:
-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;
}

复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/06/28/1231690.html,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
域名解析 网络协议 安全
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
|
分布式计算 前端开发 JavaScript
程范式解析:面向对象、函数式与声明式编程
程范式解析:面向对象、函数式与声明式编程
138 0
|
4月前
|
数据安全/隐私保护 Ruby
深入解析Ruby 面向对象
【8月更文挑战第28天】
53 8
|
3月前
|
Python
命令行解析工具 argparse
命令行解析工具 argparse
57 14
|
4月前
|
Java 开发者 C++
|
4月前
|
存储 Go UED
精通Go语言的命令行参数解析
【8月更文挑战第31天】
50 0
|
4月前
|
SQL 分布式计算 算法
【python】python指南(二):命令行参数解析器ArgumentParser
【python】python指南(二):命令行参数解析器ArgumentParser
48 0
|
4月前
|
Go
【go笔记】使用标准库flag解析命令行参数
【go笔记】使用标准库flag解析命令行参数
|
4月前
|
Python
python命令行解析模块argparse
python命令行解析模块argparse
|
6月前
|
Python
Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态
Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态

推荐镜像

更多
下一篇
DataWorks