使用命令行执行程序的时候在程序后可跟多个参数列表,而main函数的argc和argv分别存储了相关的参数个数和参数内容,而循环输入相关的时候就需要用户自己来解析相关参数。以下代码用c++的方式实现了相关解析的封装,使用起来非常方便。具体代码如下,
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; }
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; }
如果发现相关bug请发邮件至fly542@163.com QQ:634648088
转载请注明出处。