S SmartDocs
Series: C++ cpp 258 lines · Updated 2026-04-03

map_set.cpp

C++/Part3_泛型與STL/Ch13_STL容器/map_set.cpp

// map_set.cpp
// map、set、multimap、multiset 的完整用法示範
// 編譯:g++ -std=c++17 -Wall -o map_set map_set.cpp

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <sstream>

int main() {
    std::cout << "========================================" << std::endl;
    std::cout << "  map / set / multimap / multiset 示範" << std::endl;
    std::cout << "========================================\n" << std::endl;

    // ========================================================
    // Part A: std::map
    // ========================================================
    std::cout << "==================== std::map ====================" << std::endl;

    // --- 1. 建構與插入 ---
    std::cout << "\n--- 1. 建構與插入 ---" << std::endl;

    std::map<std::string, int> scores;

    // 方法 1:operator[]
    scores["Alice"] = 95;
    scores["Bob"] = 87;

    // 方法 2:insert
    scores.insert({"Charlie", 92});
    scores.insert(std::make_pair("David", 78));

    // 方法 3:emplace
    scores.emplace("Eve", 88);

    // 印出所有元素(自動按 key 排序)
    std::cout << "所有學生成績(按姓名排序):" << std::endl;
    for (const auto& [name, score] : scores) {  // C++17 結構化綁定
        std::cout << "  " << name << ": " << score << std::endl;
    }

    // --- 2. 存取元素 ---
    std::cout << "\n--- 2. 存取元素 ---" << std::endl;

    // operator[] — 不存在時會自動插入預設值!
    std::cout << "scores[\"Alice\"] = " << scores["Alice"] << std::endl;

    // at() — 不存在時拋出例外
    try {
        std::cout << "scores.at(\"Bob\") = " << scores.at("Bob") << std::endl;
        scores.at("Unknown");
    } catch (const std::out_of_range& e) {
        std::cout << "at(\"Unknown\") 例外: " << e.what() << std::endl;
    }

    // --- 3. find / count ---
    std::cout << "\n--- 3. find / count ---" << std::endl;

    auto it = scores.find("Charlie");
    if (it != scores.end()) {
        std::cout << "找到 Charlie: " << it->second << std::endl;
    }

    std::cout << "count(\"Alice\")   = " << scores.count("Alice") << std::endl;
    std::cout << "count(\"Unknown\") = " << scores.count("Unknown") << std::endl;

    // --- 4. erase ---
    std::cout << "\n--- 4. erase ---" << std::endl;

    std::cout << "刪除前 size = " << scores.size() << std::endl;
    scores.erase("David");
    std::cout << "erase(\"David\") 後 size = " << scores.size() << std::endl;

    // --- 5. 修改值 ---
    std::cout << "\n--- 5. 修改值 ---" << std::endl;

    scores["Alice"] = 100;  // 修改已有 key 的值
    std::cout << "Alice 成績改為: " << scores["Alice"] << std::endl;

    // --- 6. 應用:單字頻率計數器 ---
    std::cout << "\n--- 6. 應用:單字頻率計數器 ---" << std::endl;

    std::string text = "the quick brown fox jumps over the lazy dog the fox";
    std::map<std::string, int> word_count;

    std::istringstream iss(text);
    std::string word;
    while (iss >> word) {
        word_count[word]++;  // 自動計數
    }

    std::cout << "文字: \"" << text << "\"" << std::endl;
    std::cout << "單字頻率:" << std::endl;
    for (const auto& [w, count] : word_count) {
        std::cout << "  \"" << w << "\": " << count << " 次" << std::endl;
    }

    // ========================================================
    // Part B: std::set
    // ========================================================
    std::cout << "\n==================== std::set ====================" << std::endl;

    // --- 1. 建構(自動排序、去重)---
    std::cout << "\n--- 1. 建構(自動排序、去重)---" << std::endl;

    std::set<int> s = {5, 3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    std::cout << "初始化 {5,3,1,4,1,5,9,2,6,5,3}" << std::endl;
    std::cout << "set 內容: {";
    bool first = true;
    for (int val : s) {
        if (!first) std::cout << ", ";
        std::cout << val;
        first = false;
    }
    std::cout << "}" << std::endl;
    std::cout << "size = " << s.size() << " (重複被移除)" << std::endl;

    // --- 2. insert / emplace ---
    std::cout << "\n--- 2. insert / emplace ---" << std::endl;

    auto [iter, inserted] = s.insert(7);
    std::cout << "insert(7): " << (inserted ? "成功" : "已存在") << std::endl;

    auto [iter2, inserted2] = s.insert(5);
    std::cout << "insert(5): " << (inserted2 ? "成功" : "已存在") << std::endl;

    // --- 3. find / count / erase ---
    std::cout << "\n--- 3. find / count / erase ---" << std::endl;

    if (s.find(4) != s.end()) {
        std::cout << "找到 4" << std::endl;
    }
    std::cout << "count(9) = " << s.count(9) << std::endl;
    std::cout << "count(100) = " << s.count(100) << std::endl;

    s.erase(1);
    std::cout << "erase(1) 後: {";
    first = true;
    for (int val : s) {
        if (!first) std::cout << ", ";
        std::cout << val;
        first = false;
    }
    std::cout << "}" << std::endl;

    // --- 4. 應用:從 vector 去重 ---
    std::cout << "\n--- 4. 應用:從 vector 去重 ---" << std::endl;

    std::vector<int> vec = {4, 2, 7, 2, 1, 4, 8, 1, 7};
    std::set<int> unique_set(vec.begin(), vec.end());

    std::cout << "原始 vector: [";
    first = true;
    for (int v : vec) {
        if (!first) std::cout << ", ";
        std::cout << v;
        first = false;
    }
    std::cout << "]" << std::endl;

    std::cout << "去重排序後:  {";
    first = true;
    for (int v : unique_set) {
        if (!first) std::cout << ", ";
        std::cout << v;
        first = false;
    }
    std::cout << "}" << std::endl;

    // ========================================================
    // Part C: std::multimap
    // ========================================================
    std::cout << "\n==================== std::multimap ====================" << std::endl;

    std::cout << "\n--- multimap:一個 key 可對應多個 value ---" << std::endl;

    std::multimap<std::string, int> grades;
    grades.insert({"Alice", 95});
    grades.insert({"Alice", 88});
    grades.insert({"Alice", 92});
    grades.insert({"Bob", 77});
    grades.insert({"Bob", 85});

    std::cout << "所有成績:" << std::endl;
    for (const auto& [name, grade] : grades) {
        std::cout << "  " << name << ": " << grade << std::endl;
    }

    // equal_range 取得某個 key 的所有值
    std::cout << "\nAlice 的所有成績:" << std::endl;
    auto [lower, upper] = grades.equal_range("Alice");
    double sum = 0;
    int count = 0;
    for (auto it_range = lower; it_range != upper; ++it_range) {
        std::cout << "  " << it_range->second << std::endl;
        sum += it_range->second;
        ++count;
    }
    std::cout << "  平均: " << sum / count << std::endl;

    std::cout << "Alice 的成績筆數: " << grades.count("Alice") << std::endl;

    // ========================================================
    // Part D: std::multiset
    // ========================================================
    std::cout << "\n==================== std::multiset ====================" << std::endl;

    std::cout << "\n--- multiset:允許重複元素 ---" << std::endl;

    std::multiset<int> ms = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
    std::cout << "multiset 內容: {";
    first = true;
    for (int val : ms) {
        if (!first) std::cout << ", ";
        std::cout << val;
        first = false;
    }
    std::cout << "}" << std::endl;

    std::cout << "count(5) = " << ms.count(5) << std::endl;
    std::cout << "count(1) = " << ms.count(1) << std::endl;
    std::cout << "size()   = " << ms.size() << std::endl;

    // erase 會刪除所有相同值
    ms.erase(5);
    std::cout << "erase(5) 後 size = " << ms.size() << std::endl;

    // ========================================================
    // 應用:學生成績查詢系統
    // ========================================================
    std::cout << "\n==================== 應用:學生成績查詢 ====================" << std::endl;

    std::map<std::string, std::vector<int>> student_grades;
    student_grades["Alice"] = {95, 88, 92, 97};
    student_grades["Bob"] = {77, 85, 90};
    student_grades["Charlie"] = {62, 71, 68, 73, 80};

    for (const auto& [name, grade_list] : student_grades) {
        double avg = 0;
        for (int g : grade_list) avg += g;
        avg /= grade_list.size();

        std::cout << name << " 的成績: [";
        for (std::size_t i = 0; i < grade_list.size(); ++i) {
            if (i > 0) std::cout << ", ";
            std::cout << grade_list[i];
        }
        std::cout << "]  平均: " << avg << std::endl;
    }

    std::cout << "\n========================================" << std::endl;
    std::cout << "  map / set 示範結束" << std::endl;
    std::cout << "========================================" << std::endl;

    return 0;
}

Related articles