练习11.3
/******************************************************************************
* 编写你自己的单词计数程序。
******************************************************************************/
#include <map>
#include <iostream>
using std::cin;
using std::cout;
using std::map;
using std::string;
int main()
{
map<string, size_t> word_count;
string word;
while (cin >> word)
++word_count[word];
for (auto &w : word_count)
cout << w.first << ": " << w.second << "\n";
return 0;
}
练习11.4
/******************************************************************************
* 扩展你的程序,忽略大小写和标点。例如,“example.”、“example,”和“Example”应该递增相同的
* 计数器。
******************************************************************************/
#include <map>
#include <iostream>
using std::cin;
using std::cout;
using std::map;
using std::string;
int main()
{
map<string, size_t> word_count;
string word;
while (cin >> word)
{
if (ispunct(word[word.size() - 1]))
word.erase(word.end() - 1);
for (auto &c : word)
c = tolower(c);
++word_count[word];
}
for (auto &w : word_count)
cout << w.first << ": " << w.second << "\n";
return 0;
}
}
练习11.7
/******************************************************************************
* 定义一个map,关键字是家庭的姓,值是一个vector,保存家中的孩子(们)的名。编写代码,实现添
* 加新的家庭以及向已有家庭中添加新的孩子。
*****************************************************************************/
#include <map>
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::string;
using std::vector;
int main()
{
map<string, vector<string>> famliy;
string famliy_name, child_name;
size_t child_count;
char c;
bool FLAG = true;
while (true)
{
cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
cin >> c;
if (c == 'A')
{
vector<string> children_name;
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入该家庭中孩子的个数:";
cin >> child_count;
cout << "添加家庭中孩子(们)的名:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name;
children_name.push_back(child_name);
}
famliy[famliy_name] = children_name;
cout << "添加成功!\n";
}
else if (c == 'B')
{
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入新增孩子个数:";
cin >> child_count;
cout << "输入新增孩子(们)的名:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name;
for (auto &f : famliy)
if (f.first == famliy_name)
f.second.push_back(child_name);
}
cout << "添加成功!\n";
}
else if (c == 'C')
{
for (const auto &f : famliy)
{
cout << f.first << endl;
for (const auto &ch : f.second)
cout << ch << "\t";
cout << endl;
}
}
else
break;
}
return 0;
}
练习11.8
/******************************************************************************
* 编写一个程序,在一个vector而不是一个set中保存不重复的单词。使用set的优点是什么?
*****************************************************************************/
#include <vector>
#include <iostream>
#include <algorithm>
using std::cin;
using std::cout;
using std::string;
using std::vector;
int main()
{
vector<string> words;
string word;
while (cin >> word)
{
if (!count(words.begin(), words.end(), word))
words.push_back(word);
}
for (const auto &w : words)
cout << w << "\n";
return 0;
}
练习11.9
/******************************************************************************
* 定义一个map,将单词与一个行号的list关联,list中保存的是单词所出现的行号。
*****************************************************************************/
#include <iostream>
#include <list>
#include <map>
#include <string>
using std::cin;
using std::cout;
using std::list;
using std::map;
using std::string;
int main()
{
map<string, list<unsigned>> wordLineNumber; //存储单词-行号map
string line, word; //存储一行和一个单词
unsigned lineNum = 0; //行号
while (getline(cin, line)) //得到一行
{
bool wordExist = false; //单词是否已在map中
unsigned curpos = 0, prepos = 0; //当前、前一个非字母字符下标
++lineNum;
line += " "; //行数目加一
for (auto it = line.begin(); it != line.end(); ++it) //存储每行中的单词及单词所在行号
if (ispunct(*it) || isspace(*it) || isdigit(*it) || iscntrl(*it)) //以非字母字符分隔为单词
{
curpos = it - line.begin(); //记录当前非字母字符下标
if (curpos - prepos) //两个非字母字符之间要有单词
{
word = line.substr(prepos, curpos - prepos); //提取出单词
for (auto &w : wordLineNumber) //在map中查找单词
if (w.first == word) //如果找到了
{
w.second.push_back(lineNum); //记录行号
wordExist = true; //单词已在map中
break; //退出查找
}
if (!wordExist) //在map中未找到单词
{
list<unsigned> lineNums; //存储行号的列表
lineNums.push_back(lineNum); //将行号存进列表
wordLineNumber[word] = lineNums; //添加新单词及其对应的行号
}
}
prepos = curpos + 1; //记录前一个下标为当前下班
wordExist = false;
}
}
for (const auto &w : wordLineNumber) //打印结果
{
cout << w.first << ": ";
for (const auto &l : w.second)
cout << l << " ";
cout << "\n";
}
return 0;
}
练习11.11
/******************************************************************************
* 不使用decltype重新定义bookst。
*****************************************************************************/
/*** Sales_data.h ***/
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
class Sales_data
{
public:
std::string bookNo;
std::string isbn() const { return bookNo; }
};
#endif
/*** main.c ***/
#include <set>
#include <iostream>
#include "Sales_data.h"
using std::cout;
using std::multiset;
bool comparIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() < rhs.isbn();
}
int main()
{
multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)> bookstore(comparIsbn);
Sales_data book1, book2, book3;
book1.bookNo = "qwrwqwvr2";
book2.bookNo = "DFGNNJEU";
book3.bookNo = "tyiytmy";
bookstore = {book1, book2, book3};
for (const auto &b : bookstore)
cout << b.isbn() << "\n";
return 0;
}
练习11.12
/******************************************************************************
* 编写程序,读入string和int的序列,将每个string和int存入一个pair中,pair保存在一个
* vector中。
*****************************************************************************/
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;
int main()
{
vector<pair<string, int>> vpsi;
pair<string, int> stp;
while (cin >> stp.first >> stp.second)
vpsi.push_back(stp);
for (const auto &p : vpsi)
cout << p.first << "\t" << p.second << "\n";
return 0;
}
练习11.13
/******************************************************************************
* 在上一题的程序中,至少有三种创建pair的方法。编写此函数的三个版本,分别采用不同的方法创建
* pair。解释你认为那种形式最易于编写和理解,为什么?
*****************************************************************************/
/*** v1 ***/
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;
int main()
{
vector<pair<string, int>> vpsi;
pair<string, int> stp("", 0);
while (cin >> stp.first >> stp.second)
vpsi.push_back(stp);
for (const auto &p : vpsi)
cout << p.first << "\t" << p.second << "\n";
return 0;
}
/*** v2 ***/
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;
int main()
{
vector<pair<string, int>> vpsi;
pair<string, int> stp = {"", 0};
while (cin >> stp.first >> stp.second)
vpsi.push_back(stp);
for (const auto &p : vpsi)
cout << p.first << "\t" << p.second << "\n";
return 0;
}
/*** v3 ***/
#include <iostream>
#include <vector>
#include <utility>
using std::cin;
using std::cout;
using std::make_pair;
using std::pair;
using std::string;
using std::vector;
int main()
{
vector<pair<string, int>> vpsi;
pair<string, int> stp = make_pair("", 0); //此处用auto会将字符串识别为C语言型的,导致不能用cin,所以显示定义
while (cin >> stp.first >> stp.second)
vpsi.push_back(stp);
for (const auto &p : vpsi)
cout << p.first << "\t" << p.second << "\n";
return 0;
}
练习11.14
/******************************************************************************
* 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子
* 的名和生日。
*****************************************************************************/
#include <map>
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::pair;
using std::string;
using std::vector;
int main()
{
map<string, vector<pair<string, string>>> famliy;
string famliy_name, child_name, birthday;
size_t child_count;
pair<string, string> child_name_birthday;
char c;
while (true)
{
cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
cin >> c;
if (c == 'A')
{
vector<pair<string, string>> children_name_birthday;
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入该家庭中孩子的个数:";
cin >> child_count;
cout << "添加家庭中孩子(们)的名及其生日:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name >> birthday;
child_name_birthday.first = child_name;
child_name_birthday.second = birthday;
children_name_birthday.push_back(child_name_birthday);
}
famliy[famliy_name] = children_name_birthday;
cout << "添加成功!\n";
}
else if (c == 'B')
{
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入新增孩子个数:";
cin >> child_count;
cout << "输入新增孩子(们)的名及其生日:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name >> birthday;
child_name_birthday.first = child_name;
child_name_birthday.second = birthday;
for (auto &f : famliy)
if (f.first == famliy_name)
f.second.push_back(child_name_birthday);
}
cout << "添加成功!\n";
}
else if (c == 'C')
{
for (const auto &f : famliy)
{
cout << f.first << endl;
for (const auto &ch : f.second)
cout << ch.first << ": " << ch.second << "\t";
cout << endl;
}
}
else
break;
}
return 0;
}
练习11.16
/******************************************************************************
* 使用一个map迭代器编写一个表达式,将一个值赋予一个元素。
*****************************************************************************/
#include <map>
#include <iostream>
using std::cout;
using std::map;
using std::string;
int main()
{
map<string, int> mapsn = {{" ", 0}};
auto mapit = mapsn.begin();
mapit->second = 1;
cout << mapit->second << "\n";
return 0;
}
练习11.19
/******************************************************************************
* 不使用decltype重新定义bookst。
*****************************************************************************/
/*** Sales_data.h ***/
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
class Sales_data
{
public:
std::string bookNo;
std::string isbn() const { return bookNo; }
};
#endif
/*** main.c ***/
#include <set>
#include <iostream>
#include "Sales_data.h"
using std::cout;
using std::multiset;
bool comparIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() < rhs.isbn();
}
int main()
{
multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)> bookstore(comparIsbn);
multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)>::iterator itb = bookstore.begin();
cout << itb->bookNo;
return 0;
}
练习11.20
/******************************************************************************
* 重写11.1节练习(第376页)的单词计数程序,使用insert代替下标操作。你认为那个程序更容易编
* 写和阅读?解释原因。
******************************************************************************/
#include <map>
#include <iostream>
using std::cin;
using std::cout;
using std::map;
using std::string;
int main()
{
map<string, size_t> word_count;
string word;
while (cin >> word)
{
auto ret = word_count.insert({word, 1});
if (!ret.second)
++ret.first->second;
}
for (auto &w : word_count)
cout << w.first << ": " << w.second << "\n";
return 0;
}
练习11.23
/******************************************************************************
* 11.2.1节练习(第378页)中的multimap以孩子的姓为关键字,保存他们的名字的vector,用multimultimap
* 重写此map
*****************************************************************************/
#include <map>
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::multimap;
using std::string;
using std::vector;
int main()
{
multimap<string, vector<string>> famliy;
string famliy_name, child_name;
size_t child_count;
char c;
while (true)
{
cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
cin >> c;
if (c == 'A')
{
vector<string> children_name;
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入该家庭中孩子的个数:";
cin >> child_count;
cout << "添加家庭中孩子(们)的名:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name;
children_name.push_back(child_name);
}
famliy.insert({famliy_name, children_name});
cout << "添加成功!\n";
}
else if (c == 'B')
{
cout << "输入家庭的姓:";
cin >> famliy_name;
cout << "输入新增孩子个数:";
cin >> child_count;
cout << "输入新增孩子(们)的名:\n";
for (size_t i = 0; i != child_count; ++i)
{
cin >> child_name;
for (auto &f : famliy)
if (f.first == famliy_name)
f.second.push_back(child_name);
}
cout << "添加成功!\n";
}
else if (c == 'C')
{
for (const auto &f : famliy)
{
cout << f.first << endl;
for (const auto &ch : f.second)
cout << ch << "\t";
cout << endl;
}
}
else
break;
}
return 0;
}
练习11.26
/******************************************************************************
* 可以用什么类型来对一个map进行下标操作?下标运算符返回的类型是什么?请给出一个具体例子--
* 即--定义一个map,然后写出一个可以用来对map进行下标操作的类型以及下标运算符将会返回的类型。
*****************************************************************************/
#include <map>
#include <iostream>
using std::cout;
using std::map;
int main()
{
map<char, int> nums; //定义一个map
char str = 'q'; //写出一个可以用来对map进行下标操作的类型
map<char, int>::mapped_type mn = ++nums[str]; //下标运算符将会返回的类型
cout << mn;
return 0;
}
练习11.28
/******************************************************************************
* 对于一个string到int的vector的map,定义并初始化一个变量来保存在其上调用find所返回的结
* 果。
*****************************************************************************/
#include <iostream>
#include <vector>
#include <map>
using std::cout;
using std::map;
using std::string;
using std::vector;
int main()
{
map<string, vector<int>> svt = {{"qwer", vector<int>(2, 1)}, {"tyui", vector<int>(4, 3)}};
auto svit = svt.find("tyui");
cout << svit->second[0] << "\n";
return 0;
}
练习11.31
/******************************************************************************
* 编写程序。定义一个作者及其作品的multimap。使用find在multimap中查找一个元素并用erase删
* 除它。确保你的程序在元素不在map中时也能正常运行。
*****************************************************************************/
#include <map>
#include <iostream>
using std::cin;
using std::cout;
using std::multimap;
using std::string;
int main()
{
string find_elem;
multimap<string, string> author_works = {{"qwer", "tyui"}, {"qwer", "opas"}, {"dfgh", "jklz"}, {"dfgh", "xcvb"}};
cout << "输入你要查找的元素:";
cin >> find_elem;
auto ait = author_works.find(find_elem);
if (ait != author_works.end())
{
author_works.erase(ait);
cout << "已成功删除" + find_elem + "元素。\n";
}
else
cout << "元素“" + find_elem + "”不在该multimap中\n";
cout << "现在multimap中的元素为:\n";
for (const auto &aw : author_works)
cout << aw.first + ": " + aw.second + "\n";
return 0;
}
练习11.32
/******************************************************************************
* 使用上一题定义的multimap编写一个程序,按字典序打印作者列表和他们的作品。
*****************************************************************************/
#include <map>
#include <iostream>
using std::cout;
using std::multimap;
using std::string;
int main()
{
multimap<string, string> author_works = {{"qwer", "tyui"}, {"qwer", "opas"}, {"dfgh", "jklz"}, {"dfgh", "xcvb"}};
for (const auto &aw : author_works)
cout << aw.first + ": " + aw.second + "\n";
return 0;
}
练习11.33
/*** exercise11_33.hpp ***/
#include <fstream>
using std::ifstream;
using std::string;
void word_transform(ifstream &map_file, ifstream &input);
/*** exercise11_33.cpp ***/
#include <sstream>
#include <map>
#include <iostream>
#include "exercise11_33.hpp"
using std::cout;
using std::endl;
using std::getline;
using std::istringstream;
using std::map;
using std::runtime_error;
map<string, string> build_map(ifstream &map_file)
{
map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
return trans_map;
}
const string &transform(const string &s, const map<string, string> &m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream &map_file, ifstream &input)
{
auto trans_map = build_map(map_file);
string text;
while (getline(input, text))
{
istringstream stream(text);
string word;
bool firstword = true;
while (stream >> word)
{
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
/*** main.cpp ***/
#include "exercise11_33.hpp"
int main()
{
string map_convert_file = "exercise11_38/txt/word_convert_map.txt";
string inputfile = "exercise11_38/txt/convert_text.txt";
ifstream map_file(map_convert_file);
ifstream input(inputfile);
word_transform(map_file, input);
return 0;
}
练习11.38
/******************************************************************************
*用unordered_map重写单词计数程序(参见11.1节,第375页)和单词转换程序(参见11.3.6节,第
*391页)。
*****************************************************************************/
/*** 单词计数程序 ***/
#include <unordered_map>
#include <iostream>
using std::cin;
using std::cout;
using std::string;
using std::unordered_map;
int main()
{
unordered_map<string, size_t> word_count;
string word;
while (cin >> word)
++word_count[word];
for (auto &w : word_count)
cout << w.first << ": " << w.second << "\n";
return 0;
}
/*** 单词转换程序 ***/
/*** exercise11_38_2.hpp ***/
#include <fstream>
using std::ifstream;
using std::string;
void word_transform(ifstream &map_file, ifstream &input);
/*** exercise11_38_2.cpp ***/
#include <sstream>
#include <unordered_map>
#include <iostream>
#include "exercise11_38_2.hpp"
using std::cout;
using std::endl;
using std::getline;
using std::istringstream;
using std::runtime_error;
using std::unordered_map;
unordered_map<string, string> build_map(ifstream &map_file)
{
unordered_map<string, string> trans_map;
string key;
string value;
while (map_file >> key && getline(map_file, value))
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw runtime_error("no rule for " + key);
return trans_map;
}
const string &transform(const string &s, const unordered_map<string, string> &m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(ifstream &map_file, ifstream &input)
{
auto trans_map = build_map(map_file);
string text;
while (getline(input, text))
{
istringstream stream(text);
string word;
bool firstword = true;
while (stream >> word)
{
if (firstword)
firstword = false;
else
cout << " ";
cout << transform(word, trans_map);
}
cout << endl;
}
}
/*** main ***/
#include "exercise11_38_2.hpp"
int main()
{
string map_convert_file = "exercise11_38_2/txt/word_convert_map.txt";
string inputfile = "exercise11_38_2/txt/convert_text.txt";
ifstream map_file(map_convert_file);
ifstream input(inputfile);
word_transform(map_file, input);
return 0;
}