11.1、使用关联容器
//11.4单词计数程序,程序扩展,忽略大小写和标点
#include<iostream>
#include<fstream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
string &trans(string &s)
{
for(int p = 0; p < s.size(); ++p){
if(s[p] >= 'A' && s[p] <= 'Z')
s[p] -= ('A' - 'a');
else if(s[p] == ',' || s[p] == '.')
s.erase(p, 1); //从p开始删除一个字符
}
return s;
}
int main(int argc, char *argv[])
{
ifstream in(argv[1]);
if(!in){
cout << "打开输入文件失败" << endl;
exit(1); //异常退出
}
map<string, size_t> word_count; //string 到 count 映射
string word;
while(in >> word)
++word_count[trans(word)]; //单词出现次数加一
for(const auto &w : word_count) //对map中的每个元素
//打印结果
cout << w.first << "出现了" << w.second << "次" << endl;
return 0;
}
//11.9 定义一个map,将单词与一个行号的list关联,list中保存的是单词所出现的行号。
#include<iostream>
#include<fstream>
#include<sstream>
#include<map>
#include<list>
#include<string>
#include<algorithm>
using namespace std;
string &trans(string &s)
{
for(int p = 0; p < s.size(); ++p){
if(s[p] >= 'A' && s[p] <= 'Z')
s[p] -= ('A' - 'a');
else if(s[p] == ',' || s[p] == '.')
s.erase(p, 1); //从p开始删除一个字符
}
return s;
}
int main(int argc, char *argv[])
{
ifstream in(argv[1]);
if(!in){
cout << "打开输入文件失败" << endl;
exit(1); //异常退出
}
map<string, list<int>> word_lineno; //单词到行号的映射
string line;
string word;
int lineno = 0;
while(getline(in, line)){ //读取一行
lineno++; //行号增加
istringstream l_in(line); //构造字符串流,读取单词
while(l_in >> word){
trans(word);
word_lineno[word].push_back(lineno); //添加行号
}
}
for(const auto &w : word_lineno){ //打印单词行号
cout << w.first << "所在行:";
for(const auto &i : w.second)
cout << i << " ";
cout << endl;
}
return 0;
}
multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);
//等价于
typedef bool (*pf)(const Sales_data &, const Sales_data &);
multiset<Sales_data, pf> bookstore(compareIsbn);
pair类型(头文件utility)
//练习11.12、编写程序,读入string 和 int的序列,将每个string和int存入一个pair中,pair保存在一个vector中
#include<iostream>
#include<fstream>
#include<utility>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main(int argc, char *argv[])
{
ifstream in(argv[1]);
if(!in){
cout << "打开输入文件失败!" << endl;
exit(1);
}
vector<pair<string, int>> data; //pair的vector
string s;
int v;
while(in >> s && in >> v) //读取一个字符串和一个整数
//三种不同的方式
data.push_back({s, v});
//data.push_back(pair<string, int>(s, v));
//data.push_back(make_pair(s, v));
for(const auto &d : data) //打印单词行号
cout << d.first << " " << d.second << endl;
return 0;
}
11.3、关联容器操作
检测insert的返回值
insert(或emplace)返回的值依赖于容器类型和参数。对于不包含重复关键字的容器,添加单一元素的insert和emplace版本返回一个pair,告诉我们插入操作是否成功。pair的first成员是一个迭代器,指向具有给定关键字的元素。second是一个bool值,指出元素是否插入成功还是已经存在容器中。
删除元素
map的下标操作
使用map下标操作的返回值
对一个map进行下标操作时,会获得一个mapped_type对象;但当解引用一个map迭代器时,会得到一个value_type对象。
访问元素
//练习11.31
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
void remove_author(multimap<string,string> &books,
const string &author)
{
auto pos = books.equal_range(author); //查找给定作者范围
if(pos.first == pos.second) //空范围,没有该作者
cout << "没有" << author << "这个作者" << endl << endl;
else
books.erase(pos.first, pos.second); //删除该作者的所有著作
}
void print_books(multimap<string, string> &books)
{
cout << "当前书目包括:" << endl;
for(auto &book : books) //遍历所有书籍,打印之
cout << book.first << ", 《" << book.second << "》" << endl;
cout << endl;
}
int main(int argc, char *argv[])
{
multimap<string, string> books;
books.insert({"Barth, John", "Sot-Weed Factor"});
books.insert({"Barth, John", "Lost in the Funhouse"});
books.insert({"金庸", "射雕英雄传"});
books.insert({"金庸", "天龙八部"});
print_books(books);
remove_author(books, "张三");
remove_author(books, "金庸");
print_books(books);
return 0;
}
#include <map>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
map<string, string> buildMap(ifstream &map_file)
{
map<string, string> trans_map; //保存转换规则
string key; //要转换的单词
string value; //替换后的内容
//读取第一个单词存入key中,行中剩余内容存入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);
//如果单词在转换规则map中
if(map_it != m.cend())
return map_it->second; //使用替换短语
else
return s; //否则返回原string
}
void word_transform(ifstream &map_file, ifstream &input)
{
auto trans_map = buildMap(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 << " "; //在单词间打印一个空格
//transform返回它的第一个参数或其转换之后的形式
cout << transform(word, trans_map); //打印输出
}
cout << endl; //完成一行的转换
}
}
int main(int argc, const char *argv[])
{
if(argc != 3)
throw runtime_error("wrong numbei of arguments");
ifstream map_file(argv[1]);
if(!map_file)
throw runtime_error("no transformation file");
ifstream input(argv[2]);
if(!input)
throw runtime_error("no input file");
word_transform(map_file, input);
return 0;
}
无序容器