一个面向对象的命令行解析器

这个类能解析如下格式的参数:
  • -b
  • -h www.codeproject.com
  • stdafx.cpp
  • -temp:-7

除此以外,还可以解析以“”或“/”打头的参数。

一般有三类参数需要解析:

  • 作为标识的参数(例如“ls –l”),这叫空参数
  • 有其值的参数(例如“netstat –p tcp”),这叫值参数
  • 不带任何“-”的(例如“copy a.cpp b.cpp”),这叫默认参数。

#include
< map >
#include
< string >


#define UNKNOWN_PARAM"UNKNOWN_PARAM"
#define NO_VALUE_PARAM"PARAM_NO_VALUE"
#define GENERIC_ERROR"GENERIC_ERROR"

/**/ /**
Interfacethatmustbeimplementedbytheobjectsthatrequiresaccesstothe
commandlinearguments.
@seeCCommandLineParser
*/

class ICmdLineParam
{
public:
/**//**
MethodcalledbytheCCommandLineParsertopasstheargumentsandthevalues.
Theparsercallsthismethodtoindicatethenameoftheargumentsand/or
thevaluesonlywhenapplicable.The'-'or'/'oftheargumentsareeliminated
beforereachthismethod.
@returnfalseonlyiftheparsermuststop,onaseriouserror.
truewhentheargumentisOKorismalformed,inthissecondcase
thefunctionGetErrormustreturnadescription,seebelow.
*/

virtualboolParse(std::stringargument,std::stringvalue)=0;

/**//**MethodcalledbytheCCommandLineParsertoretrievetheerrordescription.
//ifanfailincommandlineoccurs,thismethodmustreturnadescriptionoftheerror.
//Ex:"Inaccesibleinputfile","invalidtypeofalgorithm",..,etc.
@retrun""toindicatethatnoerrorwasproduced.
*/

virtualstd::stringGetError()=0;

}
;


class CCommandLineParser
{
public:
CCommandLineParser()
{m_defaultCommand=NULL;}
/**//**
Objectthathandlethedefaultarguments.Onlyonecanbespecified.
*/

voidSetDefaultCommand(ICmdLineParam*e);
/**//**
Objectsthathandletheemptyarguments.Canbecalledhowmanytimesasnecesary.
@paramparanameoftheargumentthatthisICmdLineParamexpect.
@eICmdLineParam
*/

voidPutEmptyCommand(std::stringargument,ICmdLineParam*e);
/**//**
Entrythathandlethevaluesarguments.Canbecalledhowmanytimesasnecesary.
@paramparanameoftheargumentthatthisICmdLineParamexpect.
@eICmdLineParam
*/

voidPutValueCommand(std::stringargument,ICmdLineParam*e);
/**//**
EntrythathandletheerrorsoftheCCommandLineParser.Onlyonecanbespecified.
*/

voidSetErrorCommand(ICmdLineParam*e);


/**//**
Initstheparseprocess.
@paramargnnumberofargumentspassedtotheapplication.
@paramargvarrayofstringwiththeargumentspassedtotheapplication.
*/

boolParseArguments(intargn,char*argv[]);
private:
ICmdLineParam
*m_defaultCommand;
ICmdLineParam
*m_errorCommand;
std::map
<std::string,ICmdLineParam*>m_mapValueCommand;//值参数映射表
std::map<std::string,ICmdLineParam*>m_mapEmptyCommand;//空参数映射表

/**//**
Deletesthe'-','--','/'oftheargument.
@return<b>true</b>iftheargumentisnotavalue.
*/

boolDeleteMinus(std::string&param);
}
;

void CCommandLineParser::SetDefaultCommand(ICmdLineParam * obj)
{
m_defaultCommand
=obj;
}

void CCommandLineParser::PutEmptyCommand(std:: string argument,ICmdLineParam * obj)
{
m_mapEmptyCommand[argument]
=obj;

}

void CCommandLineParser::PutValueCommand(std:: string argument,ICmdLineParam * obj)
{
m_mapValueCommand[argument]
=obj;
}

void CCommandLineParser::SetErrorCommand(ICmdLineParam * obj)
{
m_errorCommand
=obj;
}



bool CCommandLineParser::ParseArguments( int argn, char * argv[])
{
boolbAllOK=true;
inti=1;//Firstparamterisdiscardedbecouseit'stheexecutionprogrampath.

while(i<argn)
{

std::
stringargument=argv[i];//当前待处理的参数

if(DeleteMinus(argument))
{
//到值参数映射表中寻找待设置的值参数
//Checkifthisargumentrequiresavalue.
std::map<std::string,ICmdLineParam*>::iteratorit=m_mapValueCommand.find(argument);

if(it!=m_mapValueCommand.end())
{//值参数表中存在
if(argv[i+1]==NULL)
{//没有提供值
bAllOK&=m_errorCommand->Parse(NO_VALUE_PARAM,argument);
returnfalse;
}

std::
stringpaso=argv[i+1];
if(DeleteMinus(paso))
{//没有提供值
bAllOK&=m_errorCommand->Parse(NO_VALUE_PARAM,argument);
returnfalse;
}

else
{
bAllOK
&=it->second->Parse(argument,paso);//解析出值
i++;
}

}

else
{//值参数表中不存在
it=m_mapEmptyCommand.find(argument);//到空参数表中寻找
if(it!=m_mapEmptyCommand.end())
{//找到了
bAllOK&=it->second->Parse(argument,"");
}

else
{//用户设置的格式是”参数:值“,对这种情况进行解析
//Trytosplita":"
std::string::size_typeposition=argument.find_first_of(":");
if(position!=std::string::npos)
{
std::
stringcommand=argument.substr(0,position);
std::
stringvalue=argument.substr(position+1);
//到值参数映射表中寻址
std::map<std::string,ICmdLineParam*>::iteratorit=m_mapValueCommand.find(command);
if(it!=m_mapValueCommand.end())
{//找到
bAllOK&=it->second->Parse(command,value);
}

else
{//不存在
bAllOK&=m_errorCommand->Parse(UNKNOWN_PARAM,command);
returnfalse;
}

}

else
{//未知参数
bAllOK&=m_errorCommand->Parse(UNKNOWN_PARAM,argument);
returnfalse;
}

}


}

}

else
{//不是附加参数,而是默认参数
if(m_defaultCommand!=NULL)
{
bAllOK
&=m_defaultCommand->Parse("",argument);
}

else
{
returnfalse;
}

}

i
++;
}

//错误处理
std::stringerror=m_defaultCommand->GetError();
if(error!="")
{
m_errorCommand
->Parse(GENERIC_ERROR,error);
returnfalse;
}



std::map
<std::string,ICmdLineParam*>::iteratorit=m_mapValueCommand.begin();

while(it!=m_mapValueCommand.end())
{
error
=it->second->GetError();
if(error!="")
{
m_errorCommand
->Parse(GENERIC_ERROR,error);
returnfalse;
}

it
++;
}


std::map
<std::string,ICmdLineParam*>::iteratorit2=m_mapEmptyCommand.begin();

while(it2!=m_mapEmptyCommand.end())
{
error
=it2->second->GetError();
if(error!="")
{
m_errorCommand
->Parse(GENERIC_ERROR,error);
returnfalse;
}

it2
++;
}



returnbAllOK;//Devuelvefalsesihahabidoerror.
}


bool CCommandLineParser::DeleteMinus(std:: string & argument)
{//去掉参数前的分隔符
switch(argument[0])
{
case'/':
argument
=&(argument.c_str()[1]);
returntrue;
case'-':
if(argument[1]=='-')
{
argument
=&(argument.c_str()[2]);
}

else
{
argument
=&(argument.c_str()[1]);
}

returntrue;
}



returnfalse;
}


测试程序
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#defineAPP_USAGE"Usage:hashfile[-algmd5|sha1][-outhex]file/nDefault:-algmd5-outhex/n"

classCHashType:publicICmdLineParam
{
enumtypes{MD5,SHA1};//hash类型

typesm_type;
stringm_strError;//上次错误字段
public:
CHashType()
{
m_strError
="";
m_type
=MD5;//默认hash类型
}


boolParse(stringargument,stringvalue)
{//alg是参数名称,value是参数值
if(argument=="alg")
{
if(value=="md5")
{
m_type
=MD5;
}

elseif(value=="sha1")
{
m_type
=SHA1;
}

else
{
m_strError
="Incorrecthashalgorithm.Correctvalues(casesensitive):md5,sha1.Defaultmd5.";
returnfalse;
}

}

returntrue;
}


stringGetError()
{
returnm_strError;
}

voidCalcHash(stringstrFileName,unsignedchar*&outbuffer,DWORD&rdwDataLen)
{//用指定算法进行Hash加密计算
unsignedintdLenBuffer=1024;
unsigned
intdDataLen=0;
FILE
*hFile=fopen(strFileName.c_str(),"rb");
outbuffer
=newunsignedchar[dLenBuffer];
GUIDg;
CoCreateGuid(
&g);
charszContName[100];
_snprintf(szContName,
100,"%u-%u-%u-%u",g.Data1,g.Data2,g.Data3,g.Data4);
HCRYPTPROVhProv;
if(CryptAcquireContext(&hProv,szContName,MS_DEF_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET))
{

}

else
{
HandleError(
"CryptAcquireContext1fail");
}

ALG_IDalg_id
=CALG_MD5;
switch(m_type)
{
caseSHA1:
alg_id
=CALG_SHA1;
break;
caseMD5:
alg_id
=CALG_MD5;
break;
}
;
HCRYPTHASHhHash;
if(CryptCreateHash(hProv,alg_id,0,0,&hHash))
{
}

else
{
HandleError(
"CryptCreateHashfail");
}

while(!feof(hFile))
{
dDataLen
=fread(outbuffer,1,dLenBuffer,hFile);
if(CryptHashData(hHash,outbuffer,dDataLen,0))
{
}

else
{
HandleError(
"CryptHashDatafail");
}

}

rdwDataLen
=1024;
if(CryptGetHashParam(hHash,HP_HASHVAL,outbuffer,&rdwDataLen,0))
{
}

else
{
HandleError(
"CryptHashDatafail");
}

fclose(hFile);
CryptReleaseContext(hProv,
0);
CryptAcquireContext(
&hProv,szContName,MS_DEF_PROV,PROV_RSA_FULL,CRYPT_DELETEKEYSET);
}



}
;

classCOutputType:publicICmdLineParam
{
enumtypes{HEX};//输出进制
typesm_type;
stringm_strError;
public:
COutputType()
{
m_type
=HEX;//默认是十六进制
}

boolParse(stringargument,stringvalue)
{
if(argument=="out")
{
if(value=="hex")
{
m_type
=HEX;
}

else
{
m_strError
="Incorrectoutputtypecodification.Correctvalues(casesensitive):hex.Defaulthex.";
returnfalse;
}


}

returntrue;
}


stringGetError()
{
returnm_strError;
}


voidOutputHash(unsignedchar*inbuffer,DWORDdwDataLen)
{
charcad[3];

switch(m_type)
{
caseHEX:
for(inti=0;i<dwDataLen;i++)
{
sprintf(cad,
"%02x",inbuffer[i]);
cout
<<cad;
}

break;
}

}

}
;
classCFileHash:publicICmdLineParam
{
stringm_filename;
stringm_strError;
public:
CFileHash()
{
m_filename
="";
m_strError
="";
}

stringGetFileName()
{
returnm_filename;
}

boolParse(stringargument,stringvalue)
{
if(argument=="")
{
m_filename
=value;

if(access(m_filename.c_str(),04)!=0)
{
m_strError
="Inaccesibleinputfile:"+value;
returnfalse;
}


}

returntrue;
}

stringGetError()
{
if(m_filename=="")
{
return"Mustspecifyafilename.";
}



returnm_strError;
}

}
;

classCError:publicICmdLineParam
{

public:
boolm_displayHelp;
CError()
{
m_displayHelp
=false;
}


boolParse(stringargument,stringvalue)
{//对错误类型进行处理
if(argument=="h")
{
m_displayHelp
=true;
returnfalse;

}

if(argument==GENERIC_ERROR)
{
cout
<<value<<endl<<endl;
cout
<<APP_USAGE;
returnfalse;
}

if(argument==UNKNOWN_PARAM)
{
cout
<<"Invalidargument'"<<value<<"'."<<endl<<endl;
cout
<<APP_USAGE;
returnfalse;
}

if(argument==NO_VALUE_PARAM)
{
cout
<<"Emptyargument'"<<value<<"'mustspecifyonevalue."<<endl<<endl;
cout
<<APP_USAGE;
returnfalse;
}


returntrue;
}



stringGetError()
{
if(m_displayHelp)
{
returnAPP_USAGE;
}

else
{
return"";
}

}

}
;



intmain(intargc,char*argv[])
{
CCommandLineParserparser;
COutputTypeoutput;
CHashTypehash;
CErrorerr;
CFileHashfile;


parser.PutValueCommand(
"out",&output);//第一个值参数
parser.PutValueCommand("alg",&hash);//第二个值参数
parser.SetDefaultCommand(&file);
parser.PutEmptyCommand(
"h",&err);//第一个空参数
parser.PutEmptyCommand("help",&err);//第二个空参数
parser.SetErrorCommand(&err);

if(parser.ParseArguments(argc,argv))
{

unsigned
char*inbuffer=NULL;
DWORDdwDataLen
=1024;

//数据进行hash计算
hash.CalcHash(file.GetFileName().c_str(),inbuffer,dwDataLen);
output.OutputHash(inbuffer,dwDataLen);
//输出

delete[]inbuffer;

}

system(
"pause");


return0;
}



voidHandleError(char*s)
{
charmessage[1000];
intlength=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),0,message,1000,NULL);

fprintf(stderr,
"Anerroroccurredinrunningtheprogram./n");
fprintf(stderr,
"%s/n",s);
fprintf(stderr,
"Errornumber%x:%s./n",GetLastError(),message);
fprintf(stderr,
"Programterminating./n");
exit(
1);
}
//EndofHandleError


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值