原文链接:
Command line parser

作者所考虑的语法是:
CommandLine::
=
[
<
Key
>
[,
<
Key
>
]]
<
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());
}

#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;
}

作者所考虑的语法是:
CommandLine::
=
[
<
Key
>
[,
<
Key
>
]]
<
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());
}

#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;
}
34

被折叠的 条评论
为什么被折叠?



