C++解析含嵌套花括号的自定义配置文件实现方案咨询
嵌套自定义配置解析实现方案
核心思路
你当前遇到的逐行解析失效、不支持嵌套的问题,本质是逐行处理逻辑和配置的物理格式绑定太死。最优方案是先做词法拆分(Token化) 解除换行/空格的影响,再用递归下降解析 处理嵌套结构,这套方案效率高、扩展性强,完全适配你后续的配置迭代需求。
实现步骤
1. 词法分析(Token化)
把整个配置文件一次性读入内存,遍历字符时直接跳过空格、换行、Tab、// 注释,把内容拆分为独立的语义单元(Token),类型可定义如下:
enum TokenType { TOKEN_IDENT, // 标识符:MODEL、FILEPATH、DATA0等 TOKEN_STRING, // 双引号包裹的字符串 TOKEN_NUMBER, // 数字(含浮点数) TOKEN_BOOL, // true/false TOKEN_COLON, // : TOKEN_EQUAL, // = TOKEN_LBRACE, // { TOKEN_RBRACE, // } TOKEN_COMMA, // , TOKEN_SEMICOLON,// ; TOKEN_EOF // 文件结束 }; struct Token { TokenType type; std::string strVal; // 存储标识符、字符串内容 float numVal = 0.f; // 存储数字值 bool boolVal = false;// 存储布尔值 };
词法分析只需要一次线性遍历,完全忽略物理换行、缩进,不管配置写在一行还是拆成多行,输出的Token序列完全一致,从根源解决换行适配问题。
2. 递归下降解析嵌套结构
维护一个指向当前Token的指针,按照配置的语法规则递归解析:
- 遇到
MODEL:标识符,读取后续字符串作为tagName,遇到{进入Model块解析 - Model块内逐键解析:遇到
FILEPATH/TEXTUREPATH/NORMALPATH直接读取后续字符串赋值 - 遇到
PLACEHOLDER =后接{,进入嵌套块解析,读取DATA0~DATA3的值赋值给对应结构体字段 - 遇到
}退出当前层级的块,回到上层继续解析
3. 配置格式优化建议
只需做两处小调整即可大幅降低解析复杂度,不用整体修改现有格式:
- 所有键值对末尾统一加
;(你当前示例中DATA0 = true行缺少分号,补齐即可) - 注释统一用
//开头,词法分析阶段直接跳过即可
可选轻量方案
如果你不想自行实现完整解析逻辑,可以把配置格式微调为标准JSON格式,引入单头文件库nlohmann/json 完成解析,示例代码如下:
#include "nlohmann/json.hpp" using json = nlohmann::json; // 配置JSON格式示例 /* { "models": [ { "tagName": "modelname1", "filePath": "FILEPATH1", "texturePath": "TEXTUREPATH1", "normalPath": "NORMALPATH1", "placeholder": { "data0": true, "data1": [1.0, 1.0, 1.0], "data2": [1.0, 1.0, 1.0], "data3": [1.0, 1.0, 1.0] } } ] } */ // 解析代码 std::ifstream f("config.json"); json data = json::parse(f); for (auto& model_json : data["models"]) { ModelData md; md.tagName = model_json["tagName"]; md.filePath = model_json["filePath"]; md.texturePath = model_json["texturePath"]; md.normalPath = model_json["normalPath"]; md.Data0 = model_json["placeholder"]["data0"]; auto& d1 = model_json["placeholder"]["data1"]; md.Data1 = {d1[0], d1[1], d1[2]}; // 剩余字段同理赋值 g_modelData.push_back(md); }
该方案无需自行处理词法、嵌套逻辑,开发效率最高,性能也完全满足资源加载的需求。
内容的提问来源于stack exchange,提问作者user8616480
相关产品推荐
相关产品推荐

