【C++ STL之string,tuple,array详解】

本文详细介绍了C++STL中的std::string字符串类,std::tuple元组,以及std::array数组的使用方法,包括初始化、基本操作、比较、拼接和访问修改等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.string字符串

1.简介

在C++的STL(Standard Template Library)中,std::string是一个非常有用的字符串类。它提供了一系列操作字符串的功能,包括字符串的创建、修改、查找、拼接等。本文将详细介绍C++ STL中std::string的使用方法和一些常见操作。

2.头文件及初始化

//头文件
#include<string>
//初始化
//1.使用赋值运算符 = 或拷贝构造函数进行初始化:
string str1 = "Hello";         // 使用赋值运算符 =
string str2(str1);             // 使用拷贝构造函数
string str3 = str2;            // 使用赋值运算符 =
//2.使用字符串字面值进行初始化:
string str ("Hello, World!");   // 使用字符串字面值
//3.使用重复字符进行初始化
string str(5, 'A');             // 使用重复字符
//4.
string str6(str2, 2); //结果为"3456789",截取第三个元素(2对应第三位)到最后
//5.
string str3("12345", 0, 3);//结果为"123" ,从0位置开始,长度为3
//6.
string str4("123456", 5); //结果为"12345" ,长度为5

3.特性

(1)支持比较运算符
string字符串支持常见的比较操作符(>,>=,<,<=,==,!=),支持string与C-string的比较(如 str < ”hello”)。
在使用>,>=,<,<=这些操作符的时候是根据“当前字符特性”将字符按 字典顺序 进行逐一得 比较。字典排序靠前的字符小, 比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小(前面减后面) 同时,string (“aaaa”) <string(aaaaa)。
(2)支持+运算符,代表拼接字符串
string字符串可以拼接,通过"+"运算符进行拼接

string s1;
string s2;`在这里插入代码片`
s1 = "123";
s2 = "456";
string s = s1 + s2;
cout<<s;   //123456

(3)读取字符串时注意事项

int n;
string s;
cin>>n;
getchar();//cin.get()
getline(cin,s);//可正确读入下一行的输入

解释:cin遇到回车停止后,回车还在输入流中,所以需要getchar()或者cin.get()来读取换行符,再用getline()读取。

(4)string和char之间的转换
可以用c_str()来进行转换

string s = "xing ma qi";
char s2[] = s.c_str();

(5)排序

sort(s.begin(),s.end());//按照ASCII码排序

4.基本操作

基本的功能包括
获取字符串长度,插入,删除,替换,查找,大写转小写,提取
(1)获取字符串长度

代码含义
s.length() 或者s.size()返回string对象的字符个数,他们执行效果相同。

(2)插入

代码含义
s.push_back()在末尾插入字符
s.insert(pos,element)在pos位置插入element
s.append(str)在s字符串结尾添加str字符串

(3)删除

代码含义
erase(iterator p)删除字符串中p所指的字符
erase(iterator first, iterator last)左闭右开的区间删
erase(pos, len)删除字符串中从索引位置pos开始的len个字符
clear()删除字符串中所有字符

(4)字符替换

代码含义
s.replace(pos,n,str)把当前字符串从索引pos开始的n个字符替换为str
s.replace(pos,n,n1,c)把当前字符串从索引pos开始的n个字符替换为n1个字符c
s.replace(it1,it2,str)左闭右开替换为str

(5)大写转小写

代码含义
tolower()转小写
toupper()转大写

通过transform进行转换

string s;
transform(s.begin(),s.end(),s.begin(),::tolower);//转换小写
transform(s.begin(),s.end(),s.begin(),::toupper);//转换大写

(6)提取字符串

代码含义
s.sunstr(pos,n)截取从pos索引开始的n个字符

(7)查找
对于查找的函数,为便于理解,这里直接上代码

int main()
{
    string s("dog bird chicken bird cat");
//字符串查找-----找到后返回首字母在字符串中的下标
// 1. 查找一个字符串
    cout << s.find("chicken") << endl;// 结果是:9
// 2. 从下标为6开始找字符'i',返回找到的第一个i的下标
    cout << s.find('i',6) << endl;// 结果是:11
// 3. 从字符串的末尾开始查找字符串,返回的还是首字母在字符串中的下标
    cout << s.rfind("chicken") << endl;// 结果是:9
// 4. 从字符串的末尾开始查找字符
    cout << s.rfind('i') << endl;// 结果是:18因为是从末尾开始查找,所以返回第一次找到的字符



// 5. 在该字符串中查找第一个属于字符串s的字符
    cout << s.find_first_of("13br98") << endl;// 结果是:4---b
// 6. 在该字符串中查找第一个不属于字符串s的字符------先匹配dog,然后bird匹配不到,所以打印4
    cout << s.find_first_not_of("hello dog 2006") << endl; // 结果是:4
    cout << s.find_first_not_of("dog bird 2006") << endl;  // 结果是:9
// 7. 在该字符串最后中查找第一个属于字符串s的字符
    cout << s.find_last_of("13r98") << endl;// 结果是:19
// 8. 在该字符串最后中查找第一个不属于字符串s的字符------先匹配t--a---c,然后空格匹配不到,所以打印21
    cout << s.find_last_not_of("teac") << endl;// 结果是:21
}

二.tuple元组

1.简介

在C++的STL(Standard Template Library)中,std::tuple是一个非常有用的模板类。它提供了一种将多个值组合在一起的方式,类似于一个元组。std::tuple可以用于存储和传递多个不同类型的值,而不需要定义新的数据结构。本文将详细介绍C++ STL中std::tuple的使用方法和一些常见操作。

2. 头文件及初始化

//头文件
#include <tuple>
tuple<Type1, Type2, ..., TypeN> myTuple; // 声明一个空的tuple
tuple<Type1, Type2, ..., TypeN> myTuple(value1, value2, ..., valueN); // 使用给定的值初始化
tuple<Type1, Type2, ..., TypeN> myTuple = make_tuple(value1, value2, ..., valueN); // 使用make_tuple函数创建tuple并赋值

3.访问和修改元素

可以使用以下方式访问和修改tuple中的元素:

get<Index>(myTuple); // 访问指定索引的元素
get<Index>(myTuple) = newValue; // 修改指定索引的元素

4.使用tuple作为函数返回值

tuple可以用作函数的返回值,以便一次返回多个值。例如:

tuple<int, double, string> myFunction() {
    int intValue = 10;
    double doubleValue = 3.14;
    string stringValue = "Hello";
    return make_tuple(intValue, doubleValue, stringValue);
}
int main() {
    auto result = myFunction();
    int intValue = get<0>(result);
    double doubleValue = get<1>(result);
    string stringValue = get<2>(result);
    // 使用返回的值进行后续操作
    // ...
    return 0;
}

上述示例代码中,我们定义了一个函数myFunction(),它返回一个tuple,其中包含一个整数、一个双精度浮点数和一个字符串。
在main()函数中,我们调用myFunction()并使用get(tuple)来访问返回的元组中的值。

三.array数组

1.简介

在C++的STL(Standard Template Library)中,std::array是一个非常有用的容器类。它提供了一种固定大小的数组,可以在运行时进行访问和修改。std::array的大小在编译时确定,并且具有固定的内存布局。本文将详细介绍C++ STL中std::array的使用方法和一些常见操作。

2.头文件及初始化

#include <array>
//可以使用以下方式声明和初始化一个array对象:
array<Type, Size> myArray; // 声明一个空的array
array<Type, Size> myArray = {element1, element2, ..., elementN}; // 使用已有的元素初始化array
array<Type, Size> myArray = {value}; // 使用单个值初始化array,会将所有元素初始化为该值
//声明一个大小为100的int型数组,初始值均为0(初始值与默认元素类型等效)
array<int, 100> a{};
//声明一个大小为100的int型数组,初始化部分值,其余全部为0
array<int, 100> a{1, 2, 3};

对于一些高级数据类型

array<string, 2> s = {"ha", string("haha")};
array<node, 2> a;

3.元素的访问

(1)下标访问

array<int, 4> a = {1, 2, 3, 4};
for(int i = 0; i < 4; i++) 
    cout << a[i] << " \n";

(2)智能指针

for(auto i : a)
    cout << i << " ";

(3)迭代器访问

auto it = a.begin();
for(; it != a.end(); it++) 
    cout << *it << " ";

(4)at()函数访问

array<int, 4> a = {1, 2, 3, 4};
int res = a.at(1) + a.at(2);
cout << res << "\n";

(5)get方式访问
将a数组下标为1位置处的值改为x

get<1>(a) = x;

4.基本操作

代码含义
begin()返回容器中第一个元素的访问迭代器(地址)
end()返回容器最后一个元素之后一个位置的访问迭代器(地址)
rbegin()返回最后一个元素的访问迭代器(地址)
rend()返回第一个元素之前一个位置的访问迭代器(地址)
size()返回容器中元素的数量,其值等于初始化 array 类的第二个模板参数N
empty()判断容器是否为空
at(n)返回容器中 n 位置处元素的引用,函数会自动检查 n 是否在有效的范围内,如果不是则抛出 out_of_range 异常
front()返回容器中第一个元素的直接引用,函数不适用于空的 array 容器
back()返回容器中最后一个元素的直接引用,函数不适用于空的 array 容器。
data()返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能
fill(x)将 x 这个值赋值给容器中的每个元素,相当于初始化
array1.swap(array2)交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型

对于部分功能给出代码帮助理解
下面是data()函数在array中的用法示例

#include <iostream>
#include <array>
int main() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    int* ptr = arr.data(); // 获取指向数组数据的指针
    for (int i = 0; i < arr.size(); i++) {
        std::cout << ptr[i] << " "; // 输出数组元素
    }
    std::cout << std::endl;
    return 0;
}

排序

sort(a.begin(), a.end());
<think>好的,用户想了解C++模板元编程和泛型的概念、用法及相关内容。我需要先回顾一下相关的引用资料,确保回答准确。 首先,引用[1]和[2]提到了类模板和函数模板的定义,以及实例化的过程。引用[3]讨论了非类型模板参数和模板特化,而引用[4]则展示了类模板的使用示例。用户的问题集中在模板元编程和泛型编程,可能需要更深入的解释,特别是元编程部分。 泛型编程是通过模板实现代码的通用性,如容器和算法。而模板元编程(TMP)则是在编译期进行计算,使用模板、特化和递归等技术。需要区分这两者的不同,并举例说明。 用户可能需要基础概念的解释,比如模板的类型参数和非类型参数,模板特化,以及如何在实际中使用这些特性。此外,模板元编程的高级主题如编译期计算、类型萃取等也需要涵盖。 要注意使用用户提供的引用中的例子,比如类模板Vector和Array,来说明实例化和使用过程。同时,需要确保术语准确,如模板参数列表、实例化的条件等。 可能还需要提到模板的优缺点,比如编译时间增加,但运行效率高。此外,模板元编程的常见应用场景,如Boost库中的组件,可以增强实用性。 用户的问题可能隐含对实际应用和代码示例的需求,因此需要提供具体的代码片段,比如斐波那契编译期计算、类型萃取等。同时,要确保代码符合C++标准,并解释其工作原理。 最后,生成的相关问题需要覆盖概念、应用、优化和常见问题,帮助用户进一步学习。要检查引用标记是否正确,确保引用资料与内容对应。</think>### C++模板元编程与泛型编程详解 #### 一、泛型编程基础 泛型编程通过模板实现**数据类型无关的代码复用**,核心是**编译期多态**。其特点包括: 1. 使用`template`关键字定义模板 2. 支持**类型参数化** 3. 编译时生成具体代码 **类模板定义示例**: ```cpp template<class T, size_t N=10> // 非类型模板参数N[^3] class Vector { public: T& operator[](size_t pos) { assert(pos < _size); return _pData[pos]; } private: T* _pData; size_t _size = N; // 直接使用非类型模板参数 }; ``` #### 二、模板元编程(TMP)进阶 模板元编程是**在编译期执行计算的编程范式**,核心特征: 1. 使用模板特化实现条件判断 2. 递归模板实例化实现循环 3. 类型作为计算的主要对象 **经典示例:编译期斐波那契数列**: ```cpp template<int N> struct Fib { static const int value = Fib<N-1>::value + Fib<N-2>::value; }; template<> struct Fib<0> { static const int value = 0; }; template<> struct Fib<1> { static const int value = 1; }; // 使用:Fib<10>::value 编译时计算结果为55 ``` #### 三、关键机制对比 | 特性 | 泛型编程 | 模板元编程 | |---------------|---------------------------|---------------------------| | 主要目标 | 代码复用 | 编译期计算 | | 执行时机 | 运行时实例化 | 完全编译期执行 | | 核心机制 | 模板实例化[^2] | 模板特化+递归实例化 | | 典型应用 | STL容器/算法 | 类型萃取/编译期优化 | #### 四、模板特化实践 1. **全特化**: ```cpp template<> class Vector<bool> { // 对bool类型特殊优化 // 使用位压缩存储... }; ``` 2. **偏特化**: ```cpp template<class T> class Vector<T*> { // 针对指针类型的特化版本 // 特殊的内存管理... }; ``` #### 五、类型萃取技术 通过模板元编程实现类型特征检测: ```cpp template<class T> struct is_pointer { static const bool value = false; }; template<class T> struct is_pointer<T*> { static const bool value = true; }; // 使用:is_pointer<int*>::value == true ``` #### 六、现代C++改进 1. **可变参数模板**: ```cpp template<class... Ts> class Tuple {}; // 支持任意数量类型参数 Tuple<int, string, double> t; ``` 2. **constexpr函数**: ```cpp constexpr int factorial(int n) { return n <= 1 ? 1 : n * factorial(n-1); } // 编译时计算:int x = factorial(5); // 120 ``` #### 七、最佳实践原则 1. 优先使用`typename`而非`class`声明类型参数 2. 模板定义与实现应放在头文件中[^3] 3. 避免过度复杂的模板元编程(影响编译速度) 4. 结合`static_assert`进行类型约束: ```cpp template<class T> void func(T val) { static_assert(is_arithmetic<T>::value, "T must be arithmetic type"); } ```
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马户一口吞不下又鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值