Boost 1.55.0程序选项问题
Boost 1.55.0 Program Options Issues
在过去几个月没有找到合理的ini文件读取方法后,决定最终咬紧牙,在Boost中下载,构建和链接。
在创建一个测试项目以查看过程如何工作后,我被程序在其中一个选项上抛出未知选项异常所困扰。以下是测试程序的输出以及捕获的错误消息(在try/catch中添加以进行正确的错误处理)以及ini文件内容和完整代码:
测试ini读取....
按任意键继续…
无法识别的选项'PLAYERDATA '。ID '
加载值:
名称:
ID: 8639072
gDiff:
游戏难度值:
偶遇随机性:5.96783e-039
玩家伤害修改:1.20858e-038
计算机损坏修改符:127232
项目范围低:-2
项目范围高:8623500
按任意键继续…
settings.ini:
[PLAYERDATA]
NAME = Game1A_g
ID = 12231
GDIFF = Medium
#Difficulty Values
[EASY]
ERAND = 0.25f
PDMOD = 2.12f
CDMOD = 0.65f
IRL = 1
IRH = 10
[MEDIUM]
ERAND = 1.00f
PDMOD = 1.00f
CDMOD = 1.00f
IRL = 1
IRH = 25
[HARD]
ERAND = 1.35f
PDMOD = 0.75f
CDMOD = 1.50f
IRL = 1
IRH = 30
代码:#include <iostream>
#include <Windows.h>
#include <string>
#include <fstream>
#include "boost/program_options.hpp"
using std::cout;
using std::string;
using std::endl;
using std::ifstream;
namespace gOp = boost::program_options;
struct prgVars
{
string name;
int id;
string gDiff;
float encRand;
float pDMod;
float cDMod;
int iRLow;
int iRHigh;
};
void loadGData(prgVars& pgv);
int main()
{
prgVars pgv;
cout << "Testing ini reading...." << endl;
system("Pause");
loadGData(pgv);
cout << "Loaded values:" << endl;
cout << "Name: " << pgv.name << endl;
cout << "ID: " << pgv.id << endl;
cout << "gDiff: " << pgv.gDiff << endl << endl;
cout << "Game Difficulty Values: " << endl;
cout << "Encounter Randomness: " << pgv.encRand << endl;
cout << "Player Damage Modifier: " << pgv.pDMod << endl;
cout << "Computer Damage Modifier: " << pgv.cDMod << endl;
cout << "Item Range Low: " << pgv.iRLow << endl;
cout << "Item Range High: " << pgv.iRHigh << endl;
system("Pause");
}
void loadGData(prgVars& pgv)
{
gOp::options_description desc("Settings");
desc.add_options()
("PLAYERDATA.NAME",gOp::value<string>(&pgv.name),"player_name"),
("PLAYERDATA.ID",gOp::value<int>(&pgv.id),"player_id"),
("PLAYERDATA.GDIFF",gOp::value<string>(&pgv.gDiff),"game_difficulty");
gOp::variables_map vm;
try
{
ifstream settings_file("settings.ini",ifstream::in);
gOp::store(gOp::parse_config_file(settings_file, desc), vm);
settings_file.close();
gOp::notify(vm);
}
catch (const gOp::error& e )
{
std::cerr << e.what() << std::endl;
}
if (pgv.gDiff == "Easy")
{
gOp::options_description desc("DVars");
desc.add_options()
("EASY.ERAND",gOp::value<float>(&pgv.encRand),"encounter_rate"),
("EASY.PDMOD",gOp::value<float>(&pgv.pDMod),"player_damage_bonus"),
("EASY.CDMOD",gOp::value<float>(&pgv.cDMod),"computer_damage_bonus"),
("EASY.IRL",gOp::value<int>(&pgv.iRLow),"item_rng_low"),
("EASY.IRH",gOp::value<int>(&pgv.iRHigh),"item_rng_high");
gOp::variables_map vm;
ifstream settings_file("settings.ini",ifstream::in);
gOp::store(gOp::parse_config_file(settings_file, desc), vm);
settings_file.close();
gOp::notify(vm);
}
else if (pgv.gDiff == "Medium")
{
gOp::options_description desc("DVars");
desc.add_options()
("MEDIUM.ERAND",gOp::value<float>(&pgv.encRand),"encounter_rate"),
("MEDIUM.PDMOD",gOp::value<float>(&pgv.pDMod),"player_damage_bonus"),
("MEDIUM.CDMOD",gOp::value<float>(&pgv.cDMod),"computer_damage_bonus"),
("MEDIUM.IRL",gOp::value<int>(&pgv.iRLow),"item_rng_low"),
("MEDIUM.IRH",gOp::value<int>(&pgv.iRHigh),"item_rng_high");
gOp::variables_map vm;
ifstream settings_file("settings.ini",ifstream::in);
gOp::store(gOp::parse_config_file(settings_file, desc), vm);
settings_file.close();
gOp::notify(vm);
}
else if (pgv.gDiff == "Hard")
{
gOp::options_description desc("DVars");
desc.add_options()
("HARD.ERAND",gOp::value<float>(&pgv.encRand),"encounter_rate"),
("HARD.PDMOD",gOp::value<float>(&pgv.pDMod),"player_damage_bonus"),
("HARD.CDMOD",gOp::value<float>(&pgv.cDMod),"computer_damage_bonus"),
("HARD.IRL",gOp::value<int>(&pgv.iRLow),"item_rng_low"),
("HARD.IRH",gOp::value<int>(&pgv.iRHigh),"item_rng_high");
gOp::variables_map vm;
ifstream settings_file("settings.ini",ifstream::in);
gOp::store(gOp::parse_config_file(settings_file, desc), vm);
settings_file.close();
gOp::notify(vm);
}
}
逗号太多了:
desc.add_options()
("PLAYERDATA.NAME" , gOp::value<string>(&pgv.name) , "player_name") /*HERE*/
("PLAYERDATA.ID" , gOp::value<int>(&pgv.id) , "player_id") /*HERE*/
("PLAYERDATA.GDIFF", gOp::value<string>(&pgv.gDiff), "game_difficulty");
注意,如果你在足够高的警告级别下编译,你的编译器会告诉你这个(以一种非常神秘的方式…)。
Live On Coliru 输出:Testing ini reading....
unrecognised option 'EASY.ERAND'
Loaded values:
Name:
ID: 4240909
gDiff:
Game Difficulty Values:
Encounter Randomness: 5.94265e-39
Player Damage Modifier: 0
Computer Damage Modifier: 0
Item Range Low: 0
Item Range High: 4215760
请注意,您可能还需要查看Boost PropertyTree来解析INI文件。
- http://www.boost.org/doc/libs/1_55_0/doc/html/boost_propertytree/parsers.html boost_propertytree.parsers.ini_parser
所以在她的帖子和T.C.的帮助下,我设法弄清楚了这个问题的评论。虽然添加的逗号是一个问题,但主要问题是我没有真正理解解析器是如何读取文件的。它根据add_options()的第一个参数中给出的对标识符一次读取整个内容,而不仅仅是其中的特定部分。
所以我遍历并为ini中的每个值创建了一个元素,即使我最终不打算使用它,并更新了第一个选项列表,看起来像这样:gOp::options_description desc("Settings");
desc.add_options()
("PLAYERDATA.NAME",gOp::value<string>(&cName),"player_name")
("PLAYERDATA.ID",gOp::value<int>(&pgv.id),"player_id")
("PLAYERDATA.GDIFF",gOp::value<string>(&pgv.gDiff),"game_difficulty")
("EASY.ERAND",gOp::value<float>(&pgv.encRand_e),"encounter_rate")
("EASY.PDMOD",gOp::value<float>(&pgv.pDMod_e),"player_damage_bonus")
("EASY.CDMOD",gOp::value<float>(&pgv.cDMod_e),"computer_damage_bonus")
("EASY.IRL",gOp::value<int>(&pgv.iRLow_e),"item_rng_low")
("EASY.IRH",gOp::value<int>(&pgv.iRHigh_e),"item_rng_high")
("MEDIUM.ERAND",gOp::value<float>(&pgv.encRand_m),"encounter_rate")
("MEDIUM.PDMOD",gOp::value<float>(&pgv.pDMod_m),"player_damage_bonus")
("MEDIUM.CDMOD",gOp::value<float>(&pgv.cDMod_m),"computer_damage_bonus")
("MEDIUM.IRL",gOp::value<int>(&pgv.iRLow_m),"item_rng_low")
("MEDIUM.IRH",gOp::value<int>(&pgv.iRHigh_m),"item_rng_high")
("HARD.ERAND",gOp::value<float>(&pgv.encRand_h),"encounter_rate")
("HARD.PDMOD",gOp::value<float>(&pgv.pDMod_h),"player_damage_bonus")
("HARD.CDMOD",gOp::value<float>(&pgv.cDMod_h),"computer_damage_bonus")
("HARD.IRL",gOp::value<int>(&pgv.iRLow_h),"item_rng_low")
("HARD.IRH",gOp::value<int>(&pgv.iRHigh_h),"item_rng_high");
然后从try/catch之后的函数中删除所有其他代码。现在在main中使用的是在每个难度之间进行分支,然后计算相关变量的值。
输出现在显示正确:
测试ini读取....
按任意键继续…
Game1A_g
加载值:
名称:Game1A_g
ID: 12231
gDiff:中等
游戏难度值:
偶遇随机性:1
玩家伤害修改符:1
计算机损伤修改符:1
产品范围低:1
产品范围高:25
按任意键继续…
所以,总的来说,你必须在第一个这样的列表中包括每个ini选项在你的add_options()列表中,否则你会有同样的问题,我用程序抛出未知选项错误,而不是从文件中获取数据或使用parse_config_file的bool参数(使用true忽略未知选项)。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- Win32编译器选项和内存分配
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 添加选项以显示百分比时出现生成文件问题
- C++编译器问题:3>cl:命令行错误 D8016:'/clr'和'/arch:SSE2'命令行选项不兼容
- 整个存档和无whole_archive选项的链接问题
- 如果我使用c++11功能编译一个文件,同时将其链接到一个没有c++11编译器选项编译的库,会有什么问题吗
- Boost 1.55.0程序选项问题
- Windows无边界OpenGL窗口有奇怪的选项卡问题