c++实现通用参数解析类示例

main.cpp


代码如下:

#include <iostream>
#include <getopt.h>
#include "parsingargs.h"
#include <string.h>

using namespace std;

int main(int argc, char * argv[])
{

//string tmpPara = "-p \"4567\" --out 1.log "; //ok
    //string tmpPara = "xxxx -p \"4567\" --out 1.log ";//ok
    //string tmpPara = "-p \"4567\" --out 1.log 2.log"; //ok
    string tmpPara = "";
    for(int i=1;i <argc; i++)
    {
        cout << i << "=" << argv[i] <<"---"<< endl;
        if(strlen(argv[i]) == 0) //处理空字符串
        {
            cout << "find NULL" << endl;
            tmpPara += char(31);
        }
        else
        {
            tmpPara += argv[i];
        }
        tmpPara += " ";
    }
    std::map<std::string, std::vector<std::string> > result;
    ParsingArgs pa;
    pa.AddArgType('l',"getlist", ParsingArgs::NO_VALUE);
    pa.AddArgType('p',"getuser", ParsingArgs::MAYBE_VALUE);
    pa.AddArgType('o',"outFile", ParsingArgs::MUST_VALUE);
    bool bExit = false;
    do
    {
        result.clear();
        cout << "input is:" << tmpPara << "---size = " << tmpPara.size()<< endl;
        std::string errPos;
        int iRet = pa.Parse(tmpPara,result, errPos);
        if(0>iRet)
        {
            cout << "参数错误" << iRet << errPos << endl;
        }
        else
        {
            map<std::string, std::vector<std::string> >::iterator it = result.begin();
            for(; it != result.end(); ++it)
            {
                cout << "key=" << it->first<<endl;
                for(int i=0; i<it->second.size(); ++i)
                {
                    cout << "   value =" << it->second[i] << "------" << endl;
                }
            }
        }
        string str;
        cout << ">>> ";
        getline(cin, tmpPara);
        if(0 == tmpPara.compare("exit"))
        {
            bExit = true;
        }

}while(!bExit);
    return 0;
}

parsingargs.h

代码如下:

#ifndef PARSINGARGS_H
#define PARSINGARGS_H
/* purpose @ 解析输入的参数,需先通过AddArgType将必须参数和可允许的参数key加入到判定列表中
 *          通过Parse中的result将结果返回,其中结果的key为合法的key,vecotr为参数列表
 *          参数列表支持去掉参数前后的引号和\对引号和\的转义
 *
 *          特殊合法字段:
 *          格式               实际存储值
 *          \\value\"            \value"
 *          "\\\value\""         \value"
 *
 *          注意事项:
 *              1、输入参数列表中参数分隔以空格区分
 *              2、- 后跟单字符关键字,--后跟长字符串关键字
 *              3、关键字不能重复出现,长短关键字不能同时出现在参数列表,否则会Parse函数会提示参数错误
 *
 *          用法:
 *              ParsingArgs pa;
 *              pa.AddArgType('l',"getlist", ParsingArgs::NO_VALUE); //NO_VALUE关键字后不能有参数
 *              pa.AddArgType('p',"getuser", ParsingArgs::MAYBE_VALUE); //MAYBE_VALUE 关键字后可能有关键字
 *              pa.AddArgType('o',"outFile", ParsingArgs::MUST_VALUE); // MUST_VALUE 关键字后必须有参数
 *              std::map<std::string, std::vector<std::string> > result;
 *              int iRet = pa.Parse(tmpPara,result); //result以输入关键字为key存储相关的值序列
 *
 * date    @ 2014.02.19
 * author  @ haibin.wang
 *
 */

#include <map>
#include <vector>
#include <string>

class ParsingArgs
{
public:
    ParsingArgs();
    ~ParsingArgs();
    enum KeyFlag{ INVALID_KEY=-1, NO_VALUE, MAYBE_VALUE, MUST_VALUE};
    /* pur @ 添加解释参数,一个参数可以是长参数,也可以是缩写的段参数,短参数只能为单字符,longName和shortName至少要有一个
     * para @ shortName 短参数名,0为不要短参数
     * para @ longName 长参数名 ,NULL为不要长参数
     * para @ flag 是否需要参数,0不需要,1必须要,2可要可不要
     * return @ true 添加成功,false添加失败
    */
    bool AddArgType(const char shortName, const char * longName = NULL, KeyFlag flag=NO_VALUE);

/* pur @ 根据参数类型解释传入的字符串
     * para @ paras 需要解释的字符串
     * para @ result 返回解析后的结果
     * para @ errPos 当错误的时候返回出错的大概位置
     * return @ 0 解释成功,负数 解释失败
     *          -1 未知参数错误
                -2 不能有参数的选项有参数错误
     *          -3 必有参数选项后没有跟参数
     *          -4 关键字没有加入到AddArgType中
     *          -5 关键字重复
    */
    int Parse(const std::string & paras, std::map<std::string, std::vector<std::string> > & result, std::string &errPos);

private:
    /* pur @ 判定传入的参数是否是已经添加的参数类型,如果是则去掉-或--,并返回
     * para @ key 要判定的参数
     * return @ -1 不是合法参数类型 否则返回Option中的flag
    */
    KeyFlag GetKeyFlag(std::string &key);

/* pur @ 删除关键字前的-或--
    */
    void RemoveKeyFlag(std::string & paras);

/* pur @ 从Paras中获取一个单词,自动过滤掉单词前后引号,并实现\对空格和引号的转义
     * para @ Paras 返回第一个单词后的所有内容
     * para @ word 返回第一单词
     * return @ 成功返回true,false失败
     */
    bool GetWord(std::string & Paras, std::string & word);

/* pur @ 检查关键字是否重复
     * para @ key 被检查的关键字
     * para @  result已存储的关键字序列
     * return @ true 是重复的,false不重复
    */
    bool IsDuplicateKey(const std::string &key, const std::map<std::string, std::vector<std::string> > & result);

struct Option
    {
        std::string m_longName;
        char m_shortName;
        KeyFlag m_flag;
    };

std::vector<Option> m_args; //参数信息列表
};

#endif

parsingargs.cpp

代码如下:

#include "parsingargs.h"
#include <list>

ParsingArgs::ParsingArgs()
{
}

ParsingArgs::~ParsingArgs()
{
}

bool ParsingArgs::AddArgType(char shortName, const char * longName, KeyFlag flag)
{
    if(NULL == longName && 0 == shortName)
    {
        return false;
    }
    Option tmp;
    tmp.m_longName = longName;
    tmp.m_shortName = shortName;
    tmp.m_flag = flag;
    m_args.push_back(tmp);
    return true;
}

ParsingArgs::KeyFlag ParsingArgs::GetKeyFlag(std::string &key) //返回flag,
{
    for(int i=0; i<m_args.size(); ++i)
    {
        std::string shortName = "-";
        std::string longName = "--";
        shortName += m_args[i].m_shortName;
        longName += m_args[i].m_longName;
        if( 0 == key.compare(shortName) ||
                (0==key.compare(longName))
            )
        {
            RemoveKeyFlag(key);
            return m_args[i].m_flag;
        }
    }
    return INVALID_KEY;
}

void ParsingArgs::RemoveKeyFlag(std::string & word)
{
    if(word.size()>=2)
    {
        if(word[1] == '-')
        {
            word.erase(1,1);
        }
        if(word[0] == '-')
        {
            word.erase(0,1);
        }
    }
}
/* pur @ 从Paras中获取一个单词,自动过滤掉单词前后引号,并实现\对空格和引号的转义
 * para @ Paras 返回第一个单词后的所有内容
 * para @ word 返回第一单词
 * return @ 成功返回true,false失败
*/
bool ParsingArgs::GetWord(std::string & Paras, std::string & word)
{
    size_t iNotSpacePos = Paras.find_first_not_of(' ',0);//查找第一个非空格字符位置
    if(iNotSpacePos == std::string::npos)
    {
        Paras.clear();
        word.clear();
        return true;
    }
    int length = Paras.size();
    std::list<char> specialChar;
    int islashPos = -1;
    for(int i=iNotSpacePos; i<length; i++)
    {
        char cur=Paras[i];
        bool bOk = false;
        switch(cur)
        {
            case ' ':
                if(specialChar.empty())
                {
                    if(i!=(length-1))
                    {
                        Paras = std::string(Paras, i+1, length-i-1);
                    }
                    else
                    {//最后一个是空格
                        Paras.clear();
                    }
                    bOk = true;
                }
                else
                {                   
                    if(specialChar.back() == '\\')
                    {
                        specialChar.pop_back();
                    }
                    word.append(1,cur);
                }
                break;
            case '"':
                if(specialChar.empty())
                {
                    specialChar.push_back(cur);
                }
                else if(specialChar.back() == cur)
                { //找到匹配的括号
                    specialChar.pop_back();
                }
                else if(specialChar.back() == '\\')
                {
                    word.append(1,cur);
                    specialChar.pop_back();
                }
                else
                {
                    word.clear();
                    return false;
                }
                break;
            case '\\':
                if(specialChar.empty())
                {
                    specialChar.push_back(cur);
                    islashPos = i;
                }
                else if(specialChar.back() == '"')
                {
                    if(i<(length-1))
                    {
                        if('"'==Paras[i+1] || '\\'==Paras[i+1])
                        {
                            specialChar.push_back(cur);
                        }
                        else
                        {
                            word.append(1,cur);
                        }
                    }
                    else
                    {
                        word.clear();
                        return false;
                    }
                }
                else if('\\' == specialChar.back())
                {
                     word.append(1,cur);
                     specialChar.pop_back();
                }
                else
                {
                    word.clear();
                    return false;
                }
                break;
            default:
                word.append(1,Paras[i]);
                if(i==(length-1))
                {
                    bOk = true;
                    Paras.clear();
                }
                break;
        }
        if(bOk)
        {
            return true;
        }
    }//for end
    if(specialChar.empty())
    {
        Paras.clear();
        return true;
    }
    else
    {
        return false;
    }
}

bool ParsingArgs::IsDuplicateKey(const std::string &key, const std::map<std::string, std::vector<std::string> > & result)
{
    if(result.find(key) != result.end())
    {
        return true; //关键字重复
    }

for(int i=0; i<m_args.size(); ++i)
    {
        if( (key.compare(m_args[i].m_longName) == 0 && result.find(std::string(1, m_args[i].m_shortName)) != result.end())
                || (key.compare(std::string(1, m_args[i].m_shortName)) == 0 && result.find(m_args[i].m_longName) != result.end())
          )
        {
            return true;
        }
    }
    return false;
}

int ParsingArgs::Parse(const std::string & Paras, std::map<std::string, std::vector<std::string> > & result, std::string &errPos)
{
    std::string tmpString = Paras;
    KeyFlag keyFlag = INVALID_KEY; //参数标识
    std::string sKey = ""; //key关键字
    bool bFindValue = false; //是否已经有value
    while(!tmpString.empty())
    {
        std::string word = "";

bool bRet = GetWord(tmpString, word);

if(bRet == false)
        {
            errPos = tmpString;
            return -4;//参数解析错误
        }
        else
        {
            KeyFlag tmpFlag = GetKeyFlag(word);
            if(IsDuplicateKey(word, result))
            {
                errPos = tmpString;
                return -5;
            }
            if(tmpFlag != INVALID_KEY)
            {
                if(tmpFlag == MUST_VALUE && keyFlag == MUST_VALUE && !bFindValue)
                {
                    errPos = tmpString;
                    return -3;
                }
                keyFlag = tmpFlag;
                std::vector<std::string> tmp;
                result[word] = tmp;
                sKey = word;
                bFindValue = false;
            }
            else
            {
                switch(keyFlag)
                {
                    case MAYBE_VALUE:
                    case MUST_VALUE:
                        {
                            std::map<std::string, std::vector<std::string> >::iterator it = result.find(sKey);
                            if(it != result.end())
                            {
                                it->second.push_back(word);
                                bFindValue = true;
                            }
                            else
                            {
                                errPos = tmpString;
                                return -1;// 没有发现相关的key
                            }
                        }
                        break;
                    case NO_VALUE:
                        errPos = tmpString;
                        return -2; //不能有参数的选项后有参数
                    default:
                        errPos = tmpString;
                        return -1;//参数错误
                }//switch end
            }
        }
    }//while end
    return 0;
}

(0)

相关推荐

  • c++实现通用参数解析类示例

    main.cpp 复制代码 代码如下: #include <iostream>#include <getopt.h>#include "parsingargs.h"#include <string.h> using namespace std; int main(int argc, char * argv[]){ //string tmpPara = "-p \"4567\" --out 1.log "; //

  • 使用Apache commons-cli包进行命令行参数解析的示例代码

    Apache的commons-cli包是专门用于解析命令行参数格式的包. 依赖: <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.3.1</version> </dependency> 使用此包需要: 1.先定义有哪些参数需要解析.哪些参数有额外的选项.每个参数的描述等等,对应

  • AngularJS页面带参跳转及参数解析操作示例

    本文实例讲述了AngularJS页面带参跳转及参数解析操作.分享给大家供大家参考,具体如下: 页面带参跳转 $scope.LoginSucessLocation = function () { var hre = 'http://ctb.qingguo.com/weixinCt/main#/upload_topic_start?uid=' + $scope.uid + '&orgcode=' + $scope.orgCode; location.href = hre; } 在url的后面,增加?

  • mybatis查询语句揭秘之参数解析

    一.前言 通过前面我们也知道,通过getMapper方式来进行查询,最后会通过mapperMehod类,对接口中传来的参数也会在这个类里面进行一个解析,随后就传到对应位置,与sql里面的参数进行一个匹配,最后获取结果.对于mybatis通常传参(这里忽略掉Rowbounds和ResultHandler两种类型)有几种方式. 1.javabean类型参数 2.非javabean类型参数 注意,本文是基于mybatis3.5.0版本进行分析. 1.参数的存储 2.对sql语句中参数的赋值 下面将围绕

  • python命令行参数解析OptionParser类用法实例

    本文实例讲述了python命令行参数解析OptionParser类的用法,分享给大家供大家参考. 具体代码如下: from optparse import OptionParser parser = OptionParser(usage="usage:%prog [optinos] filepath") parser.add_option("-t", "--timeout", action = "store", type =

  • SpringMVC中常用参数校验类注解使用示例教程

    目录 一.环境准备 二.常用的校验注解及示例 三.校验类方法中的普通参数 四.校验类方法中的自定义对象 五.关于@Valid和@Validated的区别联系 六.分组校验 七.自定义校验注解 一.环境准备 在项目中添加以下依赖 gradle org.hibernate:hibernate-validator:5.3.5.Final maven <dependency> <groupId>org.hibernate</groupId> <artifactId>

  • SpringMVC接收复杂集合对象(参数)代码示例

    SpringMVC在接收集合请求参数时,需要在Controller方法的集合参数里前添加@RequestBody,而@RequestBody默认接收的enctype(MIME编码)是application/json,因此发送POST请求时需要设置请求报文头信息,否则SpringMVC在解析集合请求参数时不会自动的转换成JSON数据再解析成相应的集合.以下列举接收List<String>.List<User>.List<Map<String,Object>>.

  • Java通用Mapper UUID简单示例

    #通用 Mapper UUID 简单示例 ##不可回写的 UUID 通用 Mapper 中对 UUID 的用法主要提到了一种专有的写法,如下写法: @GeneratedValue(generator = "UUID") 这种方式实现很容易理解,就是在你 insert 之前,调用 UUID 的公共方法在<bind> 标签中生成了一个值,插入到了数据库,由于这个值是临时的,并没有set到对象,因此这种方式是不支持回写的. 由于回写方式很常见,因此用这种方式很难满足要求. 而且在

  • SpringBoot整合POI导出通用Excel的方法示例

    一.准备工作 1.pom依赖 在pom.xml中加入POI的依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.11-beta1</version> </dependency> <dependency> <groupId>org.apache.poi

  • Python 利用argparse模块实现脚本命令行参数解析

    study.py内容如下 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'shouke' import argparse def argparseFunc(): ''' 基于argparse模块实现命令参数解析功能 执行示例: python study.py -i 172.19.7.236 -p 8080 -a -r python study.py --ip 172.19.7.236 --port 7077 --auth -w

随机推荐