如何使用更通用的数据结构

How can I use a more generic data structure?

本文关键字:数据结构 何使用      更新时间:2023-10-16

>我正在尝试创建一个文本解析器,该解析器将允许有限的用户定义的替换规则。

也就是说,我正在从DOS ASCII文件中读取代码,其中排序很重要,并且必须保持行号。 有了这个输入,我想应用用户定义的替换规则(用这个字符串交换那个字符串,如果我们看到这个字符串后跟那个字符串,执行这个翻译,等等(。

输出也是一个格式化的 DOS ASCII 文件。

大多数规则都是直接替换 tit 进行 tat 类型替换,但是,在某些情况下,我想定义一个规则,例如如果 A 后面跟着 B 在将来的任何时候,请应用此规则。

为此,我使用了这样的结构树:

struct node {
    list<string> common;  // the text which is not affected by conditions
    string condition;     // matching this string selects the left, otherwise the right
    node *lptr, *rptr;    // pointers to the child nodes, if needed
};

每当我遇到这样的规则时,我都可以在省略和应用规则的情况下维护输出,延迟决定使用哪个规则,直到明确解决为止。

这有点浪费内存,但似乎是避免两次传递输入数据的最佳方法(输入数据的大小未知,但可能小于 1 meg(。

当然,可能存在这样的情况,即在一个或两个子节点中触发这种类型的不同规则,因此这就是树结构的原因。

没有限制孩子必须在父母之前决定,可能是父母只能在孩子的一个分支上决定。 遇到EOF会决定任何犹豫不决的孩子朝着错误的方向发展。

所以很明显,我在倒带和折叠节点时必须小心。

对于这个普遍问题,有更简单的解决方案吗? 有没有办法以比我的树呈现的更有效的方式使用标准库容器?

你可能想看看NFA和DFA,即非确定性有限状态自动和确定性有限状态自动。这两种方法是编写解析器的最常见且通常非常有效的方法。

实际上不需要将数据存储在节点中,否则它会被传递并浪费内存。更好的方法是,分配一个变量(例如 int state = 0(来跟踪当前的解析状态。根据当前状态和输入,您的算法将更改状态。状态总是向前移动,但你可以告诉你的算法在某个条件不匹配时返回到以前的某个状态(称为"回溯"(。

例如,如果"ab"和"ac">

是两个有效的输入,那么在解析"ac"时,算法可能是这样的:

char is 'a' ==> go to state.checkB
char is not 'b' ==> go back to state.checkA
checkB was already done ==> go to state.checkC
char is 'c' ==> DoSomething();

需要大量的文章和图表才能完全解释所有内容,希望这会让您知道在哪里进一步查看。

假设"文本解析器"的意思是你试图压缩相同含义的单词和短语,以简化对命令的反应。

在这种情况下,根据旧文本冒险程序,使用规则查找表的简单左右解析器将在这里工作。

除非我误解了您的问题域,否则您的解决方案似乎过度设计。

听起来你应该尝试正则表达式。以下是有关选择库的讨论链接:C++正则表达式库选择。Boost是一种流行的。

另外,您是否考虑过使用另一种语言来解决问题?Python有一个很好的有用库基础,包括一个用于正则表达式(import re(的库。如果它在您的驾驶室中,您可能会发现它比C++解决方案更容易。

最后,考虑对输入文件使用"已定义"的文本格式,而不是自定义格式。XML 是一个不错的选择。在 XML 树中嵌套规则可能更容易。C++,你可以使用Expat XML解析器(Python将是xml.etree.ElementTree(。