C++ Primer Chapter 10 关联容器之容器的综合应用:文本查询程序

//TextQuery.h
#ifndef _TEXTQUERY_H_
#define _TEXTQUERY_H_

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <set>
#include <map>

class TextQuery{
public:
	typedef std::vector<std::string>::size_type line_no;
	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:
	void store_file(std::ifstream&);
	void build_map();
	std::vector<std::string> lines_of_text;
	std::map< std::string, std::set<line_no> > word_map;
};

#endif
//TextQuery.cpp
#include "TextQuery.h"
#include <iostream>
#include <sstream>
#include <utility>
using std::string;
using std::vector;
using std::set;
using std::map;
using std::istringstream;


std::set<TextQuery::line_no> TextQuery::run_query(const std::string &word) const
{
	map< string, set<line_no> >::const_iterator iter = word_map.find(word);
	if (iter != word_map.end())
	{
		return iter->second;
	}
	else
	{
		set<line_no> temp;
		return temp;
		//return set<line_no>();//书上使用这种方法,简明了许多
	}	
}

std::string TextQuery::text_line(line_no linenumber) const
{
	return lines_of_text[linenumber];
}

void TextQuery::store_file(std::ifstream &is)
{
	string line;
	while (getline(is, line))
	{
		lines_of_text.push_back(line);		
	}

}


void TextQuery::build_map()
{
	string word;
	map< string, set<line_no> >::iterator iter;
	for (line_no ix = 0; ix != lines_of_text.size(); ++ix)
	{
		istringstream stream(lines_of_text[ix]);
		//istringstream stream;
		//stream.str(lines_of_text[ix]);//有两种将string转换为istringstream的方法
		while (stream >> word)
		{
			//word_map[word].insert(ix);//书上用了这种写法,只需一句简单明了多了
			iter = word_map.find(word);
			if (iter != word_map.end())
			{
				iter->second.insert(ix);
			}
			else
			{
				set<line_no> lineset;
				lineset.insert(ix);
				word_map.insert(make_pair(word, lineset));
			}
		}
	}
	
}



//test.cpp
#include "TextQuery.h"
#include <iostream>
#include <string>
#include <set>
#include <fstream>
#include <utility>

using std::ifstream;
using std::cerr;
using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::set;
using std::runtime_error;


ifstream& open_file(ifstream& in, const string& file)  
{  
	in.close();  
	in.clear();  
	in.open(file.c_str());  
	return in;  
} 
void print_results(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery& file)
{
	typedef set<TextQuery::line_no> line_nums;
	line_nums::size_type size = locs.size();
	cout << "\n" << sought << " occurs "
			<< size << " "
			<< "times" << endl;
	line_nums::const_iterator iter = locs.begin();
	for ( ; iter != locs.end(); ++iter)
	{
		cout << "\t(line " 
				<< (*iter) + 1 << ") "
				<< file.text_line(*iter) << endl;
	}
}

int main(int argc, char **argv)
{
	/*下面两种文件的读取方式均可。运行程序有两种方法
	方法一:利用cmd命令到命令行窗口,进入到可执行文件所在的目录
	输入xxx.exe yyy.txt
	方法二:利用vs2008属性-调试-命令参数中填写yyy.txt
	然后在工作目录中填写可执行程序所在目录,将yyy.txt也放入此目录中
	要注意的是对于win7系统,文件名后缀是不显示的,所以在命名文件时
	不需要写yyy.txt,这样会出现文件全名变成yyy.txt.txt的情况*/
#if 0
	ifstream infile;
	if (argc < 2 || !open_file(infile, argv[1]))
	{
		cerr << "No input file!" << endl;
		//return EXIT_FAILURE;
	}
	//open_file(infile, argv[1]);
#endif
#if 1
	if (argc != 2)
	{
		throw runtime_error("wrong number of arguments");
	}
	ifstream infile;
	if (!open_file(infile, argv[1]))
	{
		throw runtime_error("no input file");
	}
#endif
	TextQuery tq;
	tq.read_file(infile);
	while (true)
	{
		cout << "enter word to look for, or q to quit: ";
		string s;
		cin >> s;
		if (!cin || s == "q")
		{
			break;
		}
		set<TextQuery::line_no> locs = tq.run_query(s);
		print_results(locs, s, tq);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值