C++中如何将用户输入的字符串转换为可调用函数?
问题描述
我正在开发一个学校项目,需要用二分法(bisection)、试位法(regula falsi)和割线法三种方法求解非线性函数的根,同时对比标准算术与区间算术,区间运算使用boost interval库。目前程序里固定使用cos函数,现在想支持用户输入自定义函数(比如x*x-3或sin(x)),但不知道怎么把字符串输入转换成可调用的函数,是不是需要做表达式解析?
当前函数定义:
Interval f(const Interval& function) { return cos(function); }
二分法调用示例:
if (f(xi) * f(przedzial.lower()) < Interval(0))
可行实现方案
1. 手写表达式解析器(适合学习场景)
作为学校项目,手写简单的表达式解析器是很好的实践。核心思路是将用户输入的字符串拆解为语法单元(数字、运算符、函数名、变量x),通过递归下降法直接计算,或者构建抽象语法树(AST)后求值。
适配boost interval的核心要点:
- 识别变量
x时,直接替换为传入的Interval参数 - 所有算术运算(
+、-、*、/)都使用boost interval提供的重载运算符 - 数学函数(
sin、cos、sqrt等)调用boost interval对应的库函数
简化示例逻辑:
Interval evaluate(const std::string& expr, const Interval& x) { // 实现递归下降解析逻辑: // 1. 跳过空格,拆分表达式为项、因子、原子单元 // 2. 遇到`x`返回传入的Interval值 // 3. 遇到数字转换为Interval类型 // 4. 遇到`sin(x)`这类函数调用,执行boost::numeric::interval::sin(x) }
2. 利用轻量级表达式解析库(快速实现)
如果不想从零写解析器,可以用轻量级的C++表达式解析库(比如ExprTk),它支持将字符串表达式编译为可调用的函数对象,且能直接适配boost interval类型。
实现框架:
#include "exprtk.hpp" typedef exprtk::symbol_table<Interval> symbol_table_t; typedef exprtk::expression<Interval> expression_t; typedef exprtk::parser<Interval> parser_t; Interval evaluate_custom(const std::string& expr_str, const Interval& x_val) { symbol_table_t symbol_table; symbol_table.add_variable("x", x_val); symbol_table.add_constants(); // 自动加入pi、e等常量 expression_t expression; expression.register_symbol_table(symbol_table); parser_t parser; if (!parser.compile(expr_str, expression)) { // 处理表达式编译错误,比如语法错误、未知函数 throw std::invalid_argument("Invalid expression: " + parser.error()); } return expression.value(); }
3. 动态编译(进阶方案)
把用户输入的函数字符串生成临时C++代码,调用编译器动态编译成共享库,再加载到程序中调用。但这种方法复杂度高,需要处理跨平台编译逻辑,学校项目一般不推荐。
注意事项
- 必须处理用户输入错误:比如语法错误、不支持的函数/运算符,返回明确的错误提示
- 所有运算必须适配boost interval特性:禁止用普通float/double的运算逻辑替代区间运算,确保结果符合区间算术的精度要求
内容的提问来源于stack exchange,提问作者Filip Pieprzyk
相关产品推荐
相关产品推荐

