如何从Exprtk表达式中获取返回的字符串结果?
如何从Exprtk表达式中获取返回的字符串结果?
Exprtk中直接调用expression.value()仅能获取数值结果,对于返回字符串的表达式(比如示例中的if(1>0,'One','Two'))会得到NaN。调试时发现表达式的control_block_私有属性里的string value_已存储正确的字符串结果,但无法直接访问。目前已知可通过return[]语句或显式定义字符串变量来获取结果,但希望能有更便捷的方式,以下是可行解决方案:
示例问题代码
#include "exprtk.hpp" int main() { typedef exprtk::symbol_table<double> symbol_table_t; typedef exprtk::expression<double> expression_t; typedef exprtk::parser<double> parser_t; const std::string expression_string = //"if (1 > 0) {'One';} else {'Two';}"; "if (1 > 0,'One','Two')"; expression_t expression; parser_t parser; if (parser.compile(expression_string, expression)) { double result = expression.value(); // 如何在此处获取字符串结果? } return 0; }
解决方案
方法1:绑定显式字符串变量(官方推荐)
在符号表中定义字符串变量,让表达式将结果赋值给该变量,这是最稳妥的官方支持方式:
#include "exprtk.hpp" int main() { typedef exprtk::symbol_table<double> symbol_table_t; typedef exprtk::expression<double> expression_t; typedef exprtk::parser<double> parser_t; std::string result_str; symbol_table_t symbol_table; symbol_table.add_stringvar("str_result", result_str); const std::string expression_string = "str_result := if (1 > 0,'One','Two');"; expression_t expression; expression.register_symbol_table(symbol_table); parser_t parser; if (parser.compile(expression_string, expression)) { expression.value(); // 执行表达式,结果自动写入result_str printf("结果:%s\n", result_str.c_str()); } return 0; }
方法2:利用return[]语句捕获字符串
通过表达式中的return[]返回字符串,再调用表达式的return_values()方法获取结果(需确保使用的Exprtk版本支持该特性):
#include "exprtk.hpp" int main() { typedef exprtk::symbol_table<double> symbol_table_t; typedef exprtk::expression<double> expression_t; typedef exprtk::parser<double> parser_t; const std::string expression_string = "return[if (1 > 0,'One','Two')];"; expression_t expression; parser_t parser; if (parser.compile(expression_string, expression)) { expression.value(); // 执行表达式 const auto& return_vals = expression.return_values(); if (!return_vals.empty() && return_vals[0].is_string()) { std::string result_str = return_vals[0].string_value(); printf("结果:%s\n", result_str.c_str()); } } return 0; }
方法3:直接访问私有成员(不推荐用于生产环境)
若需临时调试或特殊场景,可通过类型转换绕过私有成员访问限制,但这属于未定义行为,依赖Exprtk内部实现,版本更新后可能失效:
// 仅用于调试,生产环境禁止使用 #include "exprtk.hpp" #include <cstddef> // 需与Exprtk源码中control_block的结构完全匹配,避免内存偏移错误 struct FakeControlBlock { std::string value_; // 补充Exprtk control_block中的其他成员变量 }; int main() { typedef exprtk::symbol_table<double> symbol_table_t; typedef exprtk::expression<double> expression_t; typedef exprtk::parser<double> parser_t; const std::string expression_string = "if (1 > 0,'One','Two')"; expression_t expression; parser_t parser; if (parser.compile(expression_string, expression)) { expression.value(); // 强制转换获取control_block_,依赖内部内存布局 FakeControlBlock* fake_cb = reinterpret_cast<FakeControlBlock*>(&expression.control_block_); printf("结果:%s\n", fake_cb->value_.c_str()); } return 0; }
说明
Exprtk核心设计面向数值计算,字符串处理属于附加特性,官方推荐使用前两种规范方式获取字符串结果。直接访问私有成员会破坏封装性,且无法保证跨版本兼容性,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者DuxburyDutch
相关产品推荐
相关产品推荐

