综合练习:用 STL 做一个通讯录
这是什么:用 STL 拼出来的通讯录——能加联系人、能按名字查电话、能换号、能删除、还能按添加顺序列出全部。
为什么用:四章学完,武器库齐了:vector 管顺序、string 管文字、map 管查找。这次把它们拼成一件真东西,顺便看看几个容器是怎么分工协作的。
如何用:先用 map<string, string> 管查找、vector<string> 记下添加顺序,再拼出完整代码。
思路:两个容器分工
map<string, string>:名字 → 电话,负责查找、覆盖、删除vector<string>:记下添加顺序,负责"按加人的顺序列出"
map 查得快但不记顺序,vector 记顺序但查得慢——各干各的活,配合起来正好。
完整代码
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main() {
std::map<std::string, std::string> book; // 名字 → 电话
std::vector<std::string> names; // 添加顺序
// —— 增:两个容器一起动 ——
book["妈妈"] = "13800000001"; names.push_back("妈妈");
book["老爸"] = "13800000002"; names.push_back("老爸");
book["同桌"] = "13800000003"; names.push_back("同桌");
// —— 查:按名字找电话 ——
std::string who = "同桌";
auto it = book.find(who);
if (it != book.end()) {
std::cout << who << " 的电话:" << it->second << std::endl;
} else {
std::cout << "通讯录里没有 " << who << std::endl;
}
// —— 改:换号码,直接覆盖 ——
book["同桌"] = "13900000009";
// —— 删:老爸出门远行(演示用)——
book.erase("老爸");
// —— 列出全部:vector 保证顺序,map 负责查号 ——
std::cout << "---- 通讯录共 " << book.size() << " 人 ----" << std::endl;
for (const std::string& n : names) {
if (book.count(n)) {
std::cout << n << ":" << book[n] << std::endl;
}
}
return 0;
}
运行效果:
同桌 的电话:13800000003
---- 通讯录共 2 人 ----
妈妈:13800000001
同桌:13900000009
代码怎么读
| 位置 | 用到的本事 | 来自哪一章 |
|---|---|---|
book["妈妈"] = "..." |
map 的 [] 新增/覆盖 |
map 与 set |
names.push_back("妈妈") |
vector 尾部追加 | vector |
book.find(who) + it->second |
find 查找,顺路取值 | map 与 set |
book.erase("老爸") |
map 按键删除 | map 与 set |
for (const std::string& n : names) |
vector 遍历 | vector |
book.count(n) |
先确认人还在,再取号 | map 与 set |
两个细节:删掉"老爸"后,names 里还留着这个名字,所以列出时要先 count 确认再打印——真实工程里"两个容器要同步"就是这类小坑;it->second 是从 find 返回的位置里取值,first 是键、second 是值。电话号码用 string 存而不是数字,因为号码可能以 0 开头、也可能太长——这是实际开发的小经验。
记忆口诀
map 管查找,vector 管顺序;先 count 再取值,增删改查一把梭。
动手改
- 把
who改成"班主任",运行后确认走的是"查无此人"分支 - 再删一个人(比如
book.erase("妈妈")),观察 size 和列表的变化 - 制造一次"不同步":只往
book加人、忘了names.push_back,列出全部时会发生什么?
STL 毕业 🎉 C++ 板块完结!下一站 Java,看看企业级开发的中流砥柱