也许您应该使用Boost property_tree 而不是program_options,因为您的文件格式似乎与Windows INI file format 非常相似。 Boost property_tree 有一个 parser for INI files (以及一个序列化器,以防你也需要它)。
然后将通过遍历树来处理您的选项。不在一个节中的选项将位于树根下,而节选项将位于该节的节点下。
如果你真的想,你可以使用program_options。关键是将true作为最后一个参数传递给parse_config_file,即allow_unregistered_options:
#include <iostream>
#include <sstream>
#include <boost/program_options.hpp>
static const std::string fileData = // sample input
"foo=1\n"
"[bar]\n"
"foo=a distinct foo\n"
"[/etc]\n"
"baz=all\n"
"baz=multiple\n"
"baz=values\n"
"a.baz=appear\n";
int main(int argc, char *argv[]) {
namespace po = boost::program_options;
std::istringstream is(fileData);
po::parsed_options parsedOptions = po::parse_config_file(
is,
po::options_description(),
true); // <== allow unregistered options
// Print out results.
for (const auto& option : parsedOptions.options) {
std::cout << option.string_key << ':';
// Option value is a vector of strings.
for (const auto& value : option.value)
std::cout << ' ' << value;
std::cout << '\n';
}
return 0;
}
这个输出:
$ ./po
foo: 1
bar.foo: a distinct foo
/etc.baz: all
/etc.baz: multiple
/etc.baz: values
/etc.baz: appear
但是,请注意,使用这种方法得到的是一个选项向量,而不是 program_options 的典型使用产生的映射。因此,您最终可能会将 parsed_options 容器处理成您可以更轻松地查询的内容,并且该内容可能看起来像 property_tree。
这是一个使用property_tree 的类似程序。输入略有不同,因为property_tree 不允许重复键。
#include <iostream>
#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
static const std::string fileData = // sample input
"foo=1\n"
"[bar]\n"
"foo=a distinct foo\n"
"[/etc]\n"
"foo=and another\n"
"baz=all\n";
static void print_recursive(
const std::string& prefix,
const boost::property_tree::ptree& ptree) {
for (const auto& entry : ptree) {
const std::string& key = entry.first;
const boost::property_tree::ptree& value = entry.second;
if (!value.data().empty())
std::cout << prefix + key << ": " << value.data() << '\n';
else
print_recursive(prefix + key + '.', value);
}
}
int main() {
namespace pt = boost::property_tree;
std::istringstream is(fileData);
pt::ptree root;
pt::read_ini(is, root);
print_recursive("", root);
return 0;
}