C++: Command Line Processing
Save this code here for studying and using it.
Surce code is here.
CmdLine.h File
#pragma once
#include "unicodemacro.h"
#include <vector>
#include <map> namespace Utility
{ // handy little container for our argument vector
struct CmdParam {
std::vector<tstring> strings_;
}; /**
A utility for parsing command lines. This was originally written by Chris Losinger, changes were simply
removing the inheritance from std::map<>, and adding a map as a member
variable instead. then all the VCF related String was replaced with
tstring and can suite both unicode and non-unicode string Example : Our example application uses a command line that has two
required switches and two optional switches. The app should abort
if the required switches are not present and continue with default
values if the optional switches are not present. Sample command line :
MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2 Switches -p1 and -p2 are required.
p1 has two arguments and p2 has one. Switches -opt1 and -opt2 are optional.
opt1 requires a numeric argument.
opt2 has no arguments. Also, assume that the app displays a 'help' screen if the '-h' switch
is present on the command line. \code
#include "cmdline.h"
using namespace Utility;
using namespace std;
void show_help()
{
tcout<< _T("This is a help string") <<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
CommandLine cmdLine;
// parse argc,argv
if (cmdLine.SplitLine(argc, argv) < 1)
{
// no switches were given on the command line, abort
ASSERT(0);
exit(-1);
} // test for the 'help' case
if (cmdLine.HasSwitch( _T("-h") ) )
{
show_help();
exit(0);
} // get the required arguments
tstring p1_1, p1_2, p2_1;
try
{
// if any of these fail, we'll end up in the catch() block
p1_1 = cmdLine.GetArgument( _T("-p1") , 0);
p1_2 = cmdLine.GetArgument( _T("-p1") , 1);
p2_1 = cmdLine.GetArgument( _T("-p2") , 0); }
catch (...)
{
// one of the required arguments was missing, abort
ASSERT(0);
exit(-1);
} // get the optional parameters // convert to an int, default to '-1'
int iOpt1Val = tstoi( cmdLine.GetSafeArgument( _T("-optInt"), 0, _T("-1") ).c_str() );
tcout<<iOpt1Val<<endl;
return 0;
}
\endcode
@version 1.0 Chris Losinger
@version 2.0 Jim Crafton
@version 3.0 Marshall Wei
*/
class CommandLine
{
public:
typedef std::map<tstring, CmdParam> CommandLineMap;
typedef std::vector<tstring> CommandLineVector; CommandLine() {}
virtual ~CommandLine() {}
/**
parse the command line into switches and arguments.
@return int number of switches found
*/
int SplitLine( int argc, TCHAR **argv ); int SplitLine( const tstring& commandLine ); int SplitLine( const std::vector<tstring>& commandLine ); /**
was the switch found on the command line ?
\code
ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 call return
---- ------
cmdLine.HasSwitch("-a") true
cmdLine.HasSwitch("-z") false
\endcode
@return bool true if it has the swith, otherwise false
*/
bool HasSwitch( const tstring& aSwitch ) const ; /**
fetch an argument associated with a switch . if the parameter at
index iIdx is not found, this will return the default that you
provide. example :
\code
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 call return
---- ------
cmdLine.GetSafeArgument("-a", 0, "zz") p1
cmdLine.GetSafeArgument("-a", 1, "zz") p2
cmdLine.GetSafeArgument("-b", 0, "zz") p4
cmdLine.GetSafeArgument("-b", 1, "zz") zz
\endcode
*/ tstring GetSafeArgument(const tstring& aSwitch, size_t iIdx, const tstring& aDefault) const; /**
fetch a argument associated with a switch. throws an exception
of (int)0, if the parameter at index iIdx is not found. example :
\code
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 call return
---- ------
cmdLine.GetArgument("-a", 0) p1
cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string
\endcode
*/
tstring GetArgument( const tstring& aSwitch, size_t iIdx ) const; tstring GetArgument( size_t index ) const; /**
@return the number of arguments found for a given switch. -1 if the
switch was not found
*/
int GetArgumentCount(const tstring& aSwitch) const; size_t GetArgCount() const {
return m_originalCommandLine.size();
} const std::vector<tstring>& GetOriginalCommandLine() const
{
return m_originalCommandLine;
}
protected:
/**
protected member function
test a parameter to see if it's a switch :
switches are of the form : -x
where 'x' is one or more characters.
the first character of a switch must be non-numeric!
*/
bool IsSwitch(const tstring& param) const; CommandLineMap m_commandLine;
CommandLineVector m_originalCommandLine;
}; }
CmdLine.cpp file
#include "stdafx.h"
#include "cmdline.h" using namespace std; namespace Utility
{
int CommandLine::SplitLine( const std::vector<tstring>& commandLine )
{
m_commandLine.clear();
m_originalCommandLine.clear(); m_originalCommandLine = commandLine; tstring curParam; // current argv[x]
size_t argc = m_originalCommandLine.size();
// skip the exe name (start with i = 1)
for (size_t i = ; i < argc; i++) {
// if it's a switch, start a new CommandLine
if ( IsSwitch(m_originalCommandLine[i])) {
curParam = m_originalCommandLine[i]; tstring arg; // look at next input tstring to see if it's a switch or an argument
if (i + < argc) {
if (!IsSwitch(m_originalCommandLine[i + ])) {
// it's an argument, not a switch
arg = m_originalCommandLine[i + ]; // skip to next
i++;
}
else {
arg = _T("");
}
} // add it
CmdParam cmd; // only add non-empty args
if (arg != _T("") ) {
cmd.strings_.push_back(arg);
} // add the CmdParam to 'this'
std::pair<CommandLineMap::iterator, bool> res = m_commandLine.insert(CommandLineMap::value_type(curParam, cmd)); }
else {
// it's not a new switch, so it must be more stuff for the last switch // ...let's add it
CommandLineMap::iterator theIterator; // get an iterator for the current param
theIterator = m_commandLine.find(curParam);
if (theIterator!=m_commandLine.end()) {
(*theIterator).second.strings_.push_back(m_originalCommandLine[i]);
}
else {
// ??
}
}
} return static_cast<int>( m_commandLine.size() );
} int CommandLine::SplitLine( int argc, TCHAR **argv )
{
std::vector<tstring> args; for ( int j=;j<argc;j++ ) {
args.push_back( tstring(argv[j]) );
} return SplitLine( args );
} int CommandLine::SplitLine( const tstring& commandLine )
{
std::vector<tstring> args;
const TCHAR* P = commandLine.c_str();
const TCHAR* start = P;
const TCHAR* argStart = P; int sz = static_cast<int>( commandLine.size() );
while ( (P - start) < sz ) {
if ( *P == '\"' ) {
P++;
while ( ((P - start) < sz) && (*P != '\"' ) ) {
P++;
}
P++;
} if ( *P == '\"' ) {
continue; //loop again
} if ( *P == ' ' ) {
//argument
//strip out begin/end quotes tstring arg;
const TCHAR* tmpArgStart = argStart;
const TCHAR* tmpArgEnd = tmpArgStart;
while ( tmpArgEnd < P ) {
if ( *tmpArgEnd == '\"' ) {
if ( tmpArgStart != tmpArgEnd ) {
arg.append( tmpArgStart, tmpArgEnd - tmpArgStart );
tmpArgStart = tmpArgEnd;
}
tmpArgStart++;
} tmpArgEnd ++;
} if ( arg.empty() ) {
arg.append( tmpArgStart, tmpArgEnd - tmpArgStart );
} args.push_back( arg ); while ( (*P == ' ') && ((P - start) < sz) ) {
P++;
}
argStart = P;
P--;
} P++;
}
if ( argStart < P ) {
tstring arg;
arg.assign( argStart, P-argStart );
args.push_back( arg );
} return SplitLine( args );
} bool CommandLine::IsSwitch(const tstring& aParam) const
{
if (aParam.empty())
return false; // switches must non-empty
// must have at least one character after the '-' if (aParam.size() <= ) {
return false;
} // switches always start with '-'
if (aParam[]=='-') {
// allow negative numbers as arguments.
// ie., don't count them as switches
return (!isdigit(aParam[]));
}
else {
return false;
}
} bool CommandLine::HasSwitch(const tstring& aSwitch) const
{
CommandLineMap::const_iterator theIterator;
theIterator = m_commandLine.find(aSwitch);
return (theIterator != m_commandLine.end());
} tstring CommandLine::GetSafeArgument(const tstring& aSwitch, size_t index, const tstring& defaultVal) const
{
tstring result; if ( !defaultVal.empty() ) {
result = defaultVal;
} try
{
result = GetArgument(aSwitch, index);
}
catch (...)
{
} return result;
} tstring CommandLine::GetArgument( size_t index ) const
{
tstring result;
if ( (index >= ) && (index < m_originalCommandLine.size()) ) {
result = m_originalCommandLine[index];
}
return result;
} tstring CommandLine::GetArgument( const tstring& aSwitch, size_t index )const
{
if ( HasSwitch( aSwitch ) )
{
CommandLineMap::const_iterator theIterator = m_commandLine.find(aSwitch);
if (theIterator!=m_commandLine.end())
{
if ((*theIterator).second.strings_.size() > index)
{
return (*theIterator).second.strings_[index];
}
}
} throw (int); return _T("");
} int CommandLine::GetArgumentCount(const tstring& aSwitch) const
{
int result = -; if ( HasSwitch(aSwitch) ) {
CommandLineMap::const_iterator theIterator = m_commandLine.find( aSwitch );
if (theIterator!=m_commandLine.end()) {
result = static_cast<int>( (*theIterator).second.strings_.size() );
}
} return result;
}
}
C++: Command Line Processing的更多相关文章
- Linux command line exercises for NGS data processing
by Umer Zeeshan Ijaz The purpose of this tutorial is to introduce students to the frequently used to ...
- Getopt::Long - Extended processing of command line options
use Getopt::Long; my $data = "file.dat"; my $length = 24; my $verbose; GetOptions (" ...
- [笔记]The Linux command line
Notes on The Linux Command Line (by W. E. Shotts Jr.) edited by Gopher 感觉博客园是不是搞了什么CSS在里头--在博客园显示效果挺 ...
- JMeterPluginsCMD Command Line Tool
There is small command-line utility for generating graphs out of JTL files. It behave just like righ ...
- An annotation based command line parser
Java命令行选项解析之Commons-CLI & Args4J & JCommander http://rensanning.iteye.com/blog/2161201 JComm ...
- Creating Node.js Command Line Utilities to Improve Your Workflow
转自:https://developer.telerik.com/featured/creating-node-js-command-line-utilities-improve-workflow/ ...
- stderr: xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
错误提示: (1). stderr: xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer direc ...
- List of Chromium Command Line Switches(命令行开关集)——官方指定命令行更新网址
转自:http://peter.sh/experiments/chromium-command-line-switches/ There are lots of command lines which ...
- xargs: How To Control and Use Command Line Arguments
参考: http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/ http://linux ...
随机推荐
- service redis does not support chkconfig的解决办法
原文链接: http://my.oschina.net/maczhao/blog/322931 问题解决办法如下: 必须把下面两行注释放在/etc/init.d/redis文件靠前的注释中: # ch ...
- oracle 自治事物 -- autonomous transaction
一 使用规则 : 在begin 之前申明 : PRAGMA AUTONOMOUS_TRANSACTION; 二 使用理解:autonomous transaction 是一个独立的事务,这一点是理解 ...
- HttpClient 发送图片
var httpClient = new HttpClient(); using (FileStream fs = new FileStream("C:\\1.jpg", File ...
- SQL Server强制删除发布
今日发现SQL Server 中 存在以前(系统还原前)的发布内容,使用鼠标->右键,选择删除,失败. 可使用语句: EXEC SP_REMOVEDBREPLICATION '发布数据库名称 ...
- http方法
http method(方法):1.get 从服务器获取资源2.post 向服务器发送资源3.put 向服务器推送资源4.delete 告诉服务器删除某个资源5.head 告诉服务器返回数据时不需要返 ...
- android launcher3 home页简易分析
最近在修改一个问题:就是修改home页下,用户手动拖出来的APP图片下面的字体显示不全,思路比较明确,需要尽量加大整个APP控件的高度,或者缩小图片和文字之间的间隔. 跟代码发现APP整个控件的lay ...
- JetBrains公司的IDE使用技巧
1.自定义Live Templates: 点击+添加自己的.最后记住要点击,change或default来设置在哪些文件上使用代码片段.
- Android热更新开源项目Tinker集成实践总结
前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实 ...
- 移动端web开发调试
手机上安装chrome, 连接上usb允许调试,打开电脑的chrome,输入chrome://inspect 点击电脑页面的inspect即可,这时操作手机和电脑能达到同步显示. android4.4 ...
- Ecshop后台菜单添加
首先需要修改四个文件:inc_priv.php, inc_menu.php, priv_action.php, commn.php 假如当前的项要加在商品管理的菜单下 一:在languages/zh_ ...