利用Boost,我想
- 从 ini 文件中读取选项,如果在 ini 文件中遇到未知选项则中止
- 稍后将它们保存在另一个 ini 文件中。
第一部分可以使用 boost::program_options 完成:
try{
inifile_options.add_options()
("ops1.i0", po::value<int>(&p.nx)->default_value(1), "test integer")
;
po::variables_map vm;
po::store(po::parse_config_file(pthfnini, inifile_options), vm);
po::notify(vm);
}
catch(exception& e){
cerr << "error: " << e.what() << "\n";
errorflag=1;
}
据我所知,使用 boost::program_options 不可能编写 inifile,但 boost::property_tree 可以:
pt::ptree iniPropTree;
pt::ini_parser::write_ini("./used0.ini",iniPropTree);
现在的问题是如何将 po::variables_map 中存储的数据转换为 pt::ptree?
阅读 boost 文档给我的印象是这是不可能的。以下是唯一可行的方法吗?
iniPropTree.put<int>("ops1.i0",vm["ops1.i0"].as<int>();
根据我的口味,它引入了相当多的冗余。但是,从头开始将数据读入属性树似乎不支持检查未定义/拼写错误的选项。
或者,是否可以迭代variables_map的内容并以某种方式推断每个元素相应的数据类型?
完整代码在这里:
/*
* g++ iniOps_test.cpp -Wall -std=c++11 -O3 -lboost_system -lboost_program_options -o iniOps_test.exe
*
*/
// C++11 & Boost libraries
#include <boost/program_options.hpp> // po::options_description, po::variables_map, ...
#include <boost/property_tree/ptree.hpp> // pt::ptree
#include <boost/property_tree/ini_parser.hpp> // write_ini()
#include <iostream> // cout
#include <fstream> // ofstream, ifstream
// namespaces
namespace po = boost::program_options;
namespace pt = boost::property_tree;
using namespace std;
struct params{
std::string inipthfn;
int i0;
};
void read_inifile(params &p, po::variables_map &vm){
// initialize variables
int errorflag=0;
std::ifstream pthfnini("./testini.ini");
po::options_description inifile_options("Allowed inifile options");
try{
inifile_options.add_options()
("ops1.i0", po::value<int>(&p.i0)->default_value(1), "test integer")
;
;
po::store(po::parse_config_file(pthfnini, inifile_options), vm);
po::notify(vm);
}
catch(exception& e){
cerr << "error: " << e.what() << "\n";
errorflag=1;
}
pthfnini.close();
if(errorflag){ std::cout<<"--- program shutdown due to error in read_inifile ---"<<std::endl; exit(1); }
}
int main(){
params p;
po::variables_map vm;
pt::ptree iniPropTree;
read_inifile(p,vm); // get options from inifile
// ??? conversion from vm -> pt ???
pt::ini_parser::write_ini("./used0.ini",iniPropTree); // save options to used.ini
cout << p.i0 << endl;
return 0;
}
ini文件“testini.ini”的内容是:
[ops1]
i0=2
最佳答案
这里有一个概念问题。
命令行参数本质上是文本的。
变量映射中的值不是。使用的类型在值语义(选项描述的一部分)中配置。
如果您的所有选项都具有相同的类型,您可以“作弊”并对转换进行硬编码:
pt::ptree to_ptree(po::variables_map const& vm) {
pt::ptree tree;
for (auto& v : vm) {
if (!v.second.empty() && !v.second.defaulted())
tree.put(v.first, v.second.as<int>());
}
return tree;
}
这节省了:
[ops1]
i0=1
如果您需要更大的灵活性,您至少需要访问选项描述。这不是该库的预期用途,您可能很快就会遇到未记录的实现部分。
关于c++ - 使用 boost::{program_options,property_tree} 读取/写入 inifiles,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50233440/