原文链接:
Command line parser
作者所考虑的语法是:
typedefCStringCCmdLineParser_String;
#include < map >
using std::map;
class CCmdLineParser
{
public:
classCValsMap:publicmap<CCmdLineParser_String,CCmdLineParser_String>{};//存储关键字--值对
typedefCValsMap::const_iteratorPOSITION;//迭代器
public:
CCmdLineParser(LPCTSTRsCmdLine=NULL,boolbCaseSensitive=false);//默认大小写不敏感
virtual~CCmdLineParser();
boolParse(LPCTSTRsCmdLine);//解析命令行
LPCTSTRgetCmdLine()const{returnm_sCmdLine;}
voidsetCaseSensitive(boolbSensitive){m_bCaseSensitive=bSensitive;}
boolgetCaseSensitive()const{returnm_bCaseSensitive;}
constCValsMap&getVals()const{returnm_ValsMap;}
//Startiteratingthroughkeysandvalues
POSITIONgetFirst()const;//第一个
//Getnextkey-valuepair,returnsemptysKeyifendreached
POSITIONgetNext(POSITION&pos,CCmdLineParser_String&sKey,CCmdLineParser_String&sValue)const;//迭代器往后
//justhelper;)
boolisLast(POSITION&pos)const;//是否是最后一个
//TRUEif"Key"presentincommandline
boolHasKey(LPCTSTRsKey)const;//是否包含指定关键字
//Is"key"presentincommandlineandhavesomevalue
boolHasVal(LPCTSTRsKey)const;//是否包含指定值
//ReturnsvalueifvaluewasfoundorNULLotherwise
LPCTSTRGetVal(LPCTSTRsKey)const;//获取值
//Returnstrueifvaluewasfound
boolGetVal(LPCTSTRsKey,CCmdLineParser_String&sValue)const;
private:
CValsMap::const_iteratorfindKey(LPCTSTRsKey)const;//查找指定关键字
private:
CCmdLineParser_Stringm_sCmdLine;
CValsMapm_ValsMap;
boolm_bCaseSensitive;
staticconstTCHARm_sDelimeters[];
staticconstTCHARm_sValueSep[];
staticconstTCHARm_sQuotes[];
} ;
作者所考虑的语法是:
CommandLine::
=
[
<
Key
>
[,
<
Key
>
]]
< Key > :: =< Delimeter > KeyName[ < Separator >< Value > ]
< Value > :: = {KeyValue|<QuoteChar>QuotedKeyValue<QuoteChar>} ][
< Delimeter > :: = {-|/}
< Separator > :: = {:}
< QuoteChar > :: = {"}
< Key > :: =< Delimeter > KeyName[ < Separator >< Value > ]
< Value > :: = {KeyValue|<QuoteChar>QuotedKeyValue<QuoteChar>} ][
< Delimeter > :: = {-|/}
< Separator > :: = {:}
< QuoteChar > :: = {"}
typedefCStringCCmdLineParser_String;
#include < map >
using std::map;
class CCmdLineParser
{
public:
classCValsMap:publicmap<CCmdLineParser_String,CCmdLineParser_String>{};//存储关键字--值对
typedefCValsMap::const_iteratorPOSITION;//迭代器
public:
CCmdLineParser(LPCTSTRsCmdLine=NULL,boolbCaseSensitive=false);//默认大小写不敏感
virtual~CCmdLineParser();
boolParse(LPCTSTRsCmdLine);//解析命令行
LPCTSTRgetCmdLine()const{returnm_sCmdLine;}
voidsetCaseSensitive(boolbSensitive){m_bCaseSensitive=bSensitive;}
boolgetCaseSensitive()const{returnm_bCaseSensitive;}
constCValsMap&getVals()const{returnm_ValsMap;}
//Startiteratingthroughkeysandvalues
POSITIONgetFirst()const;//第一个
//Getnextkey-valuepair,returnsemptysKeyifendreached
POSITIONgetNext(POSITION&pos,CCmdLineParser_String&sKey,CCmdLineParser_String&sValue)const;//迭代器往后
//justhelper;)
boolisLast(POSITION&pos)const;//是否是最后一个
//TRUEif"Key"presentincommandline
boolHasKey(LPCTSTRsKey)const;//是否包含指定关键字
//Is"key"presentincommandlineandhavesomevalue
boolHasVal(LPCTSTRsKey)const;//是否包含指定值
//ReturnsvalueifvaluewasfoundorNULLotherwise
LPCTSTRGetVal(LPCTSTRsKey)const;//获取值
//Returnstrueifvaluewasfound
boolGetVal(LPCTSTRsKey,CCmdLineParser_String&sValue)const;
private:
CValsMap::const_iteratorfindKey(LPCTSTRsKey)const;//查找指定关键字
private:
CCmdLineParser_Stringm_sCmdLine;
CValsMapm_ValsMap;
boolm_bCaseSensitive;
staticconstTCHARm_sDelimeters[];
staticconstTCHARm_sValueSep[];
staticconstTCHARm_sQuotes[];
} ;
const
TCHARCCmdLineParser::m_sDelimeters[]
=
_T(
"
-/
"
);
//
键的起始符
const TCHARCCmdLineParser::m_sQuotes[] = _T( " / "" );//Canbe_T( " / " /' " ), for instance
const TCHARCCmdLineParser::m_sValueSep[] = _T( " : " ); // SpaceMUSTbeinset键值分隔符
/**/ //
// Construction/Destruction
/**/ //
CCmdLineParser::CCmdLineParser(LPCTSTRsCmdLine, bool bCaseSensitive)
:m_bCaseSensitive(bCaseSensitive)
{
if(sCmdLine)
{
Parse(sCmdLine);
}
}
CCmdLineParser:: ~ CCmdLineParser()
{
m_ValsMap.clear();
}
bool CCmdLineParser::Parse(LPCTSTRsCmdLine)
{
if(!sCmdLine)returnfalse;
m_sCmdLine=sCmdLine;
m_ValsMap.clear();
constCCmdLineParser_StringsEmpty;
intnArgs=0;
LPCTSTRsCurrent=sCmdLine;
while(true){
///Key:"arg"
if(_tcslen(sCurrent)==0){break;}//Nodataleft
LPCTSTRsArg=_tcspbrk(sCurrent,m_sDelimeters);
if(!sArg)break;//Nodelimetersfound
sArg=_tcsinc(sArg);
//Key:"arg"
if(_tcslen(sArg)==0)break;//Stringendswithdelimeter
LPCTSTRsVal=_tcspbrk(sArg,m_sValueSep);
if(sVal==NULL){//Keyendscommandline
CCmdLineParser_StringcsKey(sArg);
if(!m_bCaseSensitive){
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey,sEmpty));
break;
}elseif(sVal[0]==_T('')||_tcslen(sVal)==1){//Keywithnovalueorcmdlineendswith/Key:
CCmdLineParser_StringcsKey(sArg,sVal-sArg);
if(!csKey.IsEmpty()){//Prevent/:case
if(!m_bCaseSensitive){
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey,sEmpty));
}
sCurrent=_tcsinc(sVal);
continue;
}else{//Keywithvalue
CCmdLineParser_StringcsKey(sArg,sVal-sArg);
if(!m_bCaseSensitive){
csKey.MakeLower();
}
sVal=_tcsinc(sVal);
//"arg"
LPCTSTRsQuote=_tcspbrk(sVal,m_sQuotes),sEndQuote(NULL);
if(sQuote==sVal){//QuotedString
sQuote=_tcsinc(sVal);
sEndQuote=_tcspbrk(sQuote,m_sQuotes);
}else{
sQuote=sVal;
sEndQuote=_tcschr(sQuote,_T(''));
}
if(sEndQuote==NULL){//Noendquotesorterminatingspace,takerestofstring
CCmdLineParser_StringcsVal(sQuote);
if(!csKey.IsEmpty()){//Prevent/:valcase
m_ValsMap.insert(CValsMap::value_type(csKey,csVal));//保存
}
break;
}else{//Endquoteorspacepresent
if(!csKey.IsEmpty()){//Prevent/:"val"case
CCmdLineParser_StringcsVal(sQuote,sEndQuote-sQuote);
m_ValsMap.insert(CValsMap::value_type(csKey,csVal));
}
sCurrent=_tcsinc(sEndQuote);
continue;
}
}
}
return(nArgs>0);
}
CCmdLineParser::CValsMap::const_iteratorCCmdLineParser::findKey(LPCTSTRsKey) const
{
CCmdLineParser_Strings(sKey);
if(!m_bCaseSensitive){
s.MakeLower();
}
returnm_ValsMap.find(s);
}
// TRUEif"Key"presentincommandline
bool CCmdLineParser::HasKey(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
returntrue;
}
// Is"key"presentincommandlineandhavesomevalue
bool CCmdLineParser::HasVal(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
if(it->second.IsEmpty())returnfalse;
returntrue;
}
// ReturnsvalueifvaluewasfoundorNULLotherwise
LPCTSTRCCmdLineParser::GetVal(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
returnLPCTSTR(it->second);
}
// Returnstrueifvaluewasfound
bool CCmdLineParser::GetVal(LPCTSTRsKey,CCmdLineParser_String & sValue) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
sValue=it->second;
returntrue;
}
CCmdLineParser::POSITIONCCmdLineParser::getFirst() const
{
returnm_ValsMap.begin();
}
CCmdLineParser::POSITIONCCmdLineParser::getNext(POSITION & pos,CCmdLineParser_String & sKey,CCmdLineParser_String & sValue) const
{
if(isLast(pos)){
sKey.Empty();
returnpos;
}else{
sKey=pos->first;
sValue=pos->second;
pos++;
returnpos;
}
}
// justhelper;)
bool CCmdLineParser::isLast(POSITION & pos) const
{
return(pos==m_ValsMap.end());
}
const TCHARCCmdLineParser::m_sQuotes[] = _T( " / "" );//Canbe_T( " / " /' " ), for instance
const TCHARCCmdLineParser::m_sValueSep[] = _T( " : " ); // SpaceMUSTbeinset键值分隔符
/**/ //
// Construction/Destruction
/**/ //
CCmdLineParser::CCmdLineParser(LPCTSTRsCmdLine, bool bCaseSensitive)
:m_bCaseSensitive(bCaseSensitive)
{
if(sCmdLine)
{
Parse(sCmdLine);
}
}
CCmdLineParser:: ~ CCmdLineParser()
{
m_ValsMap.clear();
}
bool CCmdLineParser::Parse(LPCTSTRsCmdLine)
{
if(!sCmdLine)returnfalse;
m_sCmdLine=sCmdLine;
m_ValsMap.clear();
constCCmdLineParser_StringsEmpty;
intnArgs=0;
LPCTSTRsCurrent=sCmdLine;
while(true){
///Key:"arg"
if(_tcslen(sCurrent)==0){break;}//Nodataleft
LPCTSTRsArg=_tcspbrk(sCurrent,m_sDelimeters);
if(!sArg)break;//Nodelimetersfound
sArg=_tcsinc(sArg);
//Key:"arg"
if(_tcslen(sArg)==0)break;//Stringendswithdelimeter
LPCTSTRsVal=_tcspbrk(sArg,m_sValueSep);
if(sVal==NULL){//Keyendscommandline
CCmdLineParser_StringcsKey(sArg);
if(!m_bCaseSensitive){
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey,sEmpty));
break;
}elseif(sVal[0]==_T('')||_tcslen(sVal)==1){//Keywithnovalueorcmdlineendswith/Key:
CCmdLineParser_StringcsKey(sArg,sVal-sArg);
if(!csKey.IsEmpty()){//Prevent/:case
if(!m_bCaseSensitive){
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey,sEmpty));
}
sCurrent=_tcsinc(sVal);
continue;
}else{//Keywithvalue
CCmdLineParser_StringcsKey(sArg,sVal-sArg);
if(!m_bCaseSensitive){
csKey.MakeLower();
}
sVal=_tcsinc(sVal);
//"arg"
LPCTSTRsQuote=_tcspbrk(sVal,m_sQuotes),sEndQuote(NULL);
if(sQuote==sVal){//QuotedString
sQuote=_tcsinc(sVal);
sEndQuote=_tcspbrk(sQuote,m_sQuotes);
}else{
sQuote=sVal;
sEndQuote=_tcschr(sQuote,_T(''));
}
if(sEndQuote==NULL){//Noendquotesorterminatingspace,takerestofstring
CCmdLineParser_StringcsVal(sQuote);
if(!csKey.IsEmpty()){//Prevent/:valcase
m_ValsMap.insert(CValsMap::value_type(csKey,csVal));//保存
}
break;
}else{//Endquoteorspacepresent
if(!csKey.IsEmpty()){//Prevent/:"val"case
CCmdLineParser_StringcsVal(sQuote,sEndQuote-sQuote);
m_ValsMap.insert(CValsMap::value_type(csKey,csVal));
}
sCurrent=_tcsinc(sEndQuote);
continue;
}
}
}
return(nArgs>0);
}
CCmdLineParser::CValsMap::const_iteratorCCmdLineParser::findKey(LPCTSTRsKey) const
{
CCmdLineParser_Strings(sKey);
if(!m_bCaseSensitive){
s.MakeLower();
}
returnm_ValsMap.find(s);
}
// TRUEif"Key"presentincommandline
bool CCmdLineParser::HasKey(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
returntrue;
}
// Is"key"presentincommandlineandhavesomevalue
bool CCmdLineParser::HasVal(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
if(it->second.IsEmpty())returnfalse;
returntrue;
}
// ReturnsvalueifvaluewasfoundorNULLotherwise
LPCTSTRCCmdLineParser::GetVal(LPCTSTRsKey) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
returnLPCTSTR(it->second);
}
// Returnstrueifvaluewasfound
bool CCmdLineParser::GetVal(LPCTSTRsKey,CCmdLineParser_String & sValue) const
{
CValsMap::const_iteratorit=findKey(sKey);
if(it==m_ValsMap.end())returnfalse;
sValue=it->second;
returntrue;
}
CCmdLineParser::POSITIONCCmdLineParser::getFirst() const
{
returnm_ValsMap.begin();
}
CCmdLineParser::POSITIONCCmdLineParser::getNext(POSITION & pos,CCmdLineParser_String & sKey,CCmdLineParser_String & sValue) const
{
if(isLast(pos)){
sKey.Empty();
returnpos;
}else{
sKey=pos->first;
sValue=pos->second;
pos++;
returnpos;
}
}
// justhelper;)
bool CCmdLineParser::isLast(POSITION & pos) const
{
return(pos==m_ValsMap.end());
}
#include
"
stdafx.h
"
#include " cmdlineparser.h "
int main( int argc, char * argv[])
{
CCmdLineParserparser(_T("/Key1/Key2:-Key3:Val3-Key4:/"Val4-with/spaces/and-delimeters/"/Key5:Val5"));
ASSERT(parser.HasKey(_T("Key1"))==true);
ASSERT(parser.HasKey(_T("Key10"))==false);
ASSERT(parser.HasVal(_T("Key2"))==false);
ASSERT(parser.HasKey(_T("Key5"))==true);
_tprintf(_T("====================TestParser====================/n"));
_tprintf(_T("Commandline:[%s]/n"),parser.getCmdLine());//获取命令行参数
_tprintf(_T("Key1hasvalue:[%s]/n"),parser.GetVal(_T("Key1")));//->[];//(emptystring)
_tprintf(_T("Key2hasvalue:[%s]/n"),parser.GetVal(_T("Key2")));//->[];
_tprintf(_T("Key3hasvalue:[%s]/n"),parser.GetVal(_T("Key3")));//->[Val3];
_tprintf(_T("Key4hasvalue:[%s]/n"),parser.GetVal(_T("Key4")));//->[Val4-with/spaces/and-delimeters];
_tprintf(_T("Key5hasvalue:[%s]/n"),parser.GetVal(_T("Key5")));//->[];//(emptystring)
_tprintf(_T("/n=================RealCommandLine=================/n"));
CCmdLineParserrealParser(::GetCommandLine());
CCmdLineParser::POSITIONpos=realParser.getFirst();
CStringsKey,sVal;
while(!realParser.isLast(pos))
{
realParser.getNext(pos,sKey,sVal);
_tprintf(_T("Key:[%s],Val:[%s]/n"),sKey,sVal);
}
system("pause");
return0;
}
#include " cmdlineparser.h "
int main( int argc, char * argv[])
{
CCmdLineParserparser(_T("/Key1/Key2:-Key3:Val3-Key4:/"Val4-with/spaces/and-delimeters/"/Key5:Val5"));
ASSERT(parser.HasKey(_T("Key1"))==true);
ASSERT(parser.HasKey(_T("Key10"))==false);
ASSERT(parser.HasVal(_T("Key2"))==false);
ASSERT(parser.HasKey(_T("Key5"))==true);
_tprintf(_T("====================TestParser====================/n"));
_tprintf(_T("Commandline:[%s]/n"),parser.getCmdLine());//获取命令行参数
_tprintf(_T("Key1hasvalue:[%s]/n"),parser.GetVal(_T("Key1")));//->[];//(emptystring)
_tprintf(_T("Key2hasvalue:[%s]/n"),parser.GetVal(_T("Key2")));//->[];
_tprintf(_T("Key3hasvalue:[%s]/n"),parser.GetVal(_T("Key3")));//->[Val3];
_tprintf(_T("Key4hasvalue:[%s]/n"),parser.GetVal(_T("Key4")));//->[Val4-with/spaces/and-delimeters];
_tprintf(_T("Key5hasvalue:[%s]/n"),parser.GetVal(_T("Key5")));//->[];//(emptystring)
_tprintf(_T("/n=================RealCommandLine=================/n"));
CCmdLineParserrealParser(::GetCommandLine());
CCmdLineParser::POSITIONpos=realParser.getFirst();
CStringsKey,sVal;
while(!realParser.isLast(pos))
{
realParser.getNext(pos,sKey,sVal);
_tprintf(_T("Key:[%s],Val:[%s]/n"),sKey,sVal);
}
system("pause");
return0;
}