C++与现代开发实践第二课:C++标准库(STL)深入

第四章:C++与现代开发实践

第二课:C++标准库(STL)深入
1. STL容器与算法的全面讲解
1.1 STL的基本概念

C++标准模板库(STL)是C++的一项核心特性,为程序员提供了一个高效且灵活的方式来处理数据结构和算法。STL的设计理念是"泛型编程",允许使用通用的接口和数据类型,以减少代码的重复和增加代码的复用性。STL主要包括三部分:

  1. 容器 :用于存储数据的对象,例如 vectorlistmap 等。
  2. 算法:对容器中的数据执行操作的函数,例如排序、查找等。
  3. 迭代器:用于遍历容器的对象,提供了一种统一的方式来访问容器元素。

通过使用STL,开发者可以在提高代码可读性的同时,增强程序的性能。

1.2 STL容器的详细分类

STL容器大致分为以下几类,每类容器有其特定的使用场景和特点:

  • 序列容器 :包括 vectordequelist

    • vector:动态数组,支持随机访问,适合频繁插入和删除操作的末尾。
    • deque:双端队列,支持在两端快速插入和删除,适合需要频繁在两端操作的场景。
    • list:双向链表,适合频繁插入和删除操作,但不支持随机访问。
  • 关联容器 :包括 setmapunordered_setunordered_map

    • set:存储唯一值的集合,自动排序。
    • map:键值对集合,支持按键查找。
    • unordered_setunordered_map:基于哈希表实现,查找效率更高,但不保证顺序。
  • 适配器容器 :如 stackqueuepriority_queue

    • stack:后进先出(LIFO)结构。
    • queue:先进先出(FIFO)结构。
    • priority_queue:元素按照优先级进行访问。
1.3 STL算法的深入解析

STL算法是针对容器中元素的操作,标准库提供了大量的算法,主要包括:

  • 排序算法 :如 sort()stable_sort()
  • 查找算法 :如 find()binary_search()
  • 变换算法 :如 transform()copy()
  • 聚合算法 :如 accumulate()for_each()

例如,使用 sort()vector 进行排序:

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {4, 2, 3, 1, 5};
    std::sort(vec.begin(), vec.end());

    std::cout << "Sorted vector: ";
    for (const auto& num : vec) {
        std::cout << num << " ";
    }
    return 0;
}
1.4 迭代器的使用与优势

迭代器是STL的重要组成部分,它提供了一种统一的方式来访问容器中的元素。迭代器的类型包括:

  • 输入迭代器:只能读取数据。
  • 输出迭代器:只能写入数据。
  • 前向迭代器:可以读写数据,且只能向前移动。
  • 双向迭代器:可以向前和向后移动。
  • 随机访问迭代器:支持任意位置的快速访问。

例如,使用迭代器遍历 list

cpp 复制代码
#include <iostream>
#include <list>

int main() {
    std::list<int> lst = {1, 2, 3, 4, 5};
    for (auto it = lst.begin(); it != lst.end(); ++it) {
        std::cout << *it << " ";
    }
    return 0;
}
2. 复杂数据操作的实例
2.1 项目背景与需求

在进行大数据分析时,处理复杂数据的能力至关重要。我们的目标是创建一个系统,能够从用户输入中提取信息并进行处理。为此,我们将利用STL的强大功能来存储和处理这些数据。

2.2 使用mapvector存储数据

我们可以使用 map 存储用户信息,vector 存储特定属性(如评分、评论等):

cpp 复制代码
#include <iostream>
#include <map>
#include <vector>

struct UserInfo {
    std::string username;
    std::vector<int> ratings;

    UserInfo(const std::string& name) : username(name) {}
};
2.3 操作用户信息

以下是对用户信息进行插入和查询的示例:

cpp 复制代码
int main() {
    std::map<std::string, UserInfo> userDatabase;

    // 插入用户信息
    UserInfo user1("Alice");
    user1.ratings.push_back(5);
    userDatabase[user1.username] = user1;

    UserInfo user2("Bob");
    user2.ratings.push_back(3);
    userDatabase[user2.username] = user2;

    // 查询用户信息
    auto it = userDatabase.find("Alice");
    if (it != userDatabase.end()) {
        std::cout << "User: " << it->second.username << ", Ratings: ";
        for (const auto& rating : it->second.ratings) {
            std::cout << rating << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}
2.4 复杂数据操作的实现

我们需要实现对用户评分的统计和排序功能。首先定义一个函数计算平均评分:

cpp 复制代码
double calculateAverageRating(const UserInfo& user) {
    double sum = 0;
    for (int rating : user.ratings) {
        sum += rating;
    }
    return sum / user.ratings.size();
}

接着实现按平均评分排序的功能:

cpp 复制代码
#include <algorithm>
#include <iostream>
#include <vector>

std::vector<std::pair<std::string, double>> sortUsersByRating(const std::map<std::string, UserInfo>& users) {
    std::vector<std::pair<std::string, double>> averages;

    for (const auto& pair : users) {
        double avgRating = calculateAverageRating(pair.second);
        averages.emplace_back(pair.first, avgRating);
    }

    std::sort(averages.begin(), averages.end(),
              [](const auto& a, const auto& b) { return a.second > b.second; });

    return averages;
}
2.5 实例展示

在主函数中调用以上函数,并展示排序后的结果:

cpp 复制代码
int main() {
    std::map<std::string, UserInfo> userDatabase;
    
    // (插入用户信息的代码...)
    
    // 按评分排序
    auto sortedUsers = sortUsersByRating(userDatabase);
    std::cout << "Users sorted by average rating:\n";
    for (const auto& entry : sortedUsers) {
        std::cout << "User: " << entry.first << ", Average Rating: " << entry.second << std::endl;
    }

    return 0;
}
3. 使用STL进行实际项目开发的案例(续)
3.1 项目背景与目标(续)

在构建图书管理系统时,除了基本的书籍信息管理,我们还需要处理用户借阅图书的功能。通过STL,我们可以进一步扩展项目,增加借阅和归还图书的操作。

3.2 借阅管理的设计

我们将扩展 Library 类,增加借阅和归还书籍的功能:

cpp 复制代码
class Library {
public:
    void addBook(const Book& book) {
        books.push_back(book);
    }

    bool borrowBook(const std::string& title, const std::string& username) {
        auto it = std::find_if(books.begin(), books.end(),
                                [&title](const Book& book) { return book.title == title; });
        if (it != books.end()) {
            borrowedBooks[username].push_back(*it);
            books.erase(it);
            return true;
        }
        return false;
    }

    void returnBook(const std::string& title, const std::string& username) {
        auto it = borrowedBooks.find(username);
        if (it != borrowedBooks.end()) {
            auto& userBooks = it->second;
            auto bookIt = std::find_if(userBooks.begin(), userBooks.end(),
                                        [&title](const Book& book) { return book.title == title; });
            if (bookIt != userBooks.end()) {
                books.push_back(*bookIt);
                userBooks.erase(bookIt);
            }
        }
    }

    void displayBorrowedBooks(const std::string& username) const {
        auto it = borrowedBooks.find(username);
        if (it != borrowedBooks.end()) {
            std::cout << "Books borrowed by " << username << ":\n";
            for (const auto& book : it->second) {
                std::cout << "Title: " << book.title << ", Author: " << book.author << ", Rating: " << book.rating << std::endl;
            }
        } else {
            std::cout << "No borrowed books found for " << username << ".\n";
        }
    }

private:
    std::vector<Book> books;
    std::map<std::string, std::vector<Book>> borrowedBooks;
};
3.3 借阅与归还操作的实现

main 函数中,我们展示如何使用这些功能:

cpp 复制代码
int main() {
    Library library;

    // 添加书籍
    library.addBook(Book("C++ Primer", "Lippman", 4.8));
    library.addBook(Book("Effective C++", "Scott Meyers", 4.7));

    // 借阅书籍
    library.borrowBook("C++ Primer", "Alice");
    library.displayBorrowedBooks("Alice");

    // 归还书籍
    library.returnBook("C++ Primer", "Alice");
    library.displayBorrowedBooks("Alice");

    return 0;
}

在这个示例中,我们演示了借阅书籍、查看借阅情况以及归还书籍的操作。

3.4 扩展功能:罚款管理

为了增强系统的实用性,我们还可以添加罚款管理功能,计算逾期未还的图书罚款:

cpp 复制代码
double calculateFine(const std::string& username, const std::vector<Book>& overdueBooks) {
    double totalFine = 0.0;
    for (const auto& book : overdueBooks) {
        totalFine += 1.0;  // 每本逾期图书罚款1.0
    }
    return totalFine;
}

在这个函数中,我们计算用户未按时归还的图书所需支付的罚款。


3.5 完整示例展示

最终,在 main 函数中,结合所有功能,展示完整的书籍管理系统:

cpp 复制代码
int main() {
    Library library;

    // 添加书籍
    library.addBook(Book("C++ Primer", "Lippman", 4.8));
    library.addBook(Book("Effective C++", "Scott Meyers", 4.7));

    // 借阅书籍
    library.borrowBook("C++ Primer", "Alice");
    library.displayBorrowedBooks("Alice");

    // 归还书籍
    library.returnBook("C++ Primer", "Alice");
    library.displayBorrowedBooks("Alice");

    // 罚款计算示例
    std::vector<Book> overdueBooks = { Book("C++ Primer", "Lippman", 4.8) };
    double fine = calculateFine("Alice", overdueBooks);
    std::cout << "Total fine for Alice: $" << fine << std::endl;

    return 0;
}

小结

在本课中,我们深入探讨了C++标准库(STL),包括容器和算法的详细用法以及复杂数据操作的实例。通过构建实际项目案例,我们展示了STL在开发过程中的强大功能和灵活性。这不仅提高了代码的可维护性,还增强了开发效率。掌握STL的使用将为你在C++编程的旅程中打下坚实的基础。

相关推荐
数据小爬虫@几秒前
如何利用java爬虫获得淘宝商品评论
java·开发语言·爬虫
qq_172805598 分钟前
RUST学习教程-安装教程
开发语言·学习·rust·安装
天才在此11 分钟前
汽车加油行驶问题-动态规划算法(已在洛谷AC)
算法·动态规划
wjs202415 分钟前
MongoDB 更新集合名
开发语言
monkey_meng19 分钟前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
一只小小汤圆23 分钟前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz44 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
嘿BRE1 小时前
【C++】几个基本容器的模拟实现(string,vector,list,stack,queue,priority_queue)
c++
tangliang_cn1 小时前
java入门 自定义springboot starter
java·开发语言·spring boot
莫叫石榴姐1 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘