c++ - 配置文件中的多个重复部分

标签 c++ boost boost-program-options

我有一个配置文件格式,我希望用 Boost Program Options 来实现(因为我以前使用过那个库),但我必须以某种方式实现这样的 block :

label = whatever
depth = 3

start
source = /etc
dest = /tmp/etc/
end

start
source = /usr/local/include
dest = /tmp/include
depth = 1
end

我读了in the docs我可以有 [sections],所以我首先想知道这个:

label = whatever
depth = 3

[dir]
source = /etc
dest = /tmp/etc/

[dir]
source = /usr/local/include
dest = /tmp/include
depth = 1

但是如果我没理解错的话,dir 会成为变量名的一部分,所以不可能出现重复,这也行不通。所以我想知道将 source 移动到部分名称:

label = whatever
depth = 3

[/etc]
dest = /tmp/etc/

[/usr/local/include]
dest = /tmp/include
depth = 1

这看起来是一个合理的方法吗?我想知道当我事先不知道部分名称时如何遍历部分列表?

或者,是否有更好的方法使用程序选项库来实现此目的?

最佳答案

也许你应该使用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

但是,请注意,您通过这种方法获得的是一个选项 vector ,而不是 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;
}

关于c++ - 配置文件中的多个重复部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23178381/

相关文章:

c++ - 类不能被 boost::python 包装

c++ - boost::any 是可移动的吗?

c++ - boost 程序选项不适用于 GLIBCXX_DEBUG

c++ - 需要一个命令行解析器来满足我的要求

c++ - 我怎样才能得到 char* 的实际长度? strlen 和 sizeof(target)/sizeof(target*) 有什么区别?

c++ - QDom 删除节点

c++ - std::vector 内存管理

c++ - 运算符重载 - 不匹配

android - 在 Android Studio 中为 NDK 项目构建符号花费的时间太长

c++ - 在程序选项中添加键值对