在运行时

时间:2015-07-11 20:28:56

标签: c++ function rpn

我设计的程序可以对流数据执行某些操作。 操作由运行时提供的RPN(反向抛光表示法)表达式定义。数据从文件源流式传输,一次一个固定大小的部分。操作引用了一些当前输入的数据部分,如data[1]。程序对所有输入部分应用相同的操作(并输出结果)。

实现一个对数字和算术运算进行操作的RPN解析器很容易给出结果。但是,使用这样的实现意味着需要为每个数据部分重新解析RPN。

我想要实现的是以某种方式构建一个对象,该对象将基于数据基本操作的字母表来保存曾经解析过的RPN实现,其中程序将提供输入数据(或填充输入),调用对象的operator()来获取并输出结果。

如何实现这样一个类(callable expression)并使用' non-modern'来构造这样的对象? C ++(没有C++11C++14)?

1 个答案:

答案 0 :(得分:1)

由于其RPN,可以将操作建模为堆栈的一系列转换。在堆栈上加载一个输入部分然后按顺序执行操作就可以了。不需要树,它隐含在操作顺序中。不需要重新解析,它确实是一系列操作(函数或函子),而不是表示操作的符号序列。

我会选择一个仿函数,因为我喜欢存储对象的引用或指针比存储函数的引用或指针更好。你将它实现为一个具有重载operator()的类,它执行所需的堆栈转换(如果它是一个乘法仿函数,则将两个顶部元素相乘)。

Ancient device working that way...

上图:古代设备以这种方式工作......

关于堆栈中存储的内容以及不存储的内容:

  • 首先,您的操作数存储在与输入顺序匹配的队列中
  • 您的操作员对象,解析一次且从不更改的结果,将分别存储在操作员队列中。
  • 应用'get'运算符会将一个操作数从队列传输到操作数堆栈

所以,例如如果你想计算

sin (3 + 4) / (5 + 6)

你的操作数队列是:

[start] 3 4 5 6 [end]

您的操作员对象队列(它包含指向仿函数的指针,而不是符号,每个仿函数只有一个实例,但可能多次引用)是:

[start] &getFunctor &getFunctor &addFunctor &sinFunctor &getFunctor &getFunctor &addFunctor &divideFunctor [begin]

你的操作数堆栈开始崩溃:

[top][bottom]

应用运算符队列将随后为您提供:

(get)    [top] 3 [bottom]
(get)    [top] 3 4 [bottom]
(add)    [top] 7 [bottom]
(sin)    [top] 0.657 [bottom]
(get)    [top] 5  0.657 [bottom]
(get)    [top] 5 6  0.657 [bottom]
(add)    [top] 11  0.657[bottom]
(divide) [top] 0.0597 [bottom]

如果您希望将完全相同的操作应用于例如

[start]10 20 30 40[end]

只需替换操作数队列(或让操作数队列的起始指针指向操作数文件的下一个“块”),然后再针对这个新的操作数序列运行操作符队列。

请注意,如上所述,操作符队列不包含操作符,而是指向准备好的函数对象的指针,这些函数将在您调用它们时立即执行,而无需重新分析或重新生成代码。

所以如果你有很多数据:

[start of file]3 4 5 6   10 20 30 40   -1 -10 15 80 ...[end of file]

您只需继续应用相同的操作员队列,一切都会正常工作。