2014-05-17 36 views
1

决定在最近几个月未能找到合理的ini文件读取方法后,最终咬紧牙关,下载,构建和链接Boost。Boost 1.55.0程序选项问题

在创建一个测试项目以查看过程如何工作之后,我在程序中遇到了一个抛出未知选项异常的选项。下面是测试程序的输出与捕获的错误信息(在一个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); 
    } 
} 

回答

2

你有太多的逗号:

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 

请注意,你可能想看看升压PropertyTree解析INI文件了。

+0

感谢您的回复,因为它帮助我追踪了除额外逗号以外的主要问题。我没有考虑到每一个ini选项的存在,所以当它通过ini文件时,它窒息了它无法找到的第一个选项。我会在我的回答中更好地解释。 – Geowil

+1

这仍然关闭,因为'parse_config_file'在默认情况下会在它看到一个它不能识别的选项时抛出,这里不需要。你希望所有'parse_config_file(settings_file,desc)'调用都是'parse_config_file(settings_file,desc,true)'。 –

0

所以我设法从sehe的帖子和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之后的函数中的其他代码。相反,现在主要用于在每个难度之间进行分支,然后对相关变量的值进行计数。

输出现在显示正确:

测试INI阅读....

按任意键继续。 。 。

Game1A_g

加载的值:

名称:Game1A_g

ID:12231

GDIFF:中等

游戏难度值:

遭遇随机性:1

球员伤害修正:1

电脑伤害修正:1个

项目范围低:1个

项目范围高:25

按任意键继续。 。 。

因此,简言之,你必须包括每个INI在add_options()列表中的第一个这样的列表中选择,否则你将有我与程序抛出未知的选项错误,并没有得到数据的相同问题从文件或使用parse_config_file的bool参数(使用true忽略未知选项)。