现在的位置: 首页 > 综合 > 正文

c++ primer 中的文本查询示例

2013年10月26日 ⁄ 综合 ⁄ 共 5059字 ⁄ 字号 评论关闭

前言:

有个牛人叫bnu_chenshuo, 发微博说:

回复@TheRealBo: 学生编程练习:把 Unix 的命令行小工具用C/C++实现一遍:wc cat ls cp grep sort uniq nc head tail hexdump。把《C++ Primer》里的文本查询程序弄懂调通。写个大整数的加减乘运算。写个表达式计算器。把 string 和 vector<T>
自己实现一遍。写个太阳系几大星球的运动模拟程序。

好吧,一个一个来做吧。

今天第一个,c++ primer 中的文本查询示例。

该例子位于第10章节。(第15章节也有,引入了面向对象编程)

1.TextQuery.h

/*
 * TextQuery.h
 *
 *  Created on: 2011-8-26
 *      Author: gauss
 */

#ifndef TEXTQUERY_H_
#define TEXTQUERY_H_
#include <string>
#include <set>
#include <map>
#include <vector>
class TextQuery {
public:
	TextQuery();
	virtual ~TextQuery();
	typedef std::vector<std::string>::size_type line_no;
	/* interface:
	 * read_file builds internal data structures for the given file
	 * run_query finds the given word and returns set of lines on which it appears
	 * text_line returns a requested line from the input file
	 */
	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;
	line_no size() const {
		return lines_of_text.size();
	}
	void print_results(const std::set<TextQuery::line_no>&, const std::string&, const TextQuery&);
private:
	// utility functions uesed by read_file
	void store_file(std::ifstream&); // store input file
	void build_map(); // associated each word with a set of line numbers
	// remember the whole input file
	std::vector<std::string> lines_of_text;
	// map word to set of the lines on which it occurs
	std::map<std::string, std::set<line_no> > word_map;
	static std::string cleanup_str(const std::string&);
};
//void print_results(const std::set<TextQuery::line_no>&, const std::string&, const TextQuery&);
#endif /* TEXTQUERY_H_ */

2. TextQuery.cpp

/*
 * TextQuery.cpp
 *
 *  Created on: 2011-8-26
 *      Author: gauss
 */
#include "TextQuery.h"
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <fstream>
#include <stdexcept>
#include <cctype>
using namespace std;
TextQuery::TextQuery() {
	// TODO Auto-generated constructor stub

}

TextQuery::~TextQuery() {
	// TODO Auto-generated destructor stub
}
void TextQuery::store_file(ifstream &is) {
	// read input file: store each line as element in lines_of_text
	string textline;
	while (getline(is, textline))
		lines_of_text.push_back(textline);
}

void TextQuery::build_map() {
	// process each line from the input vector
	for (line_no n = 0; n != lines_of_text.size(); ++n) {
		// we'll use line to read the text a word at a time
		istringstream line(lines_of_text[n]);
		string word;
		while (line >> word)
			// add this number to the set;
			// subscript will add word to the map if it's not already there
			word_map[cleanup_str(word)].insert(n);
	}
}

set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const {
	// note: must use find and not subscript the map directly
	// to avoid adding words to word_map!
	map<string, set<line_no> >::const_iterator it = word_map.find(
			cleanup_str(query_word));
	if (it == word_map.end())
		return set<line_no> (); // not found, return empty set
	else
		return it->second;
}

string TextQuery::text_line(line_no line) const {
	if (line < lines_of_text.size())
		return lines_of_text[line];
	throw std::out_of_range("line number out of range");
}

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;
}

//////////////////////////////////////////////////////////////////////////
void TextQuery::print_results(const set<TextQuery::line_no> &locs, const string &sought,
		const TextQuery &file) {
	// if the word was found, then print count and all occurrences
	typedef set<TextQuery::line_no> line_nums;
	line_nums::size_type size = locs.size();
	cout << "Executed Query for: " << sought << endl;
	cout << "match occurs " << size << " " << (size > 1 ? "times" : "time")
			<< endl;

	// print each line in which the word appeared
	line_nums::const_iterator it = locs.begin();
	for (; it != locs.end(); ++it) {
		cout << "(line "
		// don't confound user with text lines starting at 0
				<< (*it) + 1 << ") " << file.text_line(*it) << endl;
	}
}

主函数:

# include "TextQuery.h"
# include <iostream>
# include <fstream>
# include <string>
using namespace std;
int main(){
	TextQuery tq;
	ifstream fin("data.txt");
	tq.read_file(fin);
	while(true){
		cout << "enter the word to look fo,or q to exit: ";
		string s;
		cin >> s;
		if (s== "q") break;
		set<TextQuery::line_no> locs = tq.run_query(s);
		tq.print_results(locs,s,tq);
	}
}

data.txt摘自一段英文文章:

运行示意图:

enter the word to look fo,or q to exit: hurricane
Executed Query for: hurricane
match occurs 5 times
(line 1) With Hurricane Irene threatening a full-force hit, New York City on Thursday ordered the evacuation of nursing homes and senior centers in low-lying areas and made plans for the possible shutdown of the entire transit system.
(line 11) Mr. Bloomberg said the city was ordering nursing homes in those areas to evacuate residents beginning at 8 a.m. on Friday unless they receive special permission from state and city health officials, among them the city’s health commissioner, Dr. Thomas
A. Farley, who, the mayor noted, was chairman of the community health sciences department at Tulane University when Hurricane Katrina hit New Orleans in 2005.
(line 19) The mayor said 300 street fairs over the weekend “would have to be curtailed” to keep streets clear for hurricane-related transportation — ambulances carrying patients to nursing homes or hospitals on higher ground, buses and city-owned trucks moving
to where they would be ready for duty once the hurricane had swept by.
(line 23) The mayor cautioned that forecasts were not always accurate and that the hurricane, a sprawling storm still far away, could become weaker.
(line 27) That seemed to be the official mantra from South Jersey to coastal Connecticut on Thursday. In East Hampton, N.Y., crews removed sidewalk benches so they would not blow away if Hurric

抱歉!评论已关闭.