C++ string 部分功能详解:迭代器、初始化与常用函数

在 C++ 中,string是处理字符串的核心容器,它封装了丰富的接口来简化字符串操作。本文将围绕string迭代器访问、初始化方式、容量调整(reserve)、反转(reverse) 四大核心功能展开,结合可直接运行的代码和结果验证建议,帮你快速掌握string的实用技巧。

一、迭代器与范围 for:遍历 string 的两种核心方式

string作为 STL 容器的一种,支持迭代器(类似指针的访问工具)和范围 for 两种遍历方式,所有的STL容器都可以用以上两种方式遍历,其中范围 for 的底层本质就是迭代器。下面通过代码详细演示两者的用法。

1.1 迭代器遍历:灵活控制访问过程

迭代器的核心作用是 "指向容器元素",支持*解引用获取值、++移动到下一个元素,适用于所有 STL 容器(如vectorlist等)。注意 :原文代码存在语法错误(如#include<iostrean漏写mmainO错写括号、cout符号错误),以下是修正后的可运行代码:

cpp

复制代码
#include <iostream>  // 修正:补充<iostream>完整头文件
#include <string>
using namespace std;  // 修正:添加分号

int main() {
    string s = "asjhjksd";  // 待遍历的字符串
    cout << "原字符串:" << s << endl;

    // 方式1:显式声明迭代器类型(string::iterator)
    string::iterator it = s.begin();  // begin()获取指向第一个元素的迭代器
    cout << "显式迭代器遍历:";
    while (it != s.end()) {  // end()获取指向"最后一个元素的下一个位置"的迭代器
        cout << *it << " ";  // 解引用获取当前元素
        it++;  // 移动到下一个元素
    }
    cout << endl;

    // 方式2:用auto简化迭代器类型(推荐)
    // 修正:auto自动推导为string::iterator,避免长类型书写
    cout << "auto简化迭代器遍历:";
    for (auto it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

1.2 范围 for:简化遍历的 "语法糖"

范围 for 专门用于 "遍历容器中所有元素",无需手动控制迭代器的开始和结束,语法更简洁。其底层逻辑与迭代器完全一致,遍历过程是s的元素逐个赋值给ch

关键细节:如何用范围 for 修改字符串?

若直接写for (auto ch : s)ch是元素的 "拷贝",修改ch不会影响原字符串;若在ch前加&(引用),则ch直接关联原字符串的元素,支持修改。

cpp

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

int main() {
    string s = "asjhjksd";
    cout << "修改前:" << s << endl;

    // 1. 普通范围for(仅遍历,不修改)
    cout << "普通范围for遍历:";
    for (auto ch : s) {
        cout << ch << " ";
    }
    cout << endl;

    // 2. 引用型范围for(支持修改原字符串)
    for (auto& ch : s) {  // 关键:添加&,ch成为原元素的引用
        ch = toupper(ch);  // 将小写字母转为大写
    }
    cout << "引用修改后:" << s << endl;  // 输出:ASJHJKSD

    return 0;
}

结果验证建议(图片内容)

运行上述两段代码后,截图应包含:

  • 原字符串输出(如asjhjksd);
  • 显式迭代器与 auto 迭代器的遍历结果(如a s j h j k s d );
  • 引用型范围 for 修改后的大写字符串(如ASJHJKSD)。

二、反向迭代器与传统访问:更多遍历选择

除了正向遍历,string还支持反向迭代器(从后往前遍历)数组式访问(用 [] 运算符),满足不同场景需求。

2.1 反向迭代器:从后往前遍历

反向迭代器通过rbegin()(指向最后一个元素)和rend()(指向 "第一个元素的前一个位置")控制范围,++操作实际是 "向前移动"。

cpp

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

int main() {
    string s = "asjhjksd";
    cout << "正向遍历:";
    for (auto ch : s) cout << ch << " ";
    cout << endl;

    // 反向迭代器遍历
    cout << "反向遍历:";
    auto rit = s.rbegin();  // auto推导为string::reverse_iterator
    while (rit != s.rend()) {
        cout << *rit << " ";  // 依次输出:d s k j h j s a
        rit++;  // 反向迭代器的++是"向前移动"
    }
    cout << endl;

    return 0;
}

2.2 传统数组式访问:借助 [] 运算符重载

string重载了[]运算符,允许像访问数组一样通过 "索引" 获取元素(索引从 0 开始),语法更符合 C 语言习惯。

cpp

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

int main() {
    string s = "asjhjksd";
    cout << "数组式访问遍历:";
    // size()获取字符串长度(元素个数)
    for (int i = 0; i < s.size(); i++) {
        cout << s[i] << " ";  // 等价于*(s.begin() + i)
    }
    cout << endl;

    return 0;
}

2.3 只读遍历:const 迭代器

若只需 "遍历不修改",可在迭代器函数前加c(如cbegin()crbegin()),获取const类型迭代器,避免误修改。

cpp

复制代码
// const正向迭代器(只读)
for (auto it = s.cbegin(); it != s.cend(); it++) {
    // *it = 'a';  // 报错:const迭代器不允许修改
    cout << *it << " ";
}

// const反向迭代器(只读)
for (auto rit = s.crbegin(); rit != s.crend(); rit++) {
    cout << *rit << " ";
}

结果验证建议(图片内容)

截图应包含:

  • 正向遍历结果(a s j h j k s d );
  • 反向迭代器遍历结果(d s k j h j s a );
  • 数组式访问结果(与正向遍历一致)。

三、string 的初始化:简洁的 "内置类型式" 写法

string的初始化方式有多种,最常用且直观的是拷贝初始化 ,语法与内置类型(如int)完全一致,降低记忆成本。

cpp

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

int main() {
    // 常用初始化:拷贝初始化(类似int a = 10;)
    string s1 = "zhdshk";  // 直接赋值字符串常量
    cout << "s1: " << s1 << endl;

    // 其他常见初始化(补充参考)
    string s2;  // 默认初始化:空字符串
    string s3(s1);  // 拷贝构造:s3是s1的副本
    string s4(5, 'a');  // 填充初始化:5个'a',即"aaaaa"

    cout << "s2: " << s2 << "(空字符串)" << endl;
    cout << "s3: " << s3 << "(s1的副本)" << endl;
    cout << "s4: " << s4 << "(5个'a')" << endl;

    return 0;
}

补充说明

更多初始化方式(如用字符指针、子字符串初始化)可参考cppreference.com或原文提到的cplusplus.com,文档中有详尽的参数说明。

结果验证建议(图片内容)

截图应包含 4 个字符串的输出:

  • s1: zhdshk
  • s2: (空字符串)(无内容);
  • s3: zhdshk(与 s1 一致);
  • s4: aaaaa

四、reserve 函数:灵活调整 string 的容量

reserve(n)的核心作用是预分配字符串的容量(capacity) ,用于优化内存分配效率,不影响字符串的长度(size)和内容。理解sizecapacity的区别是关键:

  • size:字符串当前的元素个数(实际存储的字符数);
  • capacity:字符串在不重新分配内存的情况下,最多能存储的元素个数(底层数组的大小)。

4.1 reserve 的核心规则(原文重点)

  1. n > 当前capacity:扩容到n(或更大,取决于编译器);
  2. n < 当前capacity不强制缩容(是否缩容由编译器决定);
  3. n < 当前size:绝对不缩容(容量不能小于实际元素个数);
  4. 不改变size和字符串内容。

4.2 代码演示:reserve 的实际效果

以下代码基于原文test_string4()修正,直观展示reservesizecapacity的影响:

cpp

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

// 测试reserve函数
void test_string4() {
    // 初始化一个较长的字符串
    string s2("hello worldxxxxxxxxxxxxx");  // 内容:hello world + 11个x
    cout << "初始状态:" << endl;
    cout << "size: " << s2.size() << endl;    // 输出实际字符数(11+11=22?需以运行结果为准)
    cout << "capacity: " << s2.capacity() << endl;  // 编译器默认分配的容量
    cout << "------------------------" << endl;

    // 1. reserve(20):n < 初始capacity(假设初始capacity>20)
    s2.reserve(20);
    cout << "reserve(20)后:" << endl;
    cout << "size: " << s2.size() << endl;    // size不变
    cout << "capacity: " << s2.capacity() << endl;  // 可能不缩容(编译器决定)
    cout << "------------------------" << endl;

    // 2. reserve(40):n > 初始capacity
    s2.reserve(40);
    cout << "reserve(40)后:" << endl;
    cout << "size: " << s2.size() << endl;    // size仍不变
    cout << "capacity: " << s2.capacity() << endl;  // 扩容到40(或更大)
    cout << "------------------------" << endl;
}

int main() {
    test_string4();
    return 0;
}

结果验证建议(图片内容)

以 GCC 编译器为例,截图可能包含:

  • 初始状态:size:22capacity:31(编译器默认分配的容量通常略大于实际需求);
  • reserve(20)后:size:22capacity:31(不缩容);
  • reserve(40)后:size:22capacity:40(扩容到 40)。

五、reverse 函数:一键反转 string 或容器

reverse是 STL 算法库中的函数,支持对stringvector等容器进行反转,只需传入 "待反转范围" 的迭代器(左闭右开[begin, end))。

5.1 代码演示:反转 string

cpp

复制代码
#include <iostream>
#include <string>
#include <algorithm>  // 必须包含:reverse函数在<algorithm>中
using namespace std;

int main() {
    string s = "hello world";
    cout << "反转前:" << s << endl;

    // 反转:传入s的首尾迭代器(覆盖整个字符串)
    reverse(s.begin(), s.end());

    cout << "反转后:" << s << endl;  // 输出:dlrow olleh
    return 0;
}

5.2 扩展:反转 vector

reverse同样适用于vector,用法完全一致:

cpp

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

int main() {
    vector<int> v = {1, 2, 3, 4, 5};
    cout << "反转前:";
    for (auto num : v) cout << num << " ";

    reverse(v.begin(), v.end());  // 反转vector

    cout << "\n反转后:";
    for (auto num : v) cout << num << " ";  // 输出:5 4 3 2 1
    return 0;
}

结果验证建议(图片内容)

截图包含两部分:

  • string 反转:反转前:hello world反转后:dlrow olleh
  • vector 反转:反转前:1 2 3 4 5 反转后:5 4 3 2 1

总结

本文围绕string的核心功能展开,重点掌握:

  1. 迭代器(正向 / 反向、const)与范围 for 的遍历逻辑,尤其是引用型范围 for 的修改用法;
  2. 简洁的string初始化方式,以及更多方式的查询渠道;
  3. reserve对容量的调整规则(不影响 size、缩容依赖编译器);
  4. reverse对容器的反转用法(需传入迭代器范围)。

string的接口远不止这些,若需深入学习,可访问cppreference.comcplusplus.com,结合实际代码测试,才能真正熟练掌握。

相关推荐
Evand J2 小时前
【MATLAB例程】三维环境下,EKF融合INS与DVL的核心程序,用于惯导和速度传感器的数据融合滤波。附下载链接
开发语言·matlab
枫叶丹42 小时前
【Qt开发】Qt系统(二)-> 事件分发器
c语言·开发语言·数据库·c++·qt·系统架构
独自破碎E2 小时前
Leetcode1438绝对值不超过限制的最长连续子数组
java·开发语言·算法
澜莲花3 小时前
python图色之opencv基础---验证码实战
开发语言·python·opencv
沐知全栈开发3 小时前
Numpy 数组操作
开发语言
yaoxin5211233 小时前
279. Java Stream API - Stream 拼接的两种方式:concat() vs flatMap()
java·开发语言
@小码农3 小时前
202512 电子学会 Scratch图形化编程等级考试三级真题(附答案)
服务器·开发语言·数据结构·数据库·算法
Cosmoshhhyyy3 小时前
《Effective Java》解读第29条:优先考虑泛型
java·开发语言
一路往蓝-Anbo3 小时前
C语言从句柄到对象 (六) —— 继承与 HAL:父类指针访问子类数据
c语言·开发语言·stm32·嵌入式硬件·物联网