当前位置: 首页 > news >正文

【C转C++】 C转C++超值且好用的容器与函数

前言:欢迎各位光临本博客,这里小编带你直接手撕**,文章并不复杂,愿诸君**耐其心性,忘却杂尘,道有所长!!!!

在这里插入图片描述


IF’Maxue:个人主页

 🔥 个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》

⛺️生活是默默的坚持,毅力是永久的享受。不破不立!

文章目录

  • C转C++
    • 一、map:键值对管理神器
      • 1. 核心特性:自动排序的键值对
      • 2. 底层逻辑
      • 3. unordered_map:无序但更快的键值对
      • 4. 常用操作:比C手动实现简单10倍
    • 二、vector:动态数组
      • 1. 核心特性:自动扩容的动态数组
      • 2. 对比C数组
      • 3. 常用操作
    • 三、set:自动去重与排序
      • 1. 核心特性:去重+排序
      • 2. 对比C的实现
    • 四、string:告别char*的字符串处理
      • 1. 核心特性:像用int一样用字符串
      • 2. 输入输出:解决cin的空格问题
      • 3. 常用函数:字符串操作不用愁
      • 4. 对比C的str系列函数:安全+简洁
    • 五、其他常用工具:栈、哈希检查等
      • 1. 栈(stack):先进后出的操作
      • 2. contains:检查键是否存在(C++20+)
    • 总结:C转C++,从这些容器开始

C转C++

从C转向C++,最直观的优势就是STL(标准模板库)带来的便捷——不用再手动管理内存、实现排序和查找,一行代码就能搞定C中需要几十行才能完成的功能。本文就来推荐几个C转C++必学的容器和函数,从键值对管理到动态数组,从集合操作到字符串处理,带你快速上手高效编程。

一、map:键值对管理神器

在C中,要实现“一个元素对应另一个元素”(比如“名字-分数”“ID-信息”),通常需要手动定义结构体+数组,还要自己写查找和排序逻辑,麻烦又容易出错。而C++的map容器天生为键值对设计,自动排序+快速查找,直接省去大量重复工作。

1. 核心特性:自动排序的键值对

map的本质是“关联容器”,每个元素是一个key-value(键值对),且会自动按照键(key)从小到大排序。比如用字符串作为键时,会按字典序排序;用数字作为键时,会按数值大小排序。

#include <map>  // 必须包含的头文件
#include <iostream>
using namespace std;int main() {// 定义一个map:键是string类型,值是int类型(比如“名字-分数”)map<string, int> score_map;// 1. 添加键值对(像用数组一样简单)score_map["Alice"] = 95;  // 键“Alice”对应值95score_map["Bob"] = 88;    // 键“Bob”对应值88score_map["Cindy"] = 92;  // 键“Cindy”对应值92// 2. 访问值(直接通过键获取)cout << "Bob的分数:" << score_map["Bob"] << endl;  // 输出:88// 3. 遍历所有键值对(自动按键排序)cout << "所有分数(按名字排序):" << endl;// 迭代器:类似指针,指向map中的每个键值对(结构体)for (auto it = score_map.begin(); it != score_map.end(); ++it) {// it->first 是键,it->second 是值cout << it->first << ":" << it->second << endl;}// 4. 获取键值对数量cout << "总人数:" << score_map.size() << endl;  // 输出:3return 0;
}

运行结果:

Bob的分数:88
所有分数(按名字排序):
Alice:95
Bob:88
Cindy:92
总人数:3

可以看到,map自动按名字的字典序(Alice→Bob→Cindy)排序,省去了手动调用qsort的麻烦;访问时直接用map[key],比C中遍历数组查找高效10倍。

2. 底层逻辑

map中的每个元素本质上是一个匿名结构体,类似我们在C中定义的:

// C中模拟键值对的结构体
struct KeyValue {char key[20];  // 键(名字)int value;     // 值(分数)
};
struct KeyValue score_arr[100];  // 用数组存储

map帮我们做了三件事:

  • 自动维护排序(无需手动调用排序函数);
  • 自动扩容(无需担心数组越界);
  • 快速查找(底层是红黑树,查找复杂度O(log n),比C中遍历数组的O(n)快得多)。

3. unordered_map:无序但更快的键值对

如果不需要键值对排序,unordered_map是更好的选择——它底层是哈希表,查找、插入、删除的速度更快(平均O(1)),用法和map几乎一样:

#include <unordered_map>  // 头文件不同
#include <iostream>
using namespace std;int main() {unordered_map<string, int> score_umap;score_umap["Alice"] = 95;score_umap["Bob"] = 88;// 遍历:无序(按哈希表存储顺序)for (auto it = score_umap.begin(); it != score_umap.end(); ++it) {cout << it->first << ":" << it->second << endl;}return 0;
}

什么时候用哪个?

  • 需要排序:用map(比如排行榜、字典);
  • 追求速度,无需排序:用unordered_map(比如缓存、索引)。

4. 常用操作:比C手动实现简单10倍

操作C++ map/unordered_mapC中手动实现
插入map[key] = valuemap.insert({key, value})遍历数组找空位,手动赋值
查找map.find(key) != map.end()(存在)遍历数组对比每个key
删除map.erase(key)遍历找到后移动元素覆盖
判空map.empty()检查数组长度是否为0

二、vector:动态数组

C中的数组堪称“新手噩梦”:静态数组大小固定(int arr[10]),动态数组需要malloc+realloc+free,稍不注意就内存泄漏或越界。而vector作为“动态数组”,自动管理内存,大小随元素增减而变化,彻底解决这些问题。

1. 核心特性:自动扩容的动态数组

vector可以理解为“会自动长大的数组”,初始化时可以指定大小,也可以空着,后续用push_back随时添加元素,不用担心越界。

#include <vector>  // 必须包含的头文件
#include <iostream>
using namespace std;int main() {// 1. 三种初始化方式vector<int> v1;  // 空数组(大小0)vector<int> v2(5);  // 大小为5的数组,默认值0vector<int> v3(3, 10);  // 大小为3的数组,元素都是10(10,10,10)// 2. 动态添加元素(从末尾加,自动扩容)v1.push_back(20);  // v1: [20]v1.push_back(30);  // v1: [20,30]v1.push_back(40);  // v1: [20,30,40]// 3. 重新设置大小(resize)v2.resize(3);  // 原来大小5,现在改为3(只保留前3个元素,默认0→[0,0,0])// 4. 访问元素(和数组一样用[])cout << "v3[1] = " << v3[1] << endl;  // 输出:10cout << "v1[2] = " << v1[2] << endl;  // 输出:40// 5. 遍历元素(两种方式)// 方式1:下标遍历(和C数组一样)cout << "v1元素(下标遍历):";for (int i = 0; i < v1.size(); ++i) {cout << v1[i] << " ";}cout << endl;// 方式2:迭代器遍历(更通用,所有容器都支持)cout << "v3元素(迭代器遍历):";for (auto it = v3.begin(); it != v3.end(); ++it) {cout << *it << " ";  // 迭代器解引用获取元素}cout << endl;// 6. 获取大小cout << "v1大小:" << v1.size() << endl;  // 输出:3return 0;
}

运行结果:

v3[1] = 10
v1[2] = 40
v1元素(下标遍历):20 30 40 
v3元素(迭代器遍历):10 10 10 
v1大小:3

2. 对比C数组

问题C数组C++ vector
大小固定静态数组int a[10]不能改大小,超界危险自动扩容,push_back随便加
内存管理动态数组需malloc(10*sizeof(int)),用完必须free,易泄漏自动申请和释放内存,出作用域自动销毁
扩容麻烦需手动realloc,还可能丢失数据调用resizepush_back自动处理
传递参数需同时传指针和长度(void func(int* a, int len)直接传vector,内部带size()

3. 常用操作

  • 清空元素v.clear()(替代C中手动遍历赋值或free后重新malloc);
  • 删除末尾元素v.pop_back()(替代C中len--,无需手动释放内存);
  • 判断是否为空v.empty()(替代C中if (len == 0));
  • 获取首/尾元素v.front()/v.back()(替代C中a[0]/a[len-1],更直观)。

三、set:自动去重与排序

在C中,要实现“不重复的元素集合”(比如去重后的ID列表),需要先存数组,再手动遍历去重,最后调用qsort排序,步骤繁琐。而set容器天生具备“自动去重”和“自动排序”功能,插入即处理完成。

1. 核心特性:去重+排序

set中的元素不允许重复,且会自动从小到大排序,适合存储需要去重且有序的数据。

#include <set>  // 必须包含的头文件
#include <iostream>
using namespace std;int main() {// 定义一个存储int的setset<int> id_set;// 1. 插入元素(自动去重+排序)id_set.insert(30);id_set.insert(10);id_set.insert(20);id_set.insert(10);  // 重复元素,插入无效// 2. 遍历元素(自动排序)cout << "去重并排序后的ID:";for (auto it = id_set.begin(); it != id_set.end(); ++it) {cout << *it << " ";}cout << endl;  // 输出:10 20 30 // 3. 查找元素(返回迭代器,找不到则等于end())int target = 20;auto it = id_set.find(target);if (it != id_set.end()) {cout << "找到元素:" << *it << endl;  // 输出:找到元素:20} else {cout << "未找到元素:" << target << endl;}// 4. 删除元素id_set.erase(10);  // 删除元素10cout << "删除10后的元素:";for (auto num : id_set) {  // 简化的范围for循环(C++11+)cout << num << " ";}cout << endl;  // 输出:20 30 return 0;
}

运行结果:

去重并排序后的ID:10 20 30 
找到元素:20
删除10后的元素:20 30 

2. 对比C的实现

比如实现“输入5个数字,去重后排序输出”:

  • C语言需要:定义数组→输入→双重循环去重→调用qsort→输出(至少20行代码);
  • C++用set:插入5个数字→遍历输出(不到10行代码)。
// C语言实现去重排序
#include <stdio.h>
#include <stdlib.h>int cmp(const void* a, const void* b) {return *(int*)a - *(int*)b;
}int main() {int arr[5], temp[5];int len = 0;// 输入for (int i = 0; i < 5; ++i) {scanf("%d", &arr[i]);}// 去重for (int i = 0; i < 5; ++i) {int flag = 1;for (int j = 0; j < len; ++j) {if (arr[i] == temp[j]) {flag = 0;break;}}if (flag) {temp[len++] = arr[i];}}// 排序qsort(temp, len, sizeof(int), cmp);// 输出for (int i = 0; i < len; ++i) {printf("%d ", temp[i]);}return 0;
}
// C++ set实现(简洁10倍)
#include <set>
#include <iostream>
using namespace std;int main() {set<int> s;int num;// 输入并插入set(自动去重)for (int i = 0; i < 5; ++i) {cin >> num;s.insert(num);}// 遍历输出(自动排序)for (int n : s) {cout << n << " ";}return 0;
}

四、string:告别char*的字符串处理

C中的char*字符串堪称“bug重灾区”:strcat可能缓冲区溢出,strlen需要遍历计算长度,拼接、截取字符串要手动分配内存……而C++的string类把这些操作全部封装,安全又便捷。

1. 核心特性:像用int一样用字符串

string可以直接赋值、拼接、比较,完全不用关心底层字符数组的内存管理。

#include <string>  // 必须包含的头文件
#include <iostream>
using namespace std;int main() {// 1. 定义和赋值string s1 = "hello";string s2("world");string s3;  // 空字符串// 2. 拼接(直接用+)string s4 = s1 + " " + s2;  // s4 = "hello world"cout << "拼接结果:" << s4 << endl;// 3. 比较(直接用==、>、<)if (s1 == "hello") {cout << "s1等于\"hello\"" << endl;}if (s1 < s2) {  // 按字典序比较(h < w)cout << "s1小于s2" << endl;}// 4. 长度(直接用length()或size())cout << "s4的长度:" << s4.length() << endl;  // 输出:11(包括空格)return 0;
}

运行结果:

拼接结果:hello world
s1等于"hello"
s1小于s2
s4的长度:11

2. 输入输出:解决cin的空格问题

C中scanf("%s", str)和C++中cin >> s都只能读取“不含空格的单词”,遇到空格就停止。getline(cin, s)可以读取一整行(包括空格),完美解决这个问题。

#include <string>
#include <iostream>
using namespace std;int main() {string s1, s2;cout << "输入一个单词(cin):";cin >> s1;  // 输入“hello world”,只读取“hello”cout << "s1 = " << s1 << endl;// 注意:cin读取后,缓冲区会残留换行符,需要清空cin.ignore();  // 清空缓冲区的换行符cout << "输入一行文字(getline):";getline(cin, s2);  // 输入“hello world”,完整读取cout << "s2 = " << s2 << endl;return 0;
}

运行结果:

输入一个单词(cin):hello world
s1 = hello
输入一行文字(getline):hello world
s2 = hello world

3. 常用函数:字符串操作不用愁

  • 截取子串substr(n, m)——从下标n开始,截取m个字符;substr(n)——从下标n截取到末尾(注意:字符串下标从0开始)。

    string s = "abcdef";
    cout << s.substr(1, 3) << endl;  // 从下标1取3个→"bcd"
    cout << s.substr(2) << endl;     // 从下标2取到末尾→"cdef"
    
  • 类型转换to_string(x)——把数字(int、long等)转换成string。

    int num = 123;
    string s = to_string(num);  // s = "123"
    long ln = 456789;
    string s2 = to_string(ln);  // s2 = "456789"
    
  • 查找字符/子串find(str)——返回子串第一次出现的下标,没找到返回string::npos

    string s = "hello world";
    size_t pos = s.find("world");
    if (pos != string::npos) {cout << "找到子串,下标:" << pos << endl;  // 输出:6
    }
    

4. 对比C的str系列函数:安全+简洁

操作C(str系列函数)C++ string
拼接strcat(str1, str2)(可能溢出)s1 + s2(自动扩容,安全)
长度strlen(str)(遍历计算)s.length()(直接返回,O(1))
比较strcmp(str1, str2)(返回0/1/-1)s1 == s2/s1 > s2(直观)
截取手动strncpy+\0(麻烦)s.substr(n, m)(一行搞定)

五、其他常用工具:栈、哈希检查等

除了上述容器,C++还有一些实用工具,能进一步简化代码。

1. 栈(stack):先进后出的操作

stack封装了栈的基本操作(push入栈、pop出栈、top取栈顶),比C中用数组模拟栈更安全(自动检查空栈,避免越界)。

#include <stack>
#include <iostream>
using namespace std;int main() {stack<int> st;// 入栈st.push(10);st.push(20);st.push(30);// 取栈顶(不删除)cout << "栈顶元素:" << st.top() << endl;  // 输出:30// 出栈(删除栈顶)st.pop();cout << "出栈后栈顶:" << st.top() << endl;  // 输出:20// 判空while (!st.empty()) {  // 栈非空时循环cout << st.top() << " ";st.pop();}  // 输出:20 10 return 0;
}

2. contains:检查键是否存在(C++20+)

mapunordered_map在C++20后支持contains(key)函数,直接判断键是否存在,比find更直观。

#include <map>
#include <iostream>
using namespace std;int main() {map<string, int> m{{"a", 1}, {"b", 2}};if (m.contains("a")) {  // 检查是否有键"a"cout << "存在键\"a\"" << endl;}return 0;
}

总结:C转C++,从这些容器开始

从C转向C++,不需要一次性学完所有内容,先掌握map(键值对)、vector(动态数组)、set(集合)、string(字符串)这几个核心容器,就能解决80%的日常编程问题。它们的优势在于:

  • 少写重复代码:排序、去重、内存管理交给STL;
  • 更安全:避免缓冲区溢出、内存泄漏等C中常见bug;
  • 更直观:用+拼接字符串、用[]访问键值对,符合人类思维。
http://www.dtcms.com/a/443520.html

相关文章:

  • 个人网站怎么做app做茶网站
  • VBA中类的解读及应用第二十八讲:为什么要使用类及使用类接口规范
  • Java项目包结构设计与功能划分详解
  • 建设网站的过程wordpress 4.7.5漏洞
  • 办文明网站 做文明网民活动明港seo公司
  • 东莞城乡建设规划官网seo推广是什么
  • 广宁城乡建设网站学剪辑有必要报班吗
  • 教育行业网站怎么做中文建网站
  • 京东商城网站的搜索引擎营销做的案例分析美容网站开发
  • 宁波网站建设托管隆回网站建设制作
  • 行政机关网站建设的意义做暧昧的小视频网站2
  • win11修复右键菜单缺失在此处打开终端
  • linux(sem信号量 + 线程池)
  • 电子商务网站制作步骤wordpress首页加图片
  • 北京做网站哪家公司最好自建站网址
  • C++循环结构详解:从入门到精通
  • 一键搭建网站windows网络工程师含金量高吗
  • 使用C语言制作简易的三子棋游戏
  • 网站营销推广企业高端网站定制的案例
  • 商丘公司做网站用心做的网站
  • 网站建设与管理可以专升本吗wordpress 电影模版
  • 网站设计基本功能怎么制作一个免费的网站模板
  • 18年手机网站开发公司质量管理体系
  • 简约网站首页江门做网站公司开网络公司
  • 体育局网站建设方案刚做还网站第一时间抓取
  • 搭建企业知识库windows10+Ollama+deepseek+ragflower
  • 基于华为openEuler部署my-mind思维导图工具
  • Python学习之Day05学习(定制数据对象,面向对象)
  • 公司网站 备案济南网站营销
  • 算法 | Recursion vs Iteration