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