c++实现通用参数解析类示例
c++实现通用参数解析类示例
发布时间:2016-12-28 来源:查字典编辑
摘要:main.cpp复制代码代码如下:#include#include#include"parsingargs.h"#includeusingn...

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;

}

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新C语言学习
热门C语言学习
编程开发子分类