如果程序指定以这种方式运行,那么在C++中解析命令行参数的最佳方法是什么:
prog [-abc] [input [output]]
标准库中是否有实现这个功能的方法,还是我需要编写自己的代码?
相关问题:
如果程序指定以这种方式运行,那么在C++中解析命令行参数的最佳方法是什么:
prog [-abc] [input [output]]
标准库中是否有实现这个功能的方法,还是我需要编写自己的代码?
相关问题:
我发现使用ezOptionParser更容易。它是一个单个头文件,除了STL之外不依赖任何东西,在Windows和Linux上工作(很可能也适用于其他平台),由于示例的存在没有学习曲线,具有其他库所没有的功能(例如带注释的文件导入/导出、带分隔符的任意选项名称、自动使用格式等),并且具有LGPL许可证。
你可能需要使用外部库来实现此功能。有许多可供选择。
Boost拥有一个非常丰富的库Boost Program Options(像往常一样)。
我个人在过去几年中最喜欢的是TCLAP——纯模板化,因此没有库或链接,自动生成“--help”等好处。请参见文档中的最简单的示例。
同时也有一份Google开源库可供使用。
实际上,命令行解析已经“解决”了。只需要选择一个即可。
尝试使用Boost::Program Options。它可以帮助你读取和解析命令行以及配置文件。
我认为GNU GetOpt不太容易使用。
Qt和Boost可能是解决方案,但需要下载和编译大量代码。
因此,我自己实现了一个解析器,它可以生成一个参数的std::map<std::string,std::string>。
例如,调用:
./myProgram -v -p 1234
map将是:
["-v"][""]
["-p"]["1234"]
使用方法如下:
int main(int argc, char *argv[]) {
MainOptions mo(argc, argv);
MainOptions::Option* opt = mo.getParamFromKey("-p");
const string type = opt ? (*opt).second : "";
cout << type << endl; /* Prints 1234 */
/* Your check code */
}
MainOptions.h
#ifndef MAINOPTIONS_H_
#define MAINOPTIONS_H_
#include <map>
#include <string>
class MainOptions {
public:
typedef std::pair<std::string, std::string> Option;
MainOptions(int argc, char *argv[]);
virtual ~MainOptions();
std::string getAppName() const;
bool hasKey(const std::string&) const;
Option* getParamFromKey(const std::string&) const;
void printOptions() const;
private:
typedef std::map<std::string, std::string> Options;
void parse();
const char* const *begin() const;
const char* const *end() const;
const char* const *last() const;
Options options_;
int argc_;
char** argv_;
std::string appName_;
};
MainOptions.cpp
#include "MainOptions.h"
#include <iostream>
using namespace std;
MainOptions::MainOptions(int argc, char* argv[]) :
argc_(argc),
argv_(argv) {
appName_ = argv_[0];
this->parse();
}
MainOptions::~MainOptions() {
}
std::string MainOptions::getAppName() const {
return appName_;
}
void MainOptions::parse() {
typedef pair<string, string> Option;
Option* option = new pair<string, string>();
for (const char* const * i = this->begin() + 1; i != this->end(); i++) {
const string p = *i;
if (option->first == "" && p[0] == '-') {
option->first = p;
if (i == this->last()) {
options_.insert(Option(option->first, option->second));
}
continue;
} else if (option->first != "" && p[0] == '-') {
option->second = "null"; /* or leave empty? */
options_.insert(Option(option->first, option->second));
option->first = p;
option->second = "";
if (i == this->last()) {
options_.insert(Option(option->first, option->second));
}
continue;
} else if (option->first != "") {
option->second = p;
options_.insert(Option(option->first, option->second));
option->first = "";
option->second = "";
continue;
}
}
}
void MainOptions::printOptions() const {
std::map<std::string, std::string>::const_iterator m = options_.begin();
int i = 0;
if (options_.empty()) {
cout << "No parameters\n";
}
for (; m != options_.end(); m++, ++i) {
cout << "Parameter [" << i << "] [" << (*m).first << " " << (*m).second
<< "]\n";
}
}
const char* const *MainOptions::begin() const {
return argv_;
}
const char* const *MainOptions::end() const {
return argv_ + argc_;
}
const char* const *MainOptions::last() const {
return argv_ + argc_ - 1;
}
bool MainOptions::hasKey(const std::string& key) const {
return options_.find(key) != options_.end();
}
MainOptions::Option* MainOptions::getParamFromKey(
const std::string& key) const {
const Options::const_iterator i = options_.find(key);
MainOptions::Option* o = 0;
if (i != options_.end()) {
o = new MainOptions::Option((*i).first, (*i).second);
}
return o;
}
如果我可以自吹自擂的话,我想建议您看一下我编写的一个选项解析库:dropt。
它提供的一个许多其他库都没有的特性是能够覆盖早期的选项。例如,如果您有一个shell别名:
alias bar="foo --flag1 --flag2 --flag3"
如果你想使用bar
,但需要禁用--flag1
,可以这样做:
bar --flag1=0
我喜欢C语言的getopt()函数,但我已经老了。 :-)
getopt
或argparse
。 - Andrejs Cainikovsstd :: vector <std :: string> args(argv,argv + argc);
,以便您可以解析字符串向量而不是字符数组。 - stefaanv