如何解析 C++ 中的命令行参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/865668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Parse Command Line Arguments in C++?
提问by Verhogen
Possible Duplicate:
What parameter parser libraries are there for C++?
可能的重复:
C++ 有哪些参数解析器库?
What is the best way of parsing command-line arguments in C++ if the program is specified to be run like this:
如果程序被指定为这样运行,那么在 C++ 中解析命令行参数的最佳方法是什么:
prog [-abc] [input [output]]
Is there a library in STL to do this?
STL 中有一个库可以做到这一点吗?
Related:
有关的:
采纳答案by Verhogen
Boost.Program_optionsshould do the trick
Boost.Program_options应该可以解决问题
回答by iain
The suggestions for boost::program_options
and GNU getopt are good ones.
boost::program_options
GNU getopt 和 GNU getopt的建议很好。
However, for simple command line options I tend to use std::find
但是,对于简单的命令行选项,我倾向于使用 std::find
For example, to read the name of a file after a -f
command line argument. You can also just detect if a single-word option has been passed in like -h
for help.
例如,读取-f
命令行参数后的文件名。您还可以检测是否已传入单个单词选项,例如-h
寻求帮助。
#include <algorithm>
char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
char ** itr = std::find(begin, end, option);
if (itr != end && ++itr != end)
{
return *itr;
}
return 0;
}
bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
return std::find(begin, end, option) != end;
}
int main(int argc, char * argv[])
{
if(cmdOptionExists(argv, argv+argc, "-h"))
{
// Do stuff
}
char * filename = getCmdOption(argv, argv + argc, "-f");
if (filename)
{
// Do interesting things
// ...
}
return 0;
}
On thing to look out for with this approach you must use std::strings as the value for std::find otherwise the equality check is performed on the pointer values.
使用这种方法要注意的事情是,您必须使用 std::strings 作为 std::find 的值,否则将对指针值执行相等性检查。
I hope it is okay to edit this response instead adding a new one, as this is based on the original answer. I re-wrote the functions slightly and encapsulated them in a class, so here is the code. I thought it might be practical to use it that way as well:
我希望可以编辑此回复而不是添加新回复,因为这是基于原始答案。我稍微重新编写了函数并将它们封装在一个类中,所以这里是代码。我认为以这种方式使用它也可能是实用的:
class InputParser{
public:
InputParser (int &argc, char **argv){
for (int i=1; i < argc; ++i)
this->tokens.push_back(std::string(argv[i]));
}
/// @author iain
const std::string& getCmdOption(const std::string &option) const{
std::vector<std::string>::const_iterator itr;
itr = std::find(this->tokens.begin(), this->tokens.end(), option);
if (itr != this->tokens.end() && ++itr != this->tokens.end()){
return *itr;
}
static const std::string empty_string("");
return empty_string;
}
/// @author iain
bool cmdOptionExists(const std::string &option) const{
return std::find(this->tokens.begin(), this->tokens.end(), option)
!= this->tokens.end();
}
private:
std::vector <std::string> tokens;
};
int main(int argc, char **argv){
InputParser input(argc, argv);
if(input.cmdOptionExists("-h")){
// Do stuff
}
const std::string &filename = input.getCmdOption("-f");
if (!filename.empty()){
// Do interesting things ...
}
return 0;
}
回答by naufraghi
I can suggest Templatized C++ Command Line Parser Library(some forks on GitHubare available), the API is very straightforward and (cited from the site):
我可以推荐模板化的 C++ 命令行解析器库(GitHub 上的一些分支可用),API 非常简单,并且(从站点引用):
the library is implemented entirely in header files making it easy to use and distribute with other software. It is licensed under the MIT License for worry free distribution.
该库完全在头文件中实现,使其易于使用和与其他软件一起分发。它是在 MIT 许可证下获得许可的,可以放心分发。
This is an example from the manual, colored here for simplicity:
这是手册中的一个示例,为简单起见,在此处着色:
#include <string>
#include <iostream>
#include <algorithm>
#include <tclap/CmdLine.h>
int main(int argc, char** argv)
{
// Wrap everything in a try block. Do this every time,
// because exceptions will be thrown for problems.
try {
// Define the command line object, and insert a message
// that describes the program. The "Command description message"
// is printed last in the help text. The second argument is the
// delimiter (usually space) and the last one is the version number.
// The CmdLine object parses the argv array based on the Arg objects
// that it contains.
TCLAP::CmdLine cmd("Command description message", ' ', "0.9");
// Define a value argument and add it to the command line.
// A value arg defines a flag and a type of value that it expects,
// such as "-n Bishop".
TCLAP::ValueArg<std::string> nameArg("n","name","Name to print",true,"homer","string");
// Add the argument nameArg to the CmdLine object. The CmdLine object
// uses this Arg to parse the command line.
cmd.add( nameArg );
// Define a switch and add it to the command line.
// A switch arg is a boolean argument and only defines a flag that
// indicates true or false. In this example the SwitchArg adds itself
// to the CmdLine object as part of the constructor. This eliminates
// the need to call the cmd.add() method. All args have support in
// their constructors to add themselves directly to the CmdLine object.
// It doesn't matter which idiom you choose, they accomplish the same thing.
TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false);
// Parse the argv array.
cmd.parse( argc, argv );
// Get the value parsed by each arg.
std::string name = nameArg.getValue();
bool reverseName = reverseSwitch.getValue();
// Do what you intend.
if ( reverseName )
{
std::reverse(name.begin(),name.end());
std::cout << "My name (spelled backwards) is: " << name << std::endl;
}
else
std::cout << "My name is: " << name << std::endl;
} catch (TCLAP::ArgException &e) // catch any exceptions
{ std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; }
}
回答by Matthew Flaschen
You can use GNU GetOpt(LGPL) or one of the various C++ ports, such as getoptpp(GPL).
您可以使用GNU GetOpt(LGPL) 或各种 C++ 端口之一,例如getoptpp(GPL)。
A simple example using GetOpt of what you want (prog [-ab] input) is the following:
一个使用 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;
}
回答by MSB
Yet another alternative is The Lean Mean C++ Option Parser:
另一种选择是精益平均 C++ 选项解析器:
http://optionparser.sourceforge.net
http://optionparser.sourceforge.net
It is a header-only library (just a single header file, in fact) and unlike all the other suggestions it is also freestanding, i.e. it has no dependencies whatsoever. In particular there's no dependency on the STL. It does not even use exceptions or anything else that requires library support. This means it can be linked with plain C or other languages without introducing "foreign" libraries.
它是一个只有头文件的库(实际上只是一个头文件),与所有其他建议不同,它也是独立的,即它没有任何依赖关系。特别是不依赖于 STL。它甚至不使用异常或其他任何需要库支持的东西。这意味着它可以与纯 C 或其他语言链接,而无需引入“外部”库。
Like boost::program_options its API offers convenient direct access to options, i.e. you can write code like this
像 boost::program_options 一样,它的 API 提供了对选项的方便的直接访问,即您可以编写这样的代码
if (options[HELP]) ... ;
如果(选项[帮助])...;
and
和
int verbosity = options[VERBOSE].count();
int verbosity = options[VERBOSE].count();
Unlike boost::program_options however this is simply using an array indexed with a (user-provided) enum. This offers the convenience of an associative container without the weight.
与 boost::program_options 不同的是,这只是使用一个以(用户提供的)枚举索引的数组。这提供了没有重量的关联容器的便利。
It's well documented and has a company-friendly license (MIT).
它有据可查,并拥有公司友好的许可证 (MIT)。
TLMC++OP includes a nice formatter for usage messages that can do line-wrapping and column alignment which is useful if you're localizing your program, because it ensures that the output will look good even in languages that have longer messages. It also saves you the nuisance of manually formatting your usage for 80 columns.
TLMC++OP 包含一个很好的用于使用消息的格式化程序,它可以进行换行和列对齐,这在您本地化程序时很有用,因为它确保即使在具有更长消息的语言中输出看起来也很好。它还可以为您省去手动格式化 80 列的使用格式的麻烦。
回答by Oliver Nina
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i],"-i")==0) {
filename = argv[i+1];
printf("filename: %s",filename);
} else if (strcmp(argv[i],"-c")==0) {
convergence = atoi(argv[i + 1]);
printf("\nconvergence: %d",convergence);
} else if (strcmp(argv[i],"-a")==0) {
accuracy = atoi(argv[i + 1]);
printf("\naccuracy:%d",accuracy);
} else if (strcmp(argv[i],"-t")==0) {
targetBitRate = atof(argv[i + 1]);
printf("\ntargetBitRate:%f",targetBitRate);
} else if (strcmp(argv[i],"-f")==0) {
frameRate = atoi(argv[i + 1]);
printf("\nframeRate:%d",frameRate);
}
}
回答by Jay
AnyOptionis a C++ class for easy parsing of complex commandline options. It also parses options from a rsourcefile in option value pair format.
AnyOption是一个 C++ 类,用于轻松解析复杂的命令行选项。它还以选项值对格式解析 rsourcefile 中的选项。
AnyOption implements the traditional POSIX style character options ( -n ) as well as the newer GNU style long options ( --name ). Or you can use a simpler long option version ( -name ) by asking to ignore the POSIX style options.
AnyOption 实现了传统的 POSIX 样式字符选项 ( -n ) 以及较新的 GNU 样式长选项 ( --name )。或者,您可以通过要求忽略 POSIX 样式选项来使用更简单的长选项版本 ( -name )。
回答by Macke
I'd recommend boost::program_options if you can use the Boost lib.
如果您可以使用 Boost 库,我会推荐 boost::program_options。
There's nothing specific in STL nor in the regular C++/C runtime libs.
STL 和常规 C++/C 运行时库中没有任何特定内容。
回答by Denis Shevchenko
Try CLPP library. It's simple and flexible library for command line parameters parsing. Header-only and cross-platform. Uses ISO C++ and Boost C++ libraries only. IMHO it is easier than Boost.Program_options.
试试 CLPP 库。它是用于命令行参数解析的简单灵活的库。仅标题和跨平台。仅使用 ISO C++ 和 Boost C++ 库。恕我直言,它比 Boost.Program_options 更容易。
Library: http://sourceforge.net/projects/clp-parser
库:http: //sourceforge.net/projects/clp-parser
26 October 2010 - new release 2.0rc. Many bugs fixed, full refactoring of the source code, documentation, examples and comments have been corrected.
2010 年 10 月 26 日 - 新版本 2.0rc。许多错误已修复,源代码、文档、示例和注释的完全重构已得到更正。
回答by kebs
Quite a late answer, but I have used GetPot for some projects: http://getpot.sourceforge.net/
相当晚的答案,但我已经在一些项目中使用了 GetPot:http://getpot.sourceforge.net/
Main feature: everything is in a single header file, no build hassles. Just save it somewhere on your machine and "#include" it in your file holding main()
主要特点:一切都在一个头文件中,没有构建麻烦。只需将其保存在您机器上的某个位置,然后将其“#include”到您的文件中main()
Hasn't be updated recently, but nicely documentated, and works well. You can give it a try.
最近没有更新,但有很好的文档记录,并且运行良好。你可以试一试。