我有一个文本文件,我必须读取该文件并从属于关键字的参数中提取数据。我正在阅读的此文本文件是一个要在其他文件中加载的查找表。我已通过文件流将该文件读入内存,并将其另存为std::string
。现在,完整的文本文件作为私有(private)成员变量std::string
类型保存在我的类(class)中。我正在类中调用一个私有(private)函数,以一个字符串形式传入此文本文件。此功能是解析文件以查找关键字,然后从中提取数据。另外,有些关键词出现的次数多于一次,因此我需要计算每次出现的次数。
这是我的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_CONTENTS
和END
。 TABLE_OF_CONTENTS
的唯一属性是代表我们已经到达本书文本部分的开头。其余标签可以显示多次。一些必须与它们关联的数据,另一些是可选的。例如,INTRO
是可选的标签或关键字。 INTRO
,OUTRO
和CHAPTER
在方括号内有文本,该文本表示文件名,不带扩展名。 SECTION
或NAME
中的文本(如果显示)将只是文本,该文本将保存到函数中,该函数将解析此文件的字符串存储到我的类的内部结构中。另一个关键字中可以存在的唯一关键字是NONE
。例如,NAME[NONE]
意味着没有任何名称与简介,结尾或章节相关。相反,最好完全省略NAME标签。但是,文本文件中的选项供正在读取文本文件的用户创建自己的这种类型的文件。我的类(class)快要结束了,剩下要做的就是创建这个解析函数,然后提取并保存数据。我对此解析文件有某些规则要遵循。每个带有参数数据的关键字都在文本文件中的单独一行上。但是由于已读取此文件并将其保存为字符串。这是我的问题或疑虑。
逐行方法(我的最初方法)的问题要难一些,因为我在此类之外有一个外部类来处理文本文件流。它是一个继承的类,可读取文本,其中还有另一个类,该类是与将文件写入文本的读取器相同的类所继承的。父类负责打开txt文件并保存带路径和不带路径的文本文件名,继承的类负责关闭父类打开的文件流。并且由于我的文本文件阅读器仅一次读取所有数据并将其保存为字符串,因此这就是为什么我将此文本文件作为字符串传递给我的解析函数的原因。
我还希望保持这种文本文件格式的结构,并且可能在将来也能够将其作为二进制文件读取并同时具有这两种选择。如果时间太长,我深表歉意,但有必要阐明我的观点。这不仅是从中获取潜台词,而且还要跟踪重复的关键字并确保存在某些关键字而其他关键字是可选的。
最佳答案
您正在为自己感到困难,因为您无法分开关注点。
您遇到的主要问题只是解析。这是一项艰巨的任务。次要问题是std::string
,以及处理文件I / O类。
解析是一个易于理解的任务。它可以在任何合理的文本表示形式(包括std::string
)上完美地运行。因此,不必担心这些问题。您的void parse(std::string wholeInput)
方法应该只是解析,什么也不做。它完全不关心该字符串来自的。
语法解析总是很重要的。有时,它是通过显式语法完成的,在这种情况下,有很多工具可以为您生成解析器。但作为练习,您仍然可以编写自己的解析器。
解析的第一步是词法化。这会将输入分解为单独的 token 。在这种情况下,您似乎有简单的词汇规则。 token 是(1)可能带有下划线的字母序列,(2)[]之间的任何内容或(3):与下一个换行符之间的任何内容。您甚至可以使用快捷方式并将注释视为空格,并在词法分析器中忽略它们。
现在,解析的第二步将获得一组不错的预分类 token 。您可能需要两个函数,一种在情况(1)中识别关键字,另一种在情况(2)中从[ ]
中获取参数。
第三步,也是最后一步,就是对那些公认的关键字进行特定于应用的操作。在那儿我不能给您太多建议,您应该知道如何处理这些关键字及其参数。但是,计算它们当然很容易。
关于c++ - 尝试解析保存为std::string的大文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20699215/