1. 整体需求
使用标准库实现一个简单的文本查询系统。允许用户在一个给定的文件中查询单词。 查询结果是单词在文件中出现的次数以及所在行的列表。如果一个单词在一行中出现多次,该行也只列出一次,但是出现的次数得统计在内。行序号按照升序输出。
2. 程序需要完成的功能和实现效果
需要完成的功能:
1.从文件按行读入信息,并将单词分离开来。
2.必须提取到每一个单词所出现的行号
3.行号按照升序排列且不重复
4.必须打印给定文本中的文字
5.必须统计出一个单词所出现的所有次数
实现效果:
3. 程序架构设计
<1> 因为要打印文本中所出现的文字,所以就意味着需要保存 ,那么我们选择vector<string>
来保存它,另外行号还可以作为它的下标来提取文字。
<2>使用istringstream
来分离单词 。
<3>对于每一个单词,我们使用一个multiset来保存它在文本中出现的行号 。这就自然保证了升序的特点,至于重复的问题,我们只要在输出时解决一下就行了,反正multiset中只存储了行号,不会有很多重复的数据 。
<4>使用一个map来将每个单词和它所对应的set关联起来,以便提取。
<5> 使用智能指针!! 这是为什么呐?因为QueryResult 要查询到的数据原先全在 TextQuery 中的,如果将其拷贝到 QueryResult 类中,会花费很多的时间,那么我们通过指针来减少这种花费。考虑到两个对象的同步问题(比如在QueryResult 用到TextQuery之前,TextQuery对象已经销毁了),我们通过使用智能指针来解决这种矛盾 。
4.实现代码:
liu
sheng
xi
zui
shuai
哦哦
liu
liu liu liu
lu
liy
bnglbn
bkngbgmn blnblgnb ;ng;f f;gfg; nfnbdn
bbdnbkkbnbnonb
bntlobntol
liu liu
liu
liull
gmrlnrgliu
liu shen xi
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std ;
using line_no = vector <string > ::size_type ;
class DegbugDelete{
public :
DegbugDelete(ostream &s= cerr ):os(s){ }
template <typename T>
void operator ()(T *p) const {
os<< "deleteing shared_ptr " << endl ;
delete p;
}
private :
ostream &os ;
};
class QueryResult{
friend ostream& print(ostream& os , const QueryResult &TT ){
os << TT.sought << " occurs " << TT.lines->size() << " times " << endl ;
if (TT.lines->size() == 0 )
return os ;
auto tag = TT.lines->begin() ;
decltype (tag) temp = tag ;
tag++ ;
while ( temp != TT.lines->end()){
if ( *tag != *temp ){
os << " 行 " <<*temp+1 << " : " << (*TT.file)[*temp] << endl ;
}
temp++ ;
tag++ ;
}
return os ;
}
public :
QueryResult() = default ;
QueryResult(string s ,
shared_ptr <multiset <line_no> > p ,
shared_ptr <vector <string > > f ):sought(s),lines(p),file(f){}
private :
string sought ;
shared_ptr <multiset <line_no> > lines ;
shared_ptr <vector <string > > file ;
};
class TextQuery {
public :
TextQuery(ifstream &infile): file ( new vector <string > ,DegbugDelete() )
{
string text ,word ;
while ( getline(infile,text )){
file->push_back(text) ;
int n = file->size() - 1 ;
istringstream line(text) ;
while ( line >> word ){
auto &lines = wm[word] ;
if ( ! lines )
lines.reset( new multiset <line_no> ,DegbugDelete() ) ;
lines->insert(n) ;
}
}
}
QueryResult query( const string &temp ) const {
static shared_ptr <multiset <line_no> > nodata(new multiset <line_no> ,DegbugDelete()) ;
auto loc = wm.find(temp);
if ( loc == wm.end() ){
cout << temp << " is not in test.txt file " << endl ;
return QueryResult(temp ,nodata ,file);
}
else
return QueryResult(temp, loc->second,file ) ;
}
private :
shared_ptr < vector <string > > file ;
map <string ,shared_ptr <multiset <line_no> > > wm ;
};
int fun(ifstream &infile){
const TextQuery tq(infile);
string word ;
while (1 ) {
cout << " 请 输 入 你 想 要 查 询 的 单 词 :" ;
cin >> word ;
if (word == "q" )
return 0 ;
print(cout ,tq.query(word)) << endl ;
}
return 0 ;
}
int main(void ){
cout << " 你将在文件:test.txt 中查询你想要查询的单词 \n\n" << endl ;
ifstream infile("test.txt" );
if ( !infile.is_open()){
cout << " 未 成 功 打 开 文 件!!" << endl ;
return -1 ;
}
fun(infile);
infile.close() ;
return 0 ;
}
5.运行结果: