如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:
prog [-abc] [input [output]]
是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?
相关:
在unicode c++应用程序中解析命令行参数
如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:
prog [-abc] [input [output]]
是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?
相关:
在unicode c++应用程序中解析命令行参数
当前回答
如果你不想使用boost,我推荐这个小助手类。
其他回答
Qt 5.2提供了一个命令行解析器API。
小例子:
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDebug>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
app.setApplicationName("ToolX");
app.setApplicationVersion("1.2");
QCommandLineParser parser;
parser.setApplicationDescription("Tool for doing X.");
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("infile",
QCoreApplication::translate("main", "Input file."));
QCommandLineOption verbose_opt("+",
QCoreApplication::translate("main", "be verbose"));
parser.addOption(verbose_opt);
QCommandLineOption out_opt(QStringList() << "o" << "output",
QCoreApplication::translate("main", "Output file."),
QCoreApplication::translate("main", "filename"), // value name
QCoreApplication::translate("main", "out") // default value
);
parser.addOption(out_opt);
// exits on error
parser.process(app);
const QStringList args = parser.positionalArguments();
qDebug() << "Input files: " << args
<< ", verbose: " << parser.isSet(verbose_opt)
<< ", output: " << parser.value(out_opt)
<< '\n';
return 0;
}
示例输出
自动生成的帮助界面:
$ ./qtopt -h Usage: ./qtopt [options] infile Tool for doing X. Options: -h, --help Displays this help. -v, --version Displays version information. -+ be verbose -o, --output Output file. Arguments: infile Input file.
自动生成版本输出:
$ ./qtopt -v ToolX 1.2
一些真实的电话:
$ ./qtopt b1 -+ -o tmp blah.foo Input files: ("b1", "blah.foo") , verbose: true , output: "tmp" $ ./qtopt Input files: () , verbose: false , output: "out"
解析错误:
$ ./qtopt --hlp Unknown option 'hlp'. $ echo $? 1
结论
如果您的程序已经使用了Qt(>= 5.2)库,那么它的命令行解析API足以方便地完成工作。
请注意,内置Qt选项在选项解析器运行之前会被QApplication使用。
它太大了,不可能包含在Stack Overflow回答中,但我创建了一个用于声明式定义命令行的库。它利用了c++ 14通过给每个成员变量赋初始值来构建类构造函数的能力。
这个库基本上是一个基类。要定义命令语法,需要声明一个派生自该语法的结构。下面是一个例子:
struct MyCommandLine : public core::CommandLine {
Argument<std::string> m_verb{this, "program", "program.exe",
"this is what my program does"};
Option<bool> m_help{this, "help", false,
"displays information about the command line"};
Alias<bool> alias_help{this, '?', &m_help};
Option<bool> m_demo{this, "demo", false,
"runs my program in demonstration mode"};
Option<bool> m_maximize{this, "maximize", false,
"opens the main window maximized"};
Option<int> m_loops{this, "loops", 1,
"specifies the number of times to repeat"};
EnumOption<int> m_size{this, "size", 3,
{ {"s", 1},
{"small", 1},
{"m", 3},
{"med", 3},
{"medium", 3},
{"l", 5},
{"large", 5} } };
BeginOptionalArguments here{this};
Argument<std::string> m_file{this, "file-name", "",
"name of an existing file to open"};
} cl;
参数、选项和别名类模板是在CommandLine基类的范围内声明的,您可以为自己的类型专门化它们。每个选项都包含this指针、选项名称、默认值和用于打印命令概要/用法的描述。
我仍然在寻找消除所有这些指针的需要,但我还没有找到一种不引入宏的方法。这些指针允许每个成员向驱动解析的基类中的表注册自己。
一旦有了实例,就会有多个方法重载来解析来自字符串或主样式参数向量的输入。解析器同时处理windows风格和unix风格的选项语法。
if (!cl.Parse(argc, argv)) {
std::string message;
for (const auto &error : cl.GetErrors()) {
message += error + "\n";
}
std::cerr << message;
exit(EXIT_FAILURE);
}
一旦它被解析,你可以使用operator()访问任何选项的值:
if (cl.m_help()) { std::cout << cl.GetUsage(); }
for (int i = 0; i < cl.m_loops(); ++i) { ... }
整个库只有大约300行(不包括测试)。实例有点臃肿,因为解析表是实例(而不是类)的一部分。但是每个程序通常只需要一个实例,而且这种纯声明性方法的便利性非常强大,可以通过解析新输入简单地重置实例。
提振。Program_options
您可以使用GNU GetOpt (LGPL)或各种c++端口之一,例如getoptpp (GPL)。
一个简单的例子使用GetOpt你想要的东西(prog [-ab] input)如下:
// C Libraries:
#include <string>
#include <iostream>
#include <unistd.h>
// Namespaces:
using namespace std;
int main(int argc, char** argv) {
int opt;
string input = "";
bool flagA = false;
bool flagB = false;
// Retrieve the (non-option) argument:
if ( (argc <= 1) || (argv[argc-1] == NULL) || (argv[argc-1][0] == '-') ) { // there is NO input...
cerr << "No argument provided!" << endl;
//return 1;
}
else { // there is an input...
input = argv[argc-1];
}
// Debug:
cout << "input = " << input << endl;
// Shut GetOpt error messages down (return '?'):
opterr = 0;
// Retrieve the options:
while ( (opt = getopt(argc, argv, "ab")) != -1 ) { // for each option...
switch ( opt ) {
case 'a':
flagA = true;
break;
case 'b':
flagB = true;
break;
case '?': // unknown option...
cerr << "Unknown option: '" << char(optopt) << "'!" << endl;
break;
}
}
// Debug:
cout << "flagA = " << flagA << endl;
cout << "flagB = " << flagB << endl;
return 0;
}
AnyOption是一个c++类,用于轻松解析复杂的命令行选项。它还以选项值对格式解析来自rsourcefile的选项。
AnyOption实现了传统的POSIX风格的字符选项(-n)以及较新的GNU风格的长选项(——name)。或者您可以通过要求忽略POSIX样式选项来使用更简单的长选项版本(-name)。