C++标准库练习:文本查询程序

文章目录

  • 1.前言
  • 2.测试文件
  • 3.运行结果
  • 4.示例代码
  • 5.参考资料

1.前言

C++ primer 5e 中12.3章节示例了一个使用标准库的例子:文本查询程序,其中查询的字符串是作为word(单词)方式进行搜索的,其中使用了sstream库中的istringstream标准库来对一行内容进行单词分割判断。

这里改造了下,以以下场景进行示例练习使用标准库,
匹配方式:文本行只需包含 字符串就行,不用空白字符隔开的单词方式;
搜索方式:搜索指定字符串时,第一次搜索才进行实际的查找判断,并将结果集保存起来;如果后续查找,则直接从上一次保存的结果集合中给出结果;

2.测试文件

test.txt文件内容:

today is a good day
the girl is so beautiful
It was a beautiful morning. 
aloha
hehe
how beautiful
beautiful view

3.运行结果

fs.good():  1
fs.rdstate():  0
 getline parse start
 read line 1:today is a good day
 read line 2:the girl is so beautiful
 read line 3:It was a beautiful morning.
 read line 4:aloha
 read line 5:hehe
 read line 6:how beautiful
 read line 7:beautiful view
 getline parse end
enter word to look for,or q to quit :beautiful
 [search] begin a new find action->
 [search] end
beautiful occurs 4 times
        (line 2 )the girl is so beautiful
        (line 3 )It was a beautiful morning.
        (line 6 )how beautiful
        (line 7 )beautiful view

enter word to look for,or q to quit :beautiful
 [find] you have do find action before,last find result:
beautiful occurs 4 times
        (line 2 )the girl is so beautiful
        (line 3 )It was a beautiful morning.
        (line 6 )how beautiful
        (line 7 )beautiful view

enter word to look for,or q to quit :hehe
 [search] begin a new find action->
 [search] end
hehe occurs 1 times
        (line 5 )hehe

enter word to look for,or q to quit :he
 [search] begin a new find action->
 [search] end
he occurs 2 times
        (line 2 )the girl is so beautiful
        (line 5 )hehe

4.示例代码

#include    
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
using line_no = vector<string>::size_type;
class QueryResult;
class TextQuery {
public:
	TextQuery(ifstream&  ifs);
	QueryResult  find(const string&)  ;
private:
	ifstream& fs;
	shared_ptr<vector<string>> file; 
	map<string, shared_ptr<set<line_no>>>wm;
};

TextQuery::TextQuery(ifstream& ifs) :fs(ifs), file(new vector<string>)
{
	
	string text;
	//getline 需 #include  
	int count = 0;
	cout << " getline parse start"  << endl;
	while (getline (fs, text)) {
		cout << " read line " << (++count) <<":"<< text<< endl;
		file->push_back(text); 
	}
	cout << " getline parse end"  << endl;
 
}
class QueryResult {
	friend ostream& print(ostream&, const QueryResult&);
public:
	QueryResult(string s, shared_ptr<set<line_no>>p, shared_ptr<vector<string>>f) 
		:sought(s), lines(p), file(f){}
private:
	string sought;
	shared_ptr<set<line_no>>lines;
	shared_ptr<vector<string>>file;
};
 

QueryResult TextQuery::find(const string & sought)  
{	 

	auto loc = wm.find(sought);
	if (loc != wm.end())
	{
		cout << " [find] you have do find action before,last find result:" << endl;
		return  QueryResult(sought, loc->second, file);
	}
	string text;
	//getline 需 #include 
	cout << " [search] begin a new find action->" << endl;
	shared_ptr<set<line_no>> lines;
	lines.reset(new set<line_no>); 
	
	int linenum = 0;
	for (string& text : *file)
	{
		if (text.find(sought) != string::npos)
		{
			//cout << "[find]find "<
			lines->insert(linenum);
		}
		linenum++;
	} 
		/*
	for (line_no num = 0 ;num <(*file).size();num++)
	{
		if ((*file)[num].find(sought) != string::npos)
		{
			//cout << "[find]find "<insert(num);
		} 
	}*/
	cout << " [search] end" << endl;  
	wm.insert({ sought,lines });
	return QueryResult(sought, lines, file); 
}
ostream&  print(ostream& os, const QueryResult &qr)
{
	os << qr.sought << " occurs " << qr.lines->size() <<  " times" << endl;
	for (auto num : *qr.lines)
		os << "\t(line " << num + 1 << " )" << *(qr.file->begin() + num) << endl;
	return os;
}
void runQueryies(ifstream & fs)
{
	TextQuery tq(fs);
	while (true) {
		cout << "enter word to look for,or q to quit :";
		string s;
		if (!(cin >> s) || s == "q") break;
		print(cout, tq.find(s)) << endl;
	}
}
int main(int argc,char** argv)
{ 
	string  filename("K:\\temp\\test.txt");  
	//string  filename(argv[0]);
	ifstream fs(filename);
	cout << "fs.good():  " << fs.good() << endl;
	cout << "fs.rdstate():  " << fs.rdstate() << endl;
	//cout << "fs.eof(): " << fs.eof() << endl;
	//cout << "fs.fail():  " << fs.fail() << endl;
	//cout << "fs.bad():  " << fs.bad() << endl;
	/*enum _Iostate
		{	// constants for stream states
		_Statmask = 0x17};

	static constexpr _Iostate goodbit = (_Iostate)0x0;
	static constexpr _Iostate eofbit = (_Iostate)0x1;
	static constexpr _Iostate failbit = (_Iostate)0x2;
	static constexpr _Iostate badbit = (_Iostate)0x4;
	*/
	if (!fs.good())
	{
		cout << "open file fail,please check whether the file is exist:" << filename << endl;
		return 0;
	}
	runQueryies(fs);
}
 

5.参考资料

《C++ primer》中文版 第5版,[美]stanley B.Lippman 等著,王刚 等译,电子工业出版社

你可能感兴趣的:(C++标准库)