程序的编写/数据结构和操作/容器的应用/查询程序

容器的综合应用:文本查询程序

该程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。

查询的结果是该单词出现的次数,并列出每次出现的行。如果某单词在同一行多次出现,程序将只显示该行一次。行号按升序显示。

 

设计程序的一个良好习惯是首先将程序所涉及的操作列出来。

明确需要提供的操作有助于建立需要的数据结构和实现这些行为。

从需求出发,我们的程序需要支持如下任务:

1),它必须允许用户指明要处理的文件名字。程序将储存该文件的内容,以便输出每个但系所在的原始行。

2),它必须将每一行分解为各个单词,并记录每个单词所在的所有行。在输出行号时,应保证以升序输出,并且不重复。

3),对特定单词的查询将返回出现该单词的所有行的行号

4),输出某单词所在的行文本时,程序必须能根据给定的行号从输入文件中获取相应的行。

//所谓类,无非数据,和 函数

//程序也是如此。

1数据结构

用一个简单的类实现这个程序,配合使用几种容器,可以满足上述要求

1),使用一个vector<string>类型的对象储存整个输入文件的副本。

输入文件的每一行是该vector对象的一个元素。因而,在希望输出某一行时,只需以行号为下标获取该行所在的元素即可。

2),将每个单词所在的行号存储在一个set容器对象中。使用set就可以确保每行只有一个条目,而且行号将自动按升序排列。

3),使用一个map容器将每个单词与一个set容器对象关联起来,该set容器对象记录此单词所在的行号。

 终上所述,需要定义的类将有两个数据成员:储存输入文件的vector 对象,以及一个map容器对象,该对象关联每个输入的单词以及记录该单词所在行号的set容器对象。 

2操作

对于类还要求有良好的接口

一个重要的设计策略首先要确定:查询函数需返回存储一组行号的set对象。这个返回类型应该如何设计?

查询的过程相当简单:使用下标访问map对象获取关联的set对象即可。唯一的问题是如何返回所找到的set对象。

安全的设计方案是返回该set对象的副本。但这就意味着要复制set中的每一个元素。

如果处理的是一个相当庞大的文件,则复制set对象的代价会非常昂贵。

其他可行的方法包括:返回一个pair对象,存储一对指向set中元素的迭代器;或者返回set对象的const引用。

 

第一,三,四任务是使用这个类的程序员将执行的动作。第二个任务则是类的内部任务。

将这四个任务映射为类的成员函数,则类的接口需提供下列三个public函数。

——Read_file成员函数,其形参为一个ifstream&类型对象。 该函数每次从文件中读入一行,并将它保存在vector容器中。输入完毕后,read_file将创建关联每个单词及其所在行的map容器。

——Run_query 成员函数,其形参为一个string类型对象,返回一个set对象,该set对象包含出现该string对象的所有行的行号。

——Text_line成员函数,其形参为一个行号,返回输入文本中该行对应的文本行。

无论run_query还是text_line都不会修改调用此函数的对象,所以,将这两个操作定义为const成员函数。

 

为实现read_file功能,还需定义两个private函数来读取输入文本和创建map容器:

——store_file函数读入文件,并将文件内容存储在vector 容器中。

——build_map函数将每一行分解为各个单词,创建map容器对象,同时记录每个单词出现的行号

 

  #include <vector>
  #include <map>
  #include <fstream>
  #include <set>
 
class TextQuery
{
public:
    //typedef to make declarations easier
    typedef std::vector<std::string>::size_type line_no;
    /*interface:
        read_file builds internal date structures for the given file
        run_query finds the given word and returns set of lines on which it appears
        text_line returns a requeted line from the input line    
    */ 
    void read_file(std::ifstream &is)
    { 
        store_file(is); build_map(); 
    }
    std::set< line_no > run_query(const std::string&) const;
    std::string text_line(line_no) const;
private:
    //utility functions used by read_line
    void store_file(std::ifstream&);    //store input file
    void build_map();                    //associated each word with a set of line numbers
    //remember the whole input file
    std::vector<std::string> lines_of_text;
    //map word to set of the lines on which it occures
    std::map< std::string, std::set< line_no >  > word_map;
 } ;

 10.6 p325  C++primer

原文地址:https://www.cnblogs.com/aprilapril/p/2971502.html