编写一个程序,允许在给定文件中查询一个单词,查询结果是单词在文件中出现的次数以及所在行的列表.要求编写两个类来管理数据.Textquery类用来读取数据.QueryResult类用来生成结果并保存.
#include "iostream"
#include "fstream"
#include "sstream"
#include "string"
#include "vector"
#include "algorithm"
#include "memory"
#include "map"
#include "set"
using namespace std;
using VT = vector<string>;
using Wordsmap = map<string, set<int>>;
class QueryResult;
class Textquery
{
public:
Textquery(string filename);
QueryResult query(string word)const;
private:
shared_ptr<VT> text;
shared_ptr<Wordsmap> record;
};
Textquery::Textquery(string filename)
{
text = make_shared<VT>();
record = make_shared<Wordsmap>();
ifstream in_file(filename);
size_t count = 0;
if (in_file)
{
string line, words;
while (getline(in_file, line))
{
++count;
(*text).push_back(line);
istringstream stringline(line);
while (stringline >> words)
{
words.erase(remove_if(words.begin(), words.end(), ispunct),words.end());
(*record)[words].insert(count);
}
}
}
}
class QueryResult
{
friend ostream& print(ostream&, QueryResult);
public:
QueryResult(string word,shared_ptr<VT>text,shared_ptr<Wordsmap>record);
private:
string words;
size_t count;
shared_ptr<VT> output;
vector<int> lines;
};
QueryResult::QueryResult(string word, shared_ptr<VT>text, shared_ptr<Wordsmap>record)
{
words = word;
count = (*record)[word].size();
lines.assign((*record)[word].begin(), (*record)[word].end());
output = text;
}
QueryResult Textquery::query(string word)const
{
return QueryResult(word, text, record);
}
ostream& print(ostream& os, QueryResult q)
{
cout << "\n" << q.words << " occurs " << q.count << " times \n";
size_t index = 0;
for (auto &it : q.lines)
{
cout << "(line " << it << ") ";
cout << (*(q.output))[it-1] << endl;
}
return os;
}
int main()
{
Textquery tq("Text.txt");
while (true)
{
cout << "enter word to look for,or q to end:";
string s;
if (cin >> s&&s != "q")
print(cout, tq.query(s)) << endl;
else
break;
}
return 0;
}
改进版本:用StrBlob类保存输入文本,用map<string,set<size_t>>
保存行号.为QueryResult增加begin(),end()两个成员返回查询单词所指向的行号set的位置.增加get_file返回一个指向输入文件的shared_ptr;
#include "iostream"
#include "fstream"
#include "sstream"
#include "string"
#include "vector"
#include "algorithm"
#include "memory"
#include "StrBlob.h"
#include "map"
#include "set"
using namespace std;
using VT = vector<string>;
using Wordsmap = map<string, shared_ptr<set<size_t>>>;
class QueryResult;
class Textquery
{
public:
Textquery(string filename);
QueryResult query(string word)const;
private:
shared_ptr<StrBlob> text;
Wordsmap record;
};
Textquery::Textquery(string filename) :text(new StrBlob)
{
ifstream in_file(filename);
size_t count = 0;
if (in_file)
{
string line, words;
while (getline(in_file, line))
{
++count;
text->push_back(line);
istringstream stringline(line);
while (stringline >> words)
{
words.erase(remove_if(words.begin(), words.end(), ispunct),words.end());
auto &lines = record[words];
if (!lines)
lines.reset(new set<size_t>);
lines->insert(count);
}
}
}
}
class QueryResult
{
friend ostream& print(ostream&, QueryResult);
public:
using ResultIter = set<size_t>::iterator;
QueryResult(string, shared_ptr<StrBlob>, shared_ptr<set<size_t>>);
ResultIter begin() const { return lines->begin(); };
ResultIter end() const { return lines->end(); };
shared_ptr<StrBlob> get_file()const { return output; };
private:
string words;
size_t count;
shared_ptr<StrBlob> output;
shared_ptr<set<size_t>> lines;
};
QueryResult::QueryResult(string word, shared_ptr<StrBlob> text, shared_ptr<set<size_t>> line)
{
words = word;
count = line->size();
lines = line;
output = text;
}
QueryResult Textquery::query(string word)const
{
static shared_ptr<set<size_t>> nodata(new set<size_t>);
auto loc = record.find(word);
if (loc != record.end())
return QueryResult(word, text, loc->second);
else
return QueryResult(word, text, nodata);
}
ostream& print(ostream& os, QueryResult q)
{
cout << "\n" << q.words << " occurs " << q.count << " times \n";
size_t index = 0;
for (auto &it : *q.lines)
{
StrBlobPtr p(*q.output, it-1);
cout << "(line " << it << ") ";
cout << p.deref() << endl;
}
return os;
}
int main()
{
Textquery tq("Text.txt");
auto it = tq.query("hello").begin();
cout << *(++it) << endl;
auto file = tq.query("hello").get_file();
for (auto that = file->begin(); that != file->end(); that.incr())
cout << that.deref() << endl;
return 0;
}