在C ++中查找字符串中的子字符串标记

时间:2010-12-03 23:17:05

标签: c++ xml parsing tokenize

好吧,假设我正在解析一些XML(在阅读任何“语言”时存在问题,但XML是很多人都熟悉的。)

XML如下所示:

<Tag>
  <[CDATA[ blah blah]]>
  <Tag2>
    <Tag3/>
  </Tag2>
<Tag>

现在我想在该流中找到各种令牌。重要的令牌如下(请原谅我糟糕的“令牌”名称;))。

<           = Open Token
<[CDATA[    = Open CDATA Token
]]>         = Close CDATA Token
<!          = Open Comment Token
/>          = Close Open Token
</          = Open Close Token
>           = Close Token

我遇到的问题是我有一个上面的数组,我正在尝试正确识别上述令牌中的一个,因为我逐字逐句地读取文件。

所以我读了第一个字符'&lt;'。当下的想法是,这与“开放令牌”匹配,所以我们将选择它。但是,它也与“打开关闭令牌”的第一个字符匹配。所以我们说我们读第二个字符及其'A'。所以我立即知道这是“开放令牌”而不是“打开关闭令牌”。

同样在完成标签时,例如“/&gt;”。我读了第一个字,我得到'/'。这与“Close Open Token”相匹配。但它不完整所以我应该检查下一个字符,在这种情况下是'&gt;'给我“/&gt;”它与Close Token匹配。

我的问题是,当这些令牌的数量显着增加时,很难跟踪可能的匹配是什么。有一种优雅的方式来做到这一点?或者我应该,只是当我遇到其中一个“令牌字符串”的第一个字符时,将该令牌推送到一个向量,然后在后续读取时只检查这些令牌?如果下一个字符不匹配,那么我可以清除令牌列表然后重新开始。

这是解决问题的正确方法吗?还有更好的方法吗?

(编辑:请不要指向Lexx,YACC等......我正在尝试学习一些基础知识)

任何帮助都会非常感激:)

4 个答案:

答案 0 :(得分:1)

您需要在解析器中跟踪状态 - 我现在在哪里?我接下来会发生什么? - 以特定于上下文的方式。当您看到下一步得到的内容时,可以根据当前状态的有效值列表进行检查,并可能存储已完成的已解析数据项,并可能更改状态。

仅解析XML 看起来很简单< - em>如果你真的想自己手工完成这项工作,那么就有很多需要处理的问题。你的解析器是Finite State Machine,但这是一个非平凡的例子。

答案 1 :(得分:1)

我最近一直在做很多这种类型的解析(主要是使用C#)。

我不确切知道你要完成什么,所以我不确定这有多少帮助,但我会解析整个事情并将其存储在某种数据阵列中。

找到开始标记。然后解析接下来的任何文本(你知道当你到达文本的末尾,因为你要么点击空格或标点符号)。

您可以为“!”进行特殊测试并且可能在找到数据结构时在其中设置一个标志。我发现对已知序列进行快速扫描是不切实际的。你需要逐字逐句地分解整个事物。

您可以在http://www.softcircuits.com/Blog/post/2010/02/07/Parsing-HTML-Tags-in-C.aspx看到我的一个C#结果。

答案 2 :(得分:0)

您可以flex为您执行此操作。更好的是,为您的语言挖掘现有的XML解析器 - 我确信有人已经实现了它。

答案 3 :(得分:0)

解析是一个众所周知的问题,但这并不意味着它很容易编程。 你可以自己写任何东西,但正如你遇到的那样,这变得非常复杂。

您可以使用Boost.Spirit库,它非常大,可能需要一些时间来掌握。

或者作为替代方案,使用Lex / Yacc(或类似的东西)生成解析器和词法分析器。 (这比C ++更多C,但当然不一定是坏事)

我个人花时间学习掌握Boost Spirit库,虽然一开始可能看起来很多,但从长远来看,你会节省很多时间和头痛。手动解析类似XML的语言需要的工作量比您最初预期的要多得多。