尝试解析保存为std :: string的大型文本文件

时间:2013-12-20 08:27:00

标签: c++ parsing stl

我有一个文本文件,我必须读入并从属于关键字的参数中提取数据。我正在读的这个文本文件是一个加载到其他文件中的查找表。我已通过文件流将此文件读入内存并将其另存为std::string。完整的文本文件现在作为私有成员变量std::string类型保存在我的类中。我在我的类中调用一个私有函数,将此文本文件作为一个字符串传递。此函数用于解析查找关键字的文件,然后从中提取数据。此外,一些关键词出现的次数超过一次,我需要每次出现的次数。

这是我的txt文件的样子。

: This is a comment.

HEADER[AudioBookReader v1.0]
TITLE[Gulliver's Travel]
AUTHOR[Jonathan Swift]
YEAR[1726]
CHAPTER_COUNT[39]

TABLE_OF_CONTENTS

INTRO[intro]  

SECTION[Part I. A Voyage To Lilliput]
CHAPTER[gt_1_01] 
CHAPTER[gt_1_02]
: more CHAPTERs

SECTION[Part II. A Voyage To Brobdingnag]
CHAPTER[gt_2_01]
CHAPTER[gt_2_02]
: more CHAPTERs

SECTION[Part III. A Voyage To Laputa, Balnibarbi, Luggnagg, Glubbdubdrib, And Japan]
CHAPTER[gt_3_01]
CHAPTER[gt_3_02]
CHAPTER[gt_3_03]
: more CHAPTERs and SECTIONs


OUTRO[NONE]         : This is here as an example if there is none it can be 
                    : omitted or use the tag NONE inside the parameter braces. 

END                 : This tag represents the end of the file anything after
                      will not get parsed, as you can see I did not use a comment.

所有大写单词都是标签或关键字。大括号内的任何内容都是需要的数据。在该行上冒号“:”之后的任何内容都将被跳过,在END标记之后的任何内容都将被忽略并且解析完成。大多数关键字都有与之相关的数据,在大多数情况下,我需要一串文字。

只有前五个有数据的标签才有一个实例。只有两个标签没有与之关联的任何数据,TABLE_OF_CONTENTSENDTABLE_OF_CONTENTS的唯一属性是表示我们已经达到了本书文本部分的开头。其余标签可以多次显示。有些必须有与之关联的数据,有些则是可选的。例如,INTRO是可选的标签或关键字。 INTROOUTROCHAPTER在方括号内有文本,此文本表示没有扩展名的文件名。 SECTIONNAME中的文本(如果显示)将只是保存到函数中的字符串的文本,该函数解析存储在我的类中的内部结构中的此文件。另一个关键字中唯一可以存在的关键词是NONE。例如,NAME[NONE]意味着没有与intro,outro或chapter相关联的名称。相反,最好只省略NAME标签。但是文本文件中的选项是正在读取文本文件的用户创建此类型的文件。

我的课程已接近完成,我要做的就是创建此解析功能并提取并保存我的数据。我有一些规则要遵循这个解析文件。每个带参数数据的关键字都在文本文件中各自独立的一行。但是因为这个文件被读入并保存为字符串。以下是我的问题或疑虑。

  1. 如何搜索此存储的字符串并提取每个括号之间的内容并将其保存到子字符串中,同时记录每个关键字显示的次数。

  2. 这是一个更好的解决方案,而不是一次性读取此文本文件的所有内容到std :: string,并让我的解析器逐行读取文本直到结束如果是这样怎么办呢?

  3. 逐行方法(我的初始方法)的问题有点困难,因为我在这个类之外有一个处理文本文件流的外部类。它是一个读入文本的继承类,其中我有另一个类,它继承自将文件写入文本的读取器所在的类。父类负责打开txt文件并使用和不使用路径保存文本文件名,继承的类负责关闭父类打开的文件流。由于我的文本文件阅读器只读取所有数据并将其保存为字符串,这就是我将此文本文件作为字符串传递到我的解析函数的原因。

    我还想保留这种文本文件格式的结构,并且可能在路上也能够以二进制文件的形式读取它,并且有两种选择。如果这很长,我道歉,但有必要得到我的观点。它不仅仅是从中获取子文本,而且还跟踪重复的关键字并确保某些关键字存在而其他关键字是可选的。

1 个答案:

答案 0 :(得分:2)

你自己很难,因为你没有分开顾虑。

你遇到的主要问题是解析。这是一项非常重要的任务。次要问题是std::string,并处理文件I / O类。

解析是一项众所周知的任务。它可以很好地适用于任何合理的文本表示,包括std::string。所以不要再担心这些问题了。您的void parse(std::string wholeInput)方法应该只进行解析,而不执行任何其他操作。它不应该关心那个字符串来自

解析总是用语法来解决。有时它是使用显式语法完成的,在这种情况下,有很多工具可以生成解析器。但作为练习,您仍然可以编写自己的解析器。

解析的第一步是lexing。这会在单独的令牌中分解输入。在这种情况下,你似乎有简单的lexing规则。令牌是(1)可能是下划线的字母序列,(2)在[]或(3)之间的任何东西:和下一个换行符之间的任何东西。您甚至可以使用快捷方式并将注释视为空格,并在词法分析器中忽略它们。

解析的第二步现在获得了一组很好的预先分类的令牌。您可能需要两个函数,一个用于识别case(1)中的关键字,另一个用于在案例(2)中从[ ]中获取参数。

第三步也是最后一步是针对那些已识别的关键字执行特定于应用程序的操作。我不能在那里给你很多建议,你应该知道如何处理这些关键字及其论点。但是,计算它们当然很容易。