STL基础&string容器

1 STL初识

1.1 STL的诞生

在C++发展早期,程序员在不同的项目中需要反复编写相似的数据结构和算法。重复开发带来以下问题:

代码冗余:每个项目都要重新实现基本数据结构和算法

维护困难:不同人编写的代码风格不一致,难以维护

效率低下:不同实现可能导致性能不稳定,难以优化

为了解决这些问题,1994年由Alexander Stepanov领导的团队开发了STL。

1.2 STL基本概念

  • STL(标准模板库,Standard Template Library)
  • 由多个模块组成,包括容器 (Containers)、算法 (Algorithms)和迭代器(Iterators),加上一些额外的工具
  • 容器算法 之间通过迭代器进行无缝衔接
  • STL几乎所有的代码都采用了模板类或者模板函数

1.3 STL核心组件

STL主要由六大部分 组成:容器算法迭代器适配器函数对象配置器

1.容器(Containers)

提供多种数据结构,方便存储和管理数据。常见容器包括:

容器类型 特点 常见容器
序列式容器 按照顺序存储数据 vector,deque,list,array
关联式容器 以键值对存储数据,自动排序 set,map,multiset,multimap
无序容器 使用哈希表存储数据,查找快 unordered_set,unordered_map

2. 算法(Algorithms)

提供大量常见算法,如排序、查找、修改等,使用时结合迭代器。

常见算法:

  • 修改类:fill()、replace()、copy()
  • 非修改类:find()、count()
  • 排序类:sort()、stable_sort()
  • 数值类:accumulate()(求和)、inner_produce()(内积)

3. 迭代器(Iterators)

用于遍历容器中的元素,类似于指针,但更灵活,适用于STL容器。

迭代器类别 适用容器 功能
输入迭代器 istream_iterator 只能读取
输出迭代器 ostream_iterator 只能写入
前向迭代器 forward_list 只能前进
双向迭代器 list,set,map 可前进和后退
随机访问迭代器 vector,deque,array 可随机访问

4. 适配器(Adapters)

用于改变容器、迭代器或函数行为的工具。例如:

  • 容器适配器(stackqueuepriority_queue)
  • 迭代器适配器(reverse_iterator)
  • 函数适配器(bind()mem_fn())

函数对象(Functors 仿函数)

重载的类,可以像函数一样被调用。可作为算法的某种策略。

1. 适配器(Allocators)

STL提供的内存管理机制,用于分配和释放内存。

1.4 STL的特点

  • 泛型编程
  • 高效
  • 模块化
  • 代码复用

1.2 容器算法迭代器初识

以STL中常见的容器vector为例,可以理解为"可变大小的数组",能够动态调整大小,支持随机访问。

1.5.1 vector 存放内置数据类型

下面用一个简单的例子,结合vector、算法sort和迭代器,看一下STL用法。

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm> //引入算法库
 
using namespace std;

int main(){
    //创建一个vector容器,存储int类型数据
    vector<int> v = { 5,2,8,1,3 };
    //使用算法sort对vector进行排序
    sort(v.begin(), v.end()); //排序从小到大
    //使用迭代器遍历vector
    cout << "排序后的数据:";
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";//迭代器解引用获取元素
    }
    cout << endl;
    return 0;
}

最后输出的内容:1 2 3 5 8

在上述代码中有几条代码需要讲解:
v.begin()指向数组起始位置,但v.end()并非指向末尾,而是指向"最后一个元素的下一个位置",所以v.end()-1 才是最后一个元素。
sort(v.begin(), v.end());

为什么会升序排序?原因是std::sort默认使用operator<进行比较,默认行为是从小到大排序。那么如果想降序排列怎么办?只需要这样写就可以
sort(v.begin(), v.end(),greater<int>());

或者这样写也可以
sort(v.begin(), v.end(), [](int a, int b) {return a > b; });

1.5.2 vector存放自定义数据类型

使用vector存储自定义数据类型(如class)时,需要注意:

  1. 存储对象时,类需要支持拷贝 (默认可拷贝)

  2. 若要排序,需要提供比较规则

  3. 可以存储对象本身或指针

示例:

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;

//定义Person类
class Person {
public:
 string m_Name;
 int m_Age;
 //构造函数
 Person(string name, int age) :m_Name(name), m_Age(age) {}
 //显示信息
 void show() const {
  cout << "姓名:" << m_Name << ",年龄:" << m_Age << endl;
 }
};

int main(){
 //创建Vector存储Person对象
 vector<Person> people;
 //添加元素
 people.push_back(Person("张三", 25));
 people.push_back(Person("李四", 29));
 people.push_back(Person("王五", 27));
 //遍历输出
 cout << "初始数据:" << endl;
 for (vector<Person>::iterator it = people.begin(); it != people.end(); it++) {
  it->show();
 }
 //按照年龄升序排列
 sort(people.begin(), people.end(), [](const Person& a, const Person& b) {
  return a.m_Age < b.m_Age; });
 //排序后输出
 cout << "按年龄升序排序后:" << endl;
 for (vector<Person>::iterator it = people.begin(); it != people.end(); it++) {
  it->show();
 }
 
 return 0;
}

这里的对象很小,所以直接存储对象没有问题。如果Person对象很大,或者不希望拷贝对象,可以存储Person* 指针:
vector<Person*> people; people.push_back(new Person("张三", 25)); people.push_back(new Person("李四", 30));

但要记得这是指针,要delete释放内存!

1.5.3 vector容器嵌套容器

Vector 可以存储任何类型的数据,包括另一个vector,也就是嵌套容器。

简单的示例:vector<vector<int>>

cpp 复制代码
#include<iostream>
#include<vector>
 
using namespace std; 

int main() {
 //定义一个二维vector,相当于二维数组
 vector<vector<int>> matrix = {
  {1,2,3},
  {4,5,6},
  {7,8,9}
 };
 //遍历输出
 for (vector<vector<int>>::iterator it = matrix.begin(); it != matrix.end(); it++) {
  //(*it)---> vector<int>
  for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++){
   cout << *vit << " ";
  }
  cout << endl;
 }

 return 0;
}

代码解析:

1.vector<vector<int>> matrix;

定义一个存储vector<int>vector,形成二维数据结构。

  1. 初始化嵌套vector

直接使用{}填充数据

  1. 遍历嵌套vector 第一层遍历行 vector<int>

第二层遍历列 int

在示例中插入的是规则矩阵,但可以存放不同长度的vector。如我插入一组数据matrix.push_back({ 2,3 });
matrix.push_back({ 4,5,6,7 });

这都是没有问题的。

vector支持任意类型嵌套,可以作为灵活的数据结构!如:

嵌套vector 作用
vector<vector> 存储二维数据
vector<vector> 存储字符串表
vector<vector> 存储对象表

string容器

2.1 string基本概念

string是C++STL中的字符串容器。本质上是一个封装了char*的动态字符串类 ,管理堆区分配的字符串数组,提供一系列字符串操作方法。

在底层,std::string维护了几个重要成员:

  • char*指针(指向存储字符串的动态数组)
  • 长度size_t size(字符串的当前大小)
  • 容量 size_t capacity(字符串当前分配的最大空间)
  • 字符存储区(在堆区分配的存储空间)

特点:

  1. 自动管理内存
  2. 动态扩展
  3. 提供丰富的成员函数
  4. 兼容C风格字符串
  5. STL兼容性

2.2 string构造函数

1. 默认构造(空字符串)

创建一个空字符串,长度为0,但仍可以动态扩展。

cpp 复制代码
std::string str;  
std::cout << "空字符串:\"" << str << "\"" << std::endl;

输出内容:

2. C风格字符串构造

直接使用C语言的const char*(char[])初始化std::string

cpp 复制代码
std::string  str1("Hello,World!");
std::cout << "字符串:" << str1 << std::endl;

输出内容:

3. 拷贝构造

用已有的std::string创建新字符串,内容完全相同。

cpp 复制代码
std::string  str1("Hello,World!");
string str2(str1);
cout << "拷贝构造:" << str2 << endl;  

输出内容:

4.指定长度的字符串构造

使用char* 创建字符串,但只取前n个字符。

cpp 复制代码
string str3("Hello,World!", 5);
cout << "部分截取:" << str3 << endl;  

输出内容:

5. 重复字符构造

使用n个相同字符初始化string

cpp 复制代码
string str4(10, 'A');
cout << "重复字符:" << str4 << endl; 

输出内容:

6. 迭代器构造(从容器中取一部分字符串)

使用迭代器从original中截取部分内容。

cpp 复制代码
string original = "ABCDEFG";
string str5(original.begin() + 2, original.begin() + 5);
cout << "部分字符串:" << str5 << endl;  

输出内容:

7. 移动构造

std::move允许std::string 进行资源转移。

cpp 复制代码
string tempVar = "Hello";
string str6 = move(tempVar);
cout << "移动后的tempVar:" << tempVar << endl;
cout << "移动到str6:" << str6 << endl; 

输出内容:

2.3 string赋值操作

常见的赋值操作包括:

  • operator =赋值运算符
  • assign() 赋值函数

1. 赋值运算符operator=

可以将字符串赋值给string对象,有几种不同的情况:

(1) 直接赋值C风格字符(char*)

将C风格字符串"Hello,World!"赋值给string

cpp 复制代码
string str;
str = "Hello,World!";
cout << str << endl; 

输出内容:

(2) 赋值给另一个string

str2拷贝str1的内容,不会影响str1

cpp 复制代码
string str1 = "Hello";
string str2;
str2 = str1;
cout << str2 << endl;  

输出内容:

(3) 赋值单个字符

string支持单个字符赋值(char a='A'),它会被自动转换为string("A")

cpp 复制代码
string str3;
str3 = 'A';
cout << str3 << endl;  

输出内容:

(4) 使用move()进行移动赋值

str4的数据转移到str5,避免拷贝,提高效率。

cpp 复制代码
string str4 = "Hello";
string str5;
str5 = move(str4);
cout << "str4: " << str4 << endl;  // str1 变为空
cout << "str5: " << str5 << endl;  // str2 获得 "Hello"   

输出内容:

2. assign()赋值函数

assign()string专门提供的赋值函数,可以灵活地从字符串字符迭代器范围等方式进行赋值。

(1) 赋值C风格字符串

assign()作用和operator = 一样,但更灵活。

cpp 复制代码
string str;
str.assign("Hello,World!");
cout << str << endl;  

输出内容:

(2) 赋值部分C风格字符串

char* 开头取n个字符赋值。

cpp 复制代码
string str1;
str.assign("Hello,World!", 5);
cout << str1 << endl;   

输出内容:

(3) 赋值另一个string

等价于str4=str3

cpp 复制代码
string str3 = "Hello";
string str4;
str4.assign(str3);
cout << str4 << endl;  
输出内容:  
    
![image.png](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/7e9756c9abad4191890e30d39c7f6d1d~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgRXRob25f546L:q75.awebp?rk3s=f64ab15b&x-expires=1744550920&x-signature=vojygfc3L3qxOKJ3w9Fg0TM9wYE%3D)  
#### (4) 赋值重复字符
创建5个'A'组成的字符串。  
```cpp
string str5;
str5.assign(5, 'A');
cout << str5 << endl;

输出内容:

(5) 赋值迭代器范围

使用迭代器范围截取部分字符串赋值。

cpp 复制代码
string str6 = "ABCDEFG";
string str7;
str7.assign(str6.begin() + 2, str6.begin() + 5);
cout << str7 << endl;

输出内容:

assign()函数原型

cpp 复制代码
string& assign(const string & str);           // 赋值另一个 string
string& assign(const string & str, size_t pos, size_t len = npos); // 截取部分赋值
string& assign(const char* s);               // 赋值 C 风格字符串
string& assign(const char* s, size_t n);     // 取 C 字符串的前 n 个字符
string& assign(size_t n, char c);            // 赋值 n 个字符 c
template <class InputIterator>
string& assign(InputIterator first, InputIterator last); // 迭代器范围赋值  

2.4 string字符串拼接

在C++string容器中,字符串拼接有多种方式,主要包括:

  1. 使用+运算符
  2. 使用+=运算符
  3. 使用append()函数

1.使用+运算符

+用于拼接两个字符串,可以拼接stringchar*,但不能charstring直接相加。

示例:

cpp 复制代码
string str1 = "I";
string str2 = " love";
string result1 = str1 + str2; //拼接两个字符串
cout << result1 << endl;

string result2 = result1 + " you!";//拼接string和C字符串
cout << result2 << endl;   

输出结果:

注意:string不能直接拼接单个字符。

错误示例:

cpp 复制代码
string result3 = "Hello" + 'A';
cout << result3 << endl;  

输出结果:

为什么?这是因为代码中存在类型不匹配和指针运算(指针偏移)问题。

问题分析:

  1. "Hello"的类型:"Hello"是一个C风格字符串(const char*类型)。
  2. 'A'的类型:'A'是一个字符(char类型),其ASCll值为65。
  3. "Hello"+'A'实际上等价于:const char* ptr ="Hello"+65;

也就是说,它让"Hello"的指针向后移动了65个字节,但"Hello"实际上只有6个字节(包括\0),因此访问到了随机的内存地址,导致了未定义行为(可能输出Fancyptr或者是其他的值,也可能崩溃)

正确做法:
string result3 =string("Hello")+'A'; //显示转换为string再拼接

或者
string result3 = "Hello"+string(1,'A');//先把'A'变成string再拼接

2.使用+=运算符

+=直接在原字符串上追加内容,可以拼接stringchar*char

示例:

cpp 复制代码
string str = "Closed off";
str += " from love"; //拼接C风格字符串
cout << str << endl;
str += '!';//追加单个字符
cout << str << endl;   

输出内容:

注意事项:不能拼接数字类型。

错误示范:str += 123;

那么会输出什么?

为什么会输出一个'{'?

关键问题:

123是整数(int),但stringoperator+=没有定义直接接收int作为参数。因此,C++试图找到一个兼容的重载,但没有匹配的string::operator+=(int)。隐式转换发生了,int被转换成char,而char(123)的ASCll码对应的字符是'{'。

正确做法:
str += to_string(123); //先转换为字符串

输出内容:

不要忘记头文件#include<string>

3.使用append()函数

append()适用于更复杂的拼接需求,支持拼接部分字符串、指定数量字符等。

  1. 追加整个字符串
cpp 复制代码
string str = "I didn't";
str.append(" need the pain");
cout << str << endl;

输出内容:

  1. 追加部分字符串
cpp 复制代码
string str1 = "Once or twice";
str1.append(" was enough and", 11);//只追加前11个字符
cout << str1 << endl;  

输出内容:

  1. 追加重复字符
cpp 复制代码
string str2 = "and it was all vain";
str2.append(3, '!');//追加3个'!'
cout << str2 << endl;    

输出内容:

  1. 追加另一个string的部分内容
cpp 复制代码
string str3 = "Time starts to";
string str4 = " pass before";
str3.append(str4, 0, 5);//追加str4的前5个字符
cout << str3 << endl;

输出内容:

string::append()函数原型

cpp 复制代码
string& append(const string & str); // 追加整个字符串
string& append(const string & str, size_t subpos, size_t sublen); // 追加 str 的一部分
string& append(const char* s); // 追加 C 风格字符串
string& append(const char* s, size_t n); // 追加 C 字符串前 n 个字符
string& append(size_t n, char c); // 追加 n 个字符 c
template <class InputIterator>
string& append(InputIterator first, InputIterator last); // 追加迭代器范围内容 

2.5 string查找和替换

在C++string容器中,我们可以使用一系列成员函数来查找子字符串的位置,并进行替换。

1.find()--查找子字符串

find()用于查找子字符串在当前string对象中的起始位置。
函数原型

cpp 复制代码
size_t find(const string & str, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t find(char ch, size_t pos = 0) const;    

str/s:要查找的字符串或字符
pos:从字符串的pos位置 开始查找(默认为0)

返回值:

  • 找到:返回子串第一个匹配字符的索引
  • 未找到:返回string::npos
    示例
cpp 复制代码
string str = "Before you know it you're frozen";
//查找子字符串"know"
size_t pos = str.find("know");
if (pos != string::npos)
 cout << "找到\"know\",位置:" << pos << endl;
else
 cout << "未找到\"know\"" << endl;
//查找字符'o',从索引5开始查找
pos = str.find('o', 5);
cout << "找到'o',位置:" << pos << endl;  

输出结果

在上述例子有看到使用的类型是size_t,那么这个是否可以替换为int?那就要先说一说它们之间的区别:

  1. size_t是无符号整数类型,通常表示内存大小、数值索引等非负值。
  2. int是有符合整数,可以存储负数、范围更小。

那么可以替换吗?

也不建议。虽然在小型程序中,如果没有太大的字符串(最大索引不超过int范围),那么可能不会导致错误。如果找到了,那没什么问题,但若没找到,find()函数返回的是std::string::npos,是一个特殊的常量,它的类型是size_t,通常是一个非常大的无符号整数,在32为系统通常是(2^32-1),其二进制表示与-1的二进制补码相同。那么如果用int回被表示成-1。在64位系统,如果赋值给int,会导致溢出,结果是未定义的。

2. rfind()--逆向查找

find()相同,但从字符串的末尾向前查找,返回最后一次出现的位置。

示例

cpp 复制代码
string str1 = "But something";
size_t pos1 = str1.rfind('n');
cout << "最后一次'n'出现的位置:" << pos1 << endl;

输出

3.find_first_of()--查找多个字符中的第一个匹配项

查找字符串中任意一个字符首次出现的位置

示例

cpp 复制代码
string str2 = "happened for";
size_t pos2 = str2.find_first_of("pe");
cout << "字符 'p' 或 'e' 第一次出现的位置:" << pos2 << endl; 

输出

4.find_last_of()--逆向查找多个字符

查找字符串中任意一个字符最后一次出现的位置。

示例

cpp 复制代码
string str3 = "the very firt time with you";
size_t pos3 = str.find_first_of("ry");
cout<<"字符 'r' 或 'y' 最后一次出现的位置: " << pos3 << endl;  

输出

5. replace()--替换子字符串

可以用新字符串替换已有字符串的某部分。
函数原型

cpp 复制代码
string& replace(size_t pos, size_t len, const string & str);
string& replace(size_t pos, size_t len, const char* s); 
  • pos:要替换的起始位置
  • len:要替换的长度
  • str/s:用于替换的新字符串

示例

cpp 复制代码
string str4 = "My liver melted to the ground";
//替换"liver"为"heart"
str4.replace(str4.find("liver"), 5, "heart");
cout << str4 << endl; 

输出

6. erase()--删除子字符串

可以删除string中的某部分内容
函数原型
string& erase(size_t pos = 0, size_t len = npos);

  • pos:删除的起始位置
  • len:删除的字符数(默认为npos,即删除到末尾)

示例

cpp 复制代码
string str5 = "Founddd something true";
str5.erase(5, 2);
cout << str5 << endl;   

输出

2.6 string字符串比较

在C++中,string提供了多种比较方式。主要比较方式包括:

  1. 使用==、!=、<、>等运算符
  2. 使用compare()函数进行字符串比较

1.运算符比较

C++string类重载了"==、!=、<、>、<=、>="这些运算符,比较方式如下:

  • 按ASCll码顺序逐字符比较
  • 若某个字符不同,则比较ASCll码的大小
  • 若前缀相同,则短字符串小于长字符串。

示例

cpp 复制代码
//运算符比较
string str1 = "apple";
string str2 = "banana";
string str3 = "apple";
//比较相等
cout << (str1 == str2) << endl; //0(false)
cout << (str1 == str3) << endl; //1(true)
//比较不相等
cout << (str1 != str2) << endl; //1(true)
//大小比较(按ASCll码表顺序)
cout << (str1 < str2) << endl; //1(true)
cout << (str1 > str2) << endl; //0(false)    

输出

2. compare()方法

string::compare()方法提供了更灵活的字符串比较,它返回一个整数值:

  • 0:两个字符串相等
  • <0:当前字符串小于目标字符串
  • >0:当前字符串大于目标字符串

compare()语法:
int compare(const string & str) const;
int compare(size_t pos, size_t len, const string & str) const;
int compare(size_t pos, size_t len, const string & str, size_t subpos, size_t sublen) const;

1. 直接比较两个字符串:
cpp 复制代码
string str4 = "stand";
string str5 = "apart";
string str6 = "stand";
cout << str4.compare(str5) << endl;//正数
cout << str4.compare(str6) << endl;//0
cout << str5.compare(str4) << endl;//负数  

输出

2.只比较字符串的一部分
cpp 复制代码
string str7 = "abcdef";
string str8 = "cde";
// 比较 str7[2] 开始的3个字符 ("cde") 和 str8 ("cde")
cout << str7.compare(2, 3, str8) << endl;  // 0,相等
// 比较 str7[2] 开始的3个字符 ("cde") 和 "cdf"
cout << str7.compare(2, 3, "cdf") << endl; // 负数,因为 'e' < 'f' 

输出

2.7 string字符串访问和修改

1.访问字符串中的字符

1.使用[]下标访问

string允许像数组一样使用[]访问字符:

cpp 复制代码
string str = "parse";
cout << str[0] << endl; //p
cout << str[4] << endl; //e                                              

输出


[]不会进行范围检查,如果访问超出范围,可能会导致未定义行为。

2.使用at()方法

at()方法与[]类似,但它会检查索引是否超出范围,如果超出,则抛出out_of_range异常。

cpp 复制代码
string str = "parse";
cout << str.at(1) << endl;//a
cout << str.at(10) << endl;//抛出异常

输出

异常:_Xout_of_range("invalid string position");

3.访问首尾字符
cpp 复制代码
string str = "parse";
cout << "首字符:" << str.front() << endl;
cout << "尾字符:" << str.back() << endl;  

输出

2.修改字符串

使用[]at()修改字符。

cpp 复制代码
string str = "parse";
str[0] = 'H';//修改第一个字符
str.at(4) = 'h';//使用at()修改
cout << str << endl;

输出

2.8 string插入和删除

1.插入字符

insert(pos,string)
insert(pos,string)方法用于在pos位置插入字符串:

cpp 复制代码
string str = "thoug";
str.insert(5, "ht");//在索引5处插入"ht"
cout << str << endl;

输出


insert(pos,n,char)

pos位置插入n个相同字符:

cpp 复制代码
string str = "thought";
str.insert(7, 3, '!');
cout << str << endl; 

输出

2.删除字符

erase(pos,len)

pos开始删除len个字符:

cpp 复制代码
string str1 = "Just do it";
str1.erase(4, 6);//从索引4开始删除6个字符
cout << str1 << endl;

输出


pop_back()

删除字符串的最后一个字符:

cpp 复制代码
string str2 = "Just do it!";
str.pop_back();//删除最后一个字符
cout << str << endl;  

输出

2.9 获取string子串

1.substr()方法

函数原型:
string substr(size_t pos = 0, size_t len = npos) const;

  • pos:子串的起始位置
  • len:要截取的字符数量(默认npos表示截取到末尾)
  • 返回值:返回指定范围的新字符串,不会修改原字符串

2.substr()基本用法

示例1:获取指定范围的子串

cpp 复制代码
string str = "Hello, World!";
string sub1 = str.substr(7, 5); //从索引7开始,截取5个字符
cout << sub1 << endl; //World

输出

示例2:截取从某个位置到结尾的子串

如果不提供len,则默认从pos开始一直截取到字符串末尾。

cpp 复制代码
string str = "C++ STL is powerful";
string sub2 = str.substr(6); //从索引6开始,一直到末尾
cout << sub2 << endl; //STL is powerful 

输出

示例3:获取整个字符串(等于拷贝)

如果pos =0,且len = npos,等价于复制整个字符串:

cpp 复制代码
string str = "Hello,C++!";
string copy_str = str.substr(); //复制整个字符串
cout << copy_str << endl;

输出

3.substr()find()结合使用

可以先使用find()定位子串的位置,再用substr()提取。

cpp 复制代码
string str = "Welcome to C++ programming";
//找到C++在字符串中的位置
size_t pos = str.find("C++");
//提取"C++"及后面的内容
string sub = str.substr(pos);
cout << sub << endl;

输出

相关推荐
无 证明2 小时前
【C++】类和对象 (第一弹)
开发语言·c++·算法
疾跑哥布林升级版4 小时前
C++---day7
开发语言·c++·算法
程序员老茶4 小时前
C++:函数
开发语言·c++
郭涤生4 小时前
Chapter 7: Compiling C++ Sources with CMake_《Modern CMake for C++》_Notes
c++·笔记·软件构建
fakerth5 小时前
计算机面试八股(自整)
c++·面试
双叶8365 小时前
(51单片机)矩阵按键密码锁表白(C语言代码编撰)(矩阵按键教程)(LCD1602浅教程)
c语言·开发语言·c++·算法·游戏·矩阵·51单片机
海棠蚀omo5 小时前
C++笔记-string(下)
开发语言·c++·笔记
天堂的恶魔9465 小时前
C++ —— 文件操作(流式操作)
c++
dora7 小时前
逼格提起来,使用curl发送网络请求
android·c++
yy_xzz7 小时前
基于条码数据生成校验密码的C++实现方案
开发语言·c++