What's an effective way to parse command line parameters in C++?
在C++中有一种处理命令行参数的有效方法吗?
我在下面所做的感觉完全不专业,我无法想象这是如何在专业软件中处理命令行参数(ATOI,硬编码的argc检查)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Command line usage: sum num1 num2 int main(int argc, char *argv[]) { if (argc < 3) { cout <<"Usage:" << argv[0] <<" num1 num2 "; exit(1); } int a = atoi(argv[1]); int b = atoi(argv[2]); int sum = a + b; cout <<"Sum:" << sum <<" "; return 0; } |
您可能需要使用外部库来实现这一点。有许多可供选择。
Boost有一个功能丰富(和往常一样)的库Boost程序选项。
在过去的几年里,我个人最喜欢的是TCLAP——纯粹是模板化的,因此没有库或链接、自动化的"帮助"生成和其他功能。请参阅文档中最简单的示例。
您可以为此使用已经创建的库
http://www.boost.org/doc/libs/1_44_0/doc/html/program_options.html
如果这是Linux/Unix,那么使用的标准配置是gnu getopt
http://www.gnu.org/s/libc/manual/html_node/getopt.html
它太大了,无法包含在堆栈溢出应答中,但我创建了一个用于声明性定义命令行的库。它利用C++ 14的能力,通过给每个成员变量提供初始值来构造类构造函数。
图书馆主要是一个基类。若要定义命令语法,请声明从其派生的结构。这是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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; |
我仍在寻求消除在里面撒上所有
一旦您有了一个实例,就有几个方法重载来解析来自字符串或
1 2 3 4 5 6 7 8 9 | if (!cl.Parse(argc, argv)) { std::string message; for (const auto &error : cl.GetErrors()) { message += error +" "; } std::cerr << message; exit(EXIT_FAILURE); } |
解析后,可以使用
1 2 | if (cl.m_help()) { std::cout << cl.GetUsage(); } for (int i = 0; i < cl.m_loops(); ++i) { ... } |
整个图书馆只有大约300行(不包括测试)。实例有点膨胀,因为解析表是实例的一部分(而不是类)。但是,通常每个程序只需要一个实例,这种纯声明性方法的便利性非常强,可以通过解析新的输入来重置实例。
我在windows/mingw下使用getopt():
1 2 3 4 5 6 7 8 9 10 11 | while ((c = getopt(myargc, myargv,"vp:d:rcx")) != -1) { switch (c) { case 'v': // print version printf("%s Version %s ", myargv[0], VERSION); exit(0); break; case 'p': // change local port to listen to strncpy(g_portnum, optarg, 10); break; ... |
我建议使用Boost
http://www.boost.org/doc/libs/release/libs/conversion/lexical_cast.htm
除此之外,你的代码可以用于简单的事情。