C++使用標準庫--文本查詢程序

題目:在給定文件中查詢單詞。查詢結果是單詞在文件中出現的次數及所在行的列表。如果一個單詞在一行中多次出現,此行只顯示一次,行會按照升序輸出。

效果如下:


在此程序的實現中使用到的標準庫內容包括:

(1)ifstream:用來綁定並打開指定的文本。

(2)vector<string>:用來保存整個文本,每行保存爲vector中的元素。

(3)istringstream:用來將每行分解爲單詞。

(4)multiset:用來保存每個單詞出現的行號,保證了行號按升序排列;一個單詞在某行中出現多次,行號會重複保存;

(5)set:用來將multiset中的重複去除,用於一個單詞在某行中出現多次,只顯示一次;

(6)map:將單詞和它出現的行號的multiset關聯起來。

(7)shared_ptr:用於在類之間進行數據共享;


設計思想:

1.當我們設計一個類時,在真正實現成員之前先編寫程序使用這個類,是一種非常有用的方法。通過這種方法,可以看到類是否具有我們所需要的操作。

2.在類的設計過程中,最重要的就是接口的設計,也就是頭文件的設計。


注意的問題:

1.IO對象無拷貝或賦值,需要以引用的方式傳遞參數和返回流。

2.auto& lines = wm[word];這裏也需要是按引用傳遞,否則會發生拷貝,不能操作map中的set,結果爲空。


源代碼與C++Primer(第5版)第十二章給出的稍有改動,我認爲書中講的統計單詞出現次數的方法不合理。



1.main.cpp

#include "TxtQuery.h"
#include "queryResult.h"
#include "iostream"

void runQueries(std::ifstream& infile)
{
	TxtQuery wordQuery(infile);
	while (true)
	{
		std::cout<< "enter word to look for, or q to quit:";
		std::string word;
		if (!(std::cin >> word) || word == "q") break;
		print(std::cout, wordQuery.query(word));
	}
}

int main()
{
	std::ifstream infile("1.txt");
	runQueries(infile);
}


2.TxtQuery.h
#pragma once
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <set>
#include <fstream>
#include "queryResult.h"


class TxtQuery
{
public:
	TxtQuery();
	~TxtQuery();
	TxtQuery(std::ifstream& in);
	queryResult query(const std::string& word);
private:
	std::shared_ptr<std::vector<std::string>> file;
	std::map<std::string, std::shared_ptr<std::multiset<int>>> wm;

};


3.TxtQuery.cpp

#include "TxtQuery.h"
#include <sstream>

TxtQuery::TxtQuery()
{
}


TxtQuery::~TxtQuery()
{
}

TxtQuery::TxtQuery(std::ifstream& in) :file(new std::vector<std::string>) 
{
	std::string text;
	while (std::getline(in, text))
	{
		file->push_back(text);
		int n = file->size();
		std::istringstream line(text);
		std::string word;
		while (line >> word)
		{
			auto& lines = wm[word];
			if (!lines)
			{
				lines.reset(new std::multiset<int>);
			}
			lines->insert(n);
		}
	}
}

queryResult TxtQuery::query(const std::string& word)
{
	static std::shared_ptr<std::multiset<int>> nodata(new std::multiset<int>);
	auto loc = wm.find(word);
	if(loc == wm.end())
	{ 
		return queryResult(word, nodata, file);
	}
	else
	{
		return queryResult(word, loc->second, file);
	}
}

4、queryResult.h

#pragma once
#include <string>
#include <memory>
#include <set>
#include <vector>
class queryResult
{
public:
	queryResult();
	~queryResult();
	queryResult(const std::string sought, std::shared_ptr<std::multiset<int>> lines, std::shared_ptr<std::vector<std::string>> file)	:
		sought(sought)
		,lines(lines)
		,file(file)	{}
	friend std::ostream& print(std::ostream&, const queryResult&);
private:
	std::string sought;
	std::shared_ptr<std::multiset<int>> lines;
	std::shared_ptr<std::vector<std::string>> file;
};


5、queryResult.cpp
#include "queryResult.h"
#include <iostream>

queryResult::queryResult()
{
}

queryResult::~queryResult()
{
}

std::ostream& print(std::ostream& os, const queryResult& qr)
{
	os << qr.sought << " occurs " << qr.lines->size() << " " << "times" << std::endl;
	
	//用multiset初始化set,重複的內容自動去除
	std::set<int> single(std::begin(*qr.lines), end(*qr.lines));
	for (auto num : single) {
		os << "\t(line " << num << ")" << *(qr.file->begin() + num - 1) << std::endl;
	}
	std::cout << std::endl;
	return os;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章