【C++ Primer Chapter12&15】TextQueries Project
TextQueries Project
问题:
我们将实现一个简单的文本查询程序。
我们的程序将允许用户在给定的文件中搜索可能出现的单词。
查询的结果将是单词出现的次数和该单词出现的行列表。
如果一个单词在同一行中出现多次,我们将只显示该行一次。行将按升序显示。
例子:
在给定输入文件中查找element。输出:
element occurs 112 times (line 36) A set element contains only a key; (line 158) operator creates a new element (line 160) Regardless of whether the element (line 168) When we fetch an element from a map, we (line 214) If the element is not found, find returns ......
实现:
-
功能:1)按行读入,记录单词出现的行号。2)输出的时候,能够获取行号对应的行,以升序保存结果。
-
具体:1)vector<string>按行保存输入文件,使用下标可以按行号找到对应行的句子。2)istringstream处理字符串,将输入文件分行。3)set<int>保存单词出现的行号结果。4)map<string,set<int>>保存每个文件中每个单词对应的结果。
-
数据结构:1)TextQuery类:处理输入文件并查询。2)QueryResult类:结果,输出结果。
-
细节:QueryResult类用于表示查询的结果。这些数据存储在TextQuery类型的对象中。如何访问?1)拷贝;2)智能指针。
-
使用智能指针可以避免QueryResult指向的TextQuery的data在TextQuery被销毁后无法访问的情况。(只要智能指针的reference count大于0,指针指向的对象即使在指针被销毁后也不会被释放。)
TextQueries Project Pro
功能:
-
单词查询。查找与给定字符串匹配的所有行:
Executing Query for: Daddy Daddy occurs 3 times (line 2) Her Daddy says when the wind blows (line 7) "Daddy, shush, there is no such thing," (line 10) Shyly, she asks, "I mean, Daddy, is there?"
-
非查询。使用~操作符,产生与查询不匹配的行:
Executing Query for: ~(Alice) ~(Alice) occurs 9 times (line 2) Her Daddy says when the wind blows (line 3) through her hair, it looks almost alive, (line 4) like a fiery bird in flight.
-
或查询。使用 | 操作符返回匹配两个查询中的任意一个的行:
Executing Query for: (hair | Alice) (hair | Alice) occurs 2 times (line 1) Alice Emma has long flowing red hair. (line 3) through her hair, it looks almost alive,
-
与查询。使用 & 操作符的查询返回匹配两个查询的行:
Executing query for: (hair & Alice) (hair & Alice) occurs 1 time (line 1) Alice Emma has long flowing red hair.
-
任意操作符的结合。
Executing Query for: ((fiery & bird) | wind) ((fiery & bird) | wind) occurs 3 times (line 2) Her Daddy says when the wind blows (line 4) like a fiery bird in flight. (line 5) A beautiful fiery bird, he tells her,
具体:
-
eval(),它接受一个TextQuery对象并返回一个QueryResult。eval函数将使用给定的TextQuery对象来查找查询的匹配行。
-
rep(),它返回底层查询的字符串表示形式。该函数将被eval()使用来创建一个表示匹配的QueryResult,输出操作符将使用该函数打印查询表达式。
实现:
-
Query_base:抽象基类。包含eval()和rep()两个纯虚函数。
-
WordQuery和NotQuery:直接从Query_base得到的派生类。
-
BinaryQuery:抽象基类。 表示用两个操作数的查询。
-
AndQuery和OrQuery:继承BinaryQuery。
细节:
用户代码不会直接使用继承的类。需要一个和用户交互的接口类Query(会隐藏类继承结构)。
-
Query类存储一个指向Query_base的指针。该指针将被绑定到派生自Query_base的类对象上。
-
Query提供Query_base相同的操作:eval() 计算关联的查询,和rep()生成查询的字符串版本。 它还将定义一个重载输出操作符来显示关联的查询。
-
用户只能通过对Query对象的操作间接地创建和操作Query_base对象。
-
在Query对象上定义三个重载操作符,以及一个接受字符串的Query构造函数。这些函数都将动态分配一个派生自Query_base的类型的新对象。
1)& 操作符将生成一个绑定到一个新的AndQuery的Query。
2)| 操作符将生成一个绑定到一个新的OrQuery的Query。
3)~ 操作符将生成一个绑定到新的NotQuery的Query。
4)Query构造函数接受一个字符串将生成一个新的WordQuery。
将查询表示为C++表达式
((fiery & bird) | wind) :
Query q = Query("fiery") & Query("bird") | Query("wind");
操作:
-
类的使用者
-
类的实现者
Query Program Interface Classes and Operations TextQuery: Class that reads a given file and builds a lookup map. This class has a query operation that takes a string argument and returns a QueryResult representing the lines. QueryResult: Class that holds the results of a query operation. Query: Interface class that points to an object of a type derived from Query_base. Query q(s): Binds the Query q to a new wordQuery holding the string s. q1 & q2: Returns a Query bound to a new AndQuery object holding q1 and q2. q1 | q2: Returns a Query bound to a new OrQuery object holding a1 and q2. ~q: Returns a Query bound to a new NotQuery object holding a. Query Program Implementation Classes Query_base: Abstract base class for the query classes: wordQuery: Class derived from Query_base that looks for a given word. NotQuery: Class derived from Query_base that represents the set of lines in which its Query operand does not appear. BinaryQuery: Abstract base class derived from Query_base that represents queries with two Query operands. orQuery: Class derived from Binaryouery that returns the union of the linenumbers in which its two operands appear. AndQuery: Class derived from BinaryQuery that returns the intersection of the linenumbers in which its two operands appear.