从命令行提取程序运行时选项的方法有很多。你可以自己编写相对应的完整的解析函数,或许你有丰富的C语言编程经验,熟知getopt()函数的用法,又或许使用Python的你已经在使用optparse库来简化这一工作。
program_options 提供程序员一种方便的命令行和配置文件进行程序选项设置的方法。使用program_options库而不是你自己动手写相关的解析代码,因为它更简单,声明程序选项的语法简洁,并且库自身也非常小。将选项值转换为适合的类型值的工作也都能自动完成。库有着完备的错误检查机制,如果自己手写解析代码时,就可能会错过对一些出错情况的检查了。最后,选项值不仅能从命令行获取,也能从配置文件,甚至于环境变量中提取,而这些选择不会增加明显的工作量。
1. 首先看一个简单的程序吧:
- #include <string>
- #include <iostream>
- #include <boost/program_options.hpp>
- using namespace std;
-
- int main (int ac, char* av[])
- {
- boost::program_options::options_description options("command line options");
- options.add_options() ("help", "Use -h or --help to list all arguments")
- ("file", boost::program_options::value<string>(),
- "Provide input file name");
- boost::program_options::variables_map vmap;
- boost::program_options::store(
- boost::program_options::parse_command_line(ac, av, options), vmap);
- boost::program_options::notify(vmap);
-
- if (vmap.count("help")) {
- cout << options << endl;
- }
-
- if (vmap.count("file")){
- cout <<"Your input file: " << vmap["file"].as<string>() << "\n";
- }
-
- return 0;
- }
-
-
程序的工作方式如下:
options_description 类声明所有的有效命令行选项。
使用方法 add_options,您可以注册命令和跟在命令后面的参数类型。在此例中,help 选项不需要任何参数,但是 file 选项需要一个字符串参数。
variables_map 类在运行时存储命令行选项及其参数。
Boost 的 parse_command_line 函数解析 argc 和 argv 参数。store 和 notify 方法帮助存储 vmap 对象中的数据。
vmap.count()用于检测输入的是哪个命令行参数,并采取适当的动作
2. 提供多个参数和缩写的命令选项
命令行处理通常同时需要同一个命令选项的短名称和长名称。此外,您通常必须多次使用某个选项,以便收集该选项的所有参数。例如,您可能希望使用 -h 和 --help 来打印可用的命令:
- #include <string>
- #include <iostream>
- #include <boost/program_options.hpp>
- using namespace std;
-
- int main (int ac, char* av[])
- {
- boost::program_options::options_description options("command line options");
- options.add_options() ("help,h", "Use -h or --help to list all arguments")
- ("file", boost::program_options::value<vector<string> >( ),
- "Provide input file name");
- boost::program_options::variables_map vmap;
- boost::program_options::store(
- boost::program_options::parse_command_line(ac, av, options), vmap);
- boost::program_options::notify(vmap);
-
- if (vmap.count("help")) {
- cout << options << endl;
- }
-
- if (vmap.count("file")) {
- vector<string> ifiles(vmap["file"].as< vector<string> > ());
- vector<string>::iterator vI;
- cout << "Number of input files: " << ifiles.size() << endl;
- cout << "Input file list: " << endl;
- for(vI = ifiles.begin(); vI != ifiles.end(); ++vI)
- cout << "\t" << *vI << endl;
- } else {
- cout << "No file specified\n";
- }
-
- return 0;
- }
在使用 add_options 来添加命令选项时,较长和较短的选项之间使用逗号进行分隔。请注意,较长的选项 (help) 必须在较短的选项 (h) 之前,代码才能正常工作。与使用单个字符串不同,file 选项现在是使用一个字符串向量来定义的。如果指定了 --file 选项多次,则会将所有收集到的file命令选项参数存储在关联的vector<string>中。下面是使用不同的参数来多次指定 --h 和 --file 所获得的输出:
./a.out -h
command line options:
-h [ --help ] Use -h or --help to list all arguments
--file arg Provide input file name
No file specified
./a.out --file abc --file pqr
Number of input files: 2
Input file list:
abc
pqr
3. 解析位置选项
下面的程序,第一个参数转换为 --file=<first parameter>,第二个参数转换为 --do-file=<second parameter>。
- #include <string>
- #include <iostream>
- #include <boost/program_options.hpp>
- using namespace std;
-
- int main (int ac, char* av[])
- {
- boost::program_options::options_description options("command line options");
- options.add_options() ("help,h", "Use -h or --help to list all arguments")
- ("file", boost::program_options::value<string>(),
- "Provide input file name")
- ("do-file", boost::program_options::value<string>(),
- "Specify commands file");
-
- boost::program_options::variables_map vmap;
- boost::program_options::positional_options_description poptd;
- poptd.add("file", 1);
- poptd.add("do-file", 2);
-
- boost::program_options::store(
- boost::program_options::command_line_parser(ac, av).
- options(options).positional(poptd).run(), vmap);
- boost::program_options::notify(vmap);
-
- if (vmap.count("file")) {
- cout << "file: " << vmap["file"].as<string> ( ) << endl;
- }
-
- if (vmap.count("do-file")) {
- cout << "do-file: " << vmap["do-file"].as<string> ( ) << endl;
- }
-
- return 0;
- }
下面是输出内容:
./a.out file1 dofile1
file: file1
do-file: dofile1
程序引入了新的类 positional_options_description。该类的 add 方法(add("command option", N))将位置 N 处的输入参数与命令行选项 "command option" 相关联。因此,./a.out file1 在内部解析为 ./a.out --file=file1。另一个区别在于调用 program_options::store 方法的方式。与使用 parse_command_line 例程不同,Boost 库要求您将 command_line_parser 例程与 store 方法结合在一起使用。
请注意,仍然可以使用 --file 和 --do-file 选项来调用该程序。最后,若要将所有的输入参数与同一个命令行选项相关联,您需要使用值-1 将该命令行选项添加到 positional_options_description 对象。下面是代码:
…
boost::program_options::positional_options_description poptd;
poptd.add("file", -1);
...
(itlanger) |