练习12.27
见后面总体程序
练习12.28
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <string> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <cstdlib> 9 using std::cin; 10 using std::cerr; 11 using std::cout; 12 using std::endl; 13 using std::ostream; 14 using std::ifstream; 15 using std::string; 16 using std::vector; 17 using std::map; 18 using std::set; 19 using std::istringstream; 20 21 using line_no = vector<string>::size_type; 22 vector<string> file; //文件每行内容 23 map<string, set<line_no>> wm; //单词到行号set的映射 24 25 string make_plural(size_t ctr, const string &word, const string &ending) 26 { 27 return (ctr > 1)? word + ending : word; 28 } 29 30 string cleanup_str(const string &word) 31 { 32 string ret; 33 for (auto it = word.begin(); it != word.end(); ++it) { 34 if (!ispunct(*it)) 35 ret += tolower(*it); 36 } 37 return ret; 38 } 39 40 void input_text(ifstream &is) 41 { 42 string text; 43 while (getline(is, text)) { //对文件中每一行 44 file.push_back(text); //保存此行文本 45 int n = file.size() - 1; //当前行号 46 istringstream line(text); //将文本分解为单词 47 string word; 48 while (line>>word) { 49 // 将当前行号插入到其行号set中 50 // 如果单词不在wm中,以之为下标在wm中添加一项 51 wm[cleanup_str(word)].insert(n); 52 } 53 } 54 } 55 56 ostream &query_and_print(const string &sought, ostream &os) 57 { 58 // 使用find而不是下标运算符来查找单词,避免将单词添加到wm中 59 auto loc = wm.find(sought); 60 if (loc == wm.end()) { //未找到 61 os<<sought<<" occurs 0 times"<<endl; 62 } 63 else { 64 auto lines = loc->second; //行号set 65 os<<sought<<" occurs "<<lines.size()<<" times"<<endl; 66 for (auto num : lines) //打印单词出现的每一行 67 os<<"\t(No "<< num+1<<"lines) "<<*(file.begin()+num)<<endl; 68 } 69 return os; 70 } 71 72 void runQueries(ifstream &infile) 73 { 74 // infile是一个ifstream,指向我们要查询的文件 75 input_text(infile); //读入文本并建立查询map 76 // 与用户交互:提示用户输入要查询的单词,完成查询并打印结果 77 while (true) { 78 cout<<"enter word to look for or q to quit: "; 79 string s; 80 // 若遇到文件结尾或用户输入了q时循环终止 81 if (!(cin>>s) || s == "q") break; 82 // 指向查询并打印结果 83 query_and_print(s, cout)<<endl; 84 } 85 } 86 87 // 程序接受唯一的命令行参数,表示文本文件名 88 int main(int argc, char **argv) 89 { 90 // 打开要查询的文件 91 ifstream infile; 92 // 打开文件失败,程序异常退出 93 if (argc < 2|| !(infile.open(argv[1]), infile)) { 94 cerr<<"No input file!"<<endl; 95 return EXIT_FAILURE; 96 } 97 runQueries(infile); 98 return 0; 99 }
练习12.29
1 do { 2 cout<<"enter word to look for ,or q to quit: "; 3 string s; 4 if (!(cin>>s) || s == "q") break; 5 query_and_print(s, cout)<<endl; 6 } while (true);
第一种,观感更好