正在看《C++ Primer》(4th),第325頁給出了一個TextQuery例子,很好地總結了STL容器的用法,但是書上沒有給出連續完整的代碼,我實驗過後把程式記錄下來,便於以後尋找回憶。該程式的功能是尋找輸入文字檔中某個單詞的出現次數及其行號。
先上TextQuery類的標頭檔TextQuery.h:
#ifndef TEXTQUERY_H_#define TEXTQUERY_H_#include<iostream>#include<fstream> //ifstream 的標頭檔#include<set>#include<string>#include<vector>#include<map>#include <stdlib.h> //EXIT_FALURE 的標頭檔#include<sstream> //istringstream的標頭檔#include<utility> //pairs的標頭檔using namespace std;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;};ifstream &open_file(ifstream &in, const string &file);void print_results(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery &file);
然後是TextQuery.cpp:
#include "TextQuery.h"#include <stdexcept>void TextQuery::store_file(ifstream &is){string textline;while (getline(is, textline))lines_of_text.push_back(textline);}void TextQuery::build_map(){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_map[word].insert(line_num);}}set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const{map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);if (loc == word_map.end())return set<line_no>();elsereturn loc->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 make_plural(size_t ctr, const string &word, const string &ending){return (ctr == 1) ? word : word + ending;}ifstream &open_file(ifstream &in, const string &file){in.close(); // close in case it was already openin.clear(); // clear any existing errors // if the open fails, the stream will be in an invalid statein.open(file.c_str()); // open the file we were givenreturn in; // condition state is good if open succeeded}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 << " "<< 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;}}
最後是main.cpp:
#include "TextQuery.h"using namespace std;int main(int argc, char **argv) {ifstream infile;if (argc < 2 || !open_file(infile, argv[1])) {cerr << "No input file!" << endl;return EXIT_FAILURE;}TextQuery tq;tq.read_file(infile);while (true) {cout << "enter word to look for,or q to quit" << endl;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;}
我是在Ubuntu 13.04下g++編譯測試的:
最後上測試結果: