命令行处理是另一个难点,开发人员通常不会采用结构化的方式来解决。其结果是从头到尾维护开销。Boost program_options
库提供了简化命令行处理的例程和数据结构。
清单 15 详细描述了 boost::program_options
的使用。这是建议在您的代码中使用的标准模板。
#include #include #include 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(), "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; }
return 0; } |
您必须包括 program_options.hpp 头文件。清单 15 的工作方式如下:
options_description
类声明所有的有效命令行选项。- 使用方法
add_options
,您可以注册命令和跟在命令后面的参数类型。在此例中,help
选项不需要任何参数,但是 file
选项需要一个字符串参数。 variables_map
类在运行时存储命令行选项及其参数。- Boost 的
parse_command_line
例程解析 argc
和 argv
参数。store
和 notify
方法帮助存储 vmap
对象中的数据。 - 当您检查
help
是否为程序的恰当命令行选项(这是 vmap.count("help")
所做的工作)时,options
对象将被转储到 cout
。这意味着运算符 <<
是为 options_description
类定义的。
下面是来自清单 15 的输出:
[user@/home/user1] ./a.out --help command line options: --help Use -h or --help to list all arguments --file arg Provide input file name |
当您遇到其他选项时,可以采取进一步的操作。例如,下面的代码片段经过了修改,以打印您输入的文件名:
… if (vmap.count("file")) { cout << "Setting input file to " << vmap["file"].as() << ".\n"; } else { cout << "No file specified\n"; } …
|
请注意,variable_map
类在许多方面与哈希表非常相似。例如,要检索 file 参数,您可以调用 vmap["file"]
。
命令行处理通常同时需要同一个命令选项的短名称和长名称。此外,您通常必须多次使用某个选项,以便收集该选项的所有参数。例如,您可能希望使用 ¨Ch
和 ¨Chelp
来打印可用的命令。清单 16 演示了这些功能。
#include #include #include 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 >( ), "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 ifiles(vmap["file"].as< vector > ()); vector::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
选项现在是使用一个字符串向量来定义的。如果指定了 ¨Cfile
选项多次,则会将在所有指定中收集到的命令选项参数存储在关联的 vector
中。下面是使用不同的参数来多次指定 ¨Ch
和 ¨Cfile
所获得的输出:
[user@/home/user1] ./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 [user@/home/user1] ./a.out --file abc --file pqr Number of input files: 2 Input file list: abc pqr
|
带输入参数但是不带命令行选项来调用某个程序是非常普遍的。您预期参数和命令行选项之间自动存在某种神奇关联。这种行为由 boost::program_options
提供支持。
请考虑清单 17。第一个参数转换为 --file=
,第二个参数转换为 --do-file=
。
#include #include #include 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(), "Provide input file name") ("do-file", boost::program_options::value(), "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 ( ) << endl; }
if (vmap.count("do-file")) { cout << "do-file: " << vmap["do-file"].as ( ) << endl; }
return 0; } |
下面是输出内容:
[user@/home/user1] ./a.out file1 dofile1 file: file1 do-file: dofile1
|
清单 15 中使用的某些 API 在清单 17 中已发生更改。清单 17 引入了新的类 positional_options_description
。该类的 add
方法(add("command option", N)
)将位置 N 处的输入参数与命令行选项 "command option"
相关联。因此,./a.out file1
在内部解析为 ./a.out ¨Cfile=file1
。另一个区别在于调用 program_options::store
方法的方式。与使用 parse_command_line
例程不同,Boost 库要求您将 command_line_parser
例程与 store
方法结合在一起使用。
请注意,仍然可以使用 ¨Cfile
和 ¨Cdo-file
选项来调用该程序。最后,若要将所有的输入参数与同一个命令行选项相关联,您需要使用值 -1 将该命令行选项添加到 positional_options_description
对象。下面是代码:
… boost::program_options::positional_options_description poptd; poptd.add("file", -1); ...
|
阅读(2414) | 评论(0) | 转发(0) |