C++面向对象编程实例——文本查询程序

题目来源:C++ Primer 10.6题目。

文本查询程序,读取一段文本输入单词,获得该单词在文本中的行号,并输出该行的内容(若该单词在一行出现多次,只输出一次)

TextQuery.h

#ifndef TEXTQUERY_H
#define TEXTQUERY_H

#include<string>
#include<vector>
#include<map>
#include<cctype>
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;

class TextQuery{
public:
	//类型别名
	typedef vector<string>::size_type line_no;
	typedef string::size_type str_size;
	
	//接口
	//read_file建立给定文件的内部数据结构
	void 
	read_file(ifstream &is){
		store_file(is);
		build_map();
	}
	
	//查询给定单词并返回该单词所在行的行号集合
	vector<line_no>
	run_query(const string&)const;
	
	//返回输入文件中指定行号对应的行
	string
	text_line(line_no) const;
	
private:
	//保存输入文件
	void store_file(ifstream&);
	
	//将每个单词与一个行号集合想关联
	void build_map();
	
	//保存输入文件
	vector<string> lines_of_text;

	//将单词与出现该单词行的行号集合相关联
	map<string,vector<line_no> > word_map;
	
	//去掉标点并将字母变成小写
	static std::string
	cleanup_str(const std::string&);
};
#endif







TextQuery.cpp

#include "TextQuery.h"
#include <sstream>
#include<stdexcept>
string 
TextQuery::text_line(line_no line)const{
	if(line<lines_of_text.size())
		return lines_of_text[line];
	throw out_of_range("line number out of range");	
}

//读入文件,将每行存储为lines_of_text的一个元素
void
TextQuery::store_file(ifstream& is){
	string textline;
	while(getline(is,textline))
		lines_of_text.push_back(textline);
}

//在输入vector中找以空白为间隔的单词,将单词以及出现该单词的行的行号一起放入word_map
void
TextQuery::build_map(){
	//处理输入vector中的每一行
	for(line_no line_num=0;line_num!=lines_of_text.size();++line_num){
		//一次读一个单词
		istringstream line(lines_of_text[line_num]);
		string word;
		while(line>>word){
			//去掉标点
			word=cleanup_str(word);
			//将行号加入到vector容器中
			if(word_map.count(word)==0)
				word_map[word].push_back(line_num);
			else {
				if(line_num!=word_map[word].back())
					word_map[word].push_back(line_num);		
			}
		}
	}
}

vector<TextQuery::line_no>
TextQuery::run_query(const string &query_word)const{
	map<string,vector<line_no> >::const_iterator
		loc=word_map.find(query_word);
	if(loc==word_map.end())
		return vector<line_no>();//返回个空的vector对象
	else
		return loc->second;
}

//去掉标点并将字母变成小写
string
TextQuery::cleanup_str(const string &word){
	string ret;
	for(string::const_iterator it=word.begin();it!=word.end();++it){
		if(!ispunct(*it))
			ret+=tolower(*it);
	}
	return ret;
}

主函数main.cpp

#include "TextQuery.h"
#include <stdlib.h>

string
make_plural(size_t ctr,const string &word,const string &ending){
	return (ctr==1)?word:word+ending;
}

//打开输入文件流in并绑定到给定的文件
ifstream& 
open_file(ifstream &in,const string &file){
	in.close();
	in.clear();
	in.open(file.c_str());
	return in;
}

void
print_results(const vector<TextQuery::line_no>& locs,
	const string& sought,const TextQuery& file){

	typedef vector<TextQuery::line_no> line_nums;
	line_nums::size_type size=locs.size();
	cout<<"\n"<<sought<<" occurs "<<size<<" "<<make_plural(size,"time","s")<<endl;

	//输出出现该单词的每一行
	line_nums::const_iterator it=locs.begin();
	for(; it!=locs.end(); ++it){
		cout<<"\t(line "<<(*it)+1<<")"<<file.text_line(*it)<<endl;
	}
}


int main(int argc,char** argv){
	//open the file from which user will query words
	ifstream infile;
	if(argc!=2||!open_file(infile,argv[1])){
		cerr<<"No input file!"<<endl;
		return EXIT_FAILURE;
	}
	
	TextQuery tq;
	tq.read_file(infile);//建立map容器,逐行保存输入流中文件内容
	
	//循环接受用户的查询要求并输出结果
	while(true){
		cout<<"enter word to look for, or q to quit: ";
		string s ;
		cin>>s;
		string ret;
		for(string::const_iterator it=s.begin();it!=s.end();++it){
			ret+=tolower(*it);
		}
		s=ret;

		//如果用户输入文件结束符或字符‘q’及'Q',则结束循环
		if(!cin||s=="q"||s=="Q") break;
		
		//获取吹安所查询单词所有行的行号
		vector<TextQuery::line_no> locs=tq.run_query(s);

		//输出出现次数及所有相关文本行
		print_results(locs,s,tq);
	}
	

	return 0;
}


makefile

objects=main.o TextQuery.o 

run:$(objects)
	g++ -o run $(objects)

main.o:TextQuery.o 
TextQuery.o:

.PHONY:clean

clean:
	rm run $(objects)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值