C++中的一些特殊组件(区别于C)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

这篇文章持续更新一些C++中新增的组件的写法和用法,例如容器等


提示:以下是本篇文章正文内容,下面案例可供参考

一、容器(vector)

  • 容器 vector 是 C++ 标准库中的一个概念,相当于一个动态数组。vector 提供了一种灵活的方式来存储和管理元素序列,它可以根据需要自动调整大小。实现插入或删除的操作
  • 而C 语言本身没有实现类似动态数组的数据结构。只能使用静态数组或者指针和动态内存分配来模拟类似的行为。
//创建一个容器,使用迭代器正向和反向遍历输出元素
#include <iostream>
#include <vector>

int main() {
    // 创建一个空的 vector 容器
    std::vector<int> numbers;
    // 提示用户输入 5 个整数
    std::cout << "请输入 5 个整数:" << std::endl;
    // 循环读取用户输入的整数并存储到 vector 中
    for (int i = 0; i < 5; i++) {
        int num;
        std::cin >> num;
        numbers.push_back(num);//调用内部函数将输入的数据存放到容器中
    }

    // 使用正向迭代器遍历 vector 并输出元素
    std::cout << "使用正向迭代器遍历输出:" << std::endl;
    for (std::vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++) {
        std::cout << *it << " ";//由于it是指针,因此*it指向容器中的值
    }
    std::cout << std::endl;

    // 使用反向迭代器遍历 vector 并输出元素
    std::cout << "使用反向迭代器遍历输出:" << std::endl;
    for (std::vector<int>::reverse_iterator it = numbers.rbegin(); it != numbers.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

这段代码中可能需要解释一下for 循环中条件的写法,这种写法是迭代器遍历容器的标准方式。首先是正向遍历:

  • std::vector::iterator:这是定义迭代器类型的声明。iterator 是 std::vector 类的内置成员类型,表示一个可以遍历 vector 中元素的迭代器。
  • it = numbers.begin():这行代码返回一个指向 vector 第一个元素的迭代器。迭代器可以被视为一个指针。相当于定义了int i = 0;
  • it != numbers.end():这是 for 循环的条件部分。numbers.end() 返回一个迭代器,它指向 vector 中最后一个元素之后的“虚拟位置”。当迭代器 it 没有达到 vector 的末尾时,即 it 不等于 numbers.end(),循环继续执行。

如果是逆向遍历,则提供了rbegin()和rend()方法,前者返回一个指向容器末尾的指针,后者返回指向容器起始位置的前一个指针,这是一种逆序遍历方式

二、队列(deque)

  • deque 是 “double-ended queue” 的缩写,它是一种允许在两端进行插入和删除操作的容器。deque 是一种序列容器,它结合了 vector 的动态数组特性和 list 的双向链表特性,提供了在序列两端快速添加或移除元素的能力。
  • 与vector 不同,deque 不保证元素的物理连续性,因此它在两端添加或删除元素时通常比 vector 更快,因为不需要移动其他元素来重新分配内存。然而,由于 deque 的内部实现可能涉及到更多的内存分配和释放,所以在中间插入或删除元素时可能比 vector 慢。
  • deque 提供了许多与 std::vector 类似的成员函数,如 push_back()(队尾插入)、push_front(队头插入)、pop_back(队尾取出)、pop_front(队头取出) 、empty()(检测队列是否为空)、size()(返回队列大小)等函数;同时也支持迭代器和反向迭代器,使得它在需要频繁在序列两端操作的场景中特别实用。
//这段代码中就定义了一个队列,这个队列里存储的是class类型(队列可以存储很多种数据类型)
//然后向队列中插入了一些例化好的类,并取出
#include <iostream>
#include <deque>
using namespace std;

class Guest {
public:
    string name;
    bool vip;

    Guest(string name, bool vip) {
        this->name = name;
        this->vip = vip;
    }
};

int main() {
	//例化一些Guest类
    Guest guest1("张三", false);
    Guest guest2("李四", false);
    Guest vipGuest("王五", true);
    deque<Guest> deque;//定义一个队列,并指明该队列存储的对象是class Guest

    //将类插入到队列中
    deque.push_back(guest1);
    deque.push_back(guest2);
    deque.push_front(vipGuest);
	//这是遍历队列的一种方式,实际上编译器会自动把它转换成迭代器遍历写法
	//等价于for(deque<Guest>::iterator it = numbers.begin(); it != numbers.end(); ++it);vector中也可以这样写;添加const类型是防止遍历过程中该变量队列中的值
    for (const Guest& g : deque) {
        cout << g.name << " ";
    }

    return 0;
}

三、关联容器(map)

C++中的map是一个关联容器,其中存储的是键值对(key-value pairs),其中每个键都是唯一的。它能够提供对元素的有序存储,并且支持高效的查找、插入和删除操作。以下是map的一些基本用法:

  1. 包含头文件:在C++程序中使用map之前,需要包含头文件。
#include <map>
  1. 声明map,需要指定键(key)和值(value)的类型。默认情况下,map中的元素是按照键排序的。
std::map<char, int> myMap;//声明一个键为字符,值为整数的map
  1. 插入元素,使用insert方法。
myMap.insert(std::make_pair("Alice", 1));
myMap.insert(std::make_pair("Bob", 2));
  1. 访问元素,使用at方法可以通过键来访问map中的元素。如果键不存在,抛出std::out_of_range异常。
int value = myMap.at(“Alice”); // 获取键为“Alice”的值
//或者使用[]运算符,它会在键不存在时创建一个新的键值对。
myMap["Charlie"] = 3; // 如果键3不存在,会创建一个新的键值对
  1. 遍历map
for (auto it = myMap.begin(); it != myMap.end(); it++) {
	//auto 关键字用于自动推导循环中迭代变量的类型。由于 map 是一种关联容器,它的元素是键值对(pair),所以 auto 会推导出 std::pair<const Key, Value> 类型,其中 Key 是 map 的键类型,Value 是 map 的值类型。使用 auto 可以简化代码,因为它允许编译器根据 map 中元素的实际类型来推导变量的类型,这样你就不需要显式地指定类型。这在处理复杂类型或者类型较长时尤其有用。
    std::cout << it->first << ": " << it->second << std::endl;
    //被auto修饰后it就是map中的一个 std::pair 对象,包含两个成员:it.first 和 it.second,分别对应 map 中的键和值。
}
  1. 查找元素,使用find方法来查找特定的键。
if (myMap.find("Alice") != myMap.end()) {
    std::cout << "Found key Alice" << std::endl;
}
  1. 删除元素,可以使用erase方法删除指定的键值对。
myMap.erase("Alice"); // 删除键为2的元素
  1. 获取map的大小,使用size方法获取map中元素的数量。
std::cout << "Map size: " << myMap.size() << std::endl;
  1. 清空map,使用clear方法清空map中的所有元素。
myMap.clear();
  1. 比较操作,map支持比较操作,可以用来比较两个map是否相等。
std::map<int, std::string> anotherMap = myMap;
bool areEqual = (myMap == anotherMap); // true if both maps are equal

举一个例子,使用map统计一个字符串中各字母出现的次数

#include <iostream>
#include <map>
using namespace std;

int main() {
	//输入一个字符串
    char str[100] = { 0 };
    cin.getline(str, sizeof(str));

    //定义map,并遍历字符串遇到新的字符就创建
    map <char, int> maps;
    for(int i = 0; str[i] != '\0'; i++) {
        if(isalpha(str[i])) {
            maps[str[i]]++;//[]是一个运算符,如果没有str[i]就会创建这个键并且值加1,如果存在的话,值加1,这样就能够计数
        }
    }
	//统计完后遍历map,打印相应的键和值
    for(auto it = maps.begin(); it != maps.end(); it++) {
        cout << it->first << ":" << it->second << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值