C++STL容器string第二讲--string常用接口,插入删除接口,替换replace,正反向查找,模拟迭代器的实现和常用接口的模拟实现


博主名称:deM0one ⭐️C++专栏: C++ ⭐️C++string第一讲: string第一讲

文章目录

  • C++string常用接口介绍、测试及模拟
    • [一、引言:string 操作总览](#一、引言:string 操作总览)
      • [1.1 为什么单独研究 string](#1.1 为什么单独研究 string)
      • [1.2 本文知识地图](#1.2 本文知识地图)
      • [1.3 重要提醒](#1.3 重要提醒)
    • 二、append:向字符串末尾追加
      • [2.1 作用](#2.1 作用)
      • [2.2 常用重载(C++98 / C++11 / C++14)](#2.2 常用重载(C++98 / C++11 / C++14))
      • [2.3 理解要点](#2.3 理解要点)
    • 三、erase:删除字符串中的内容
      • [3.1 作用](#3.1 作用)
      • [3.2 常用重载(C++98 / C++11)](#3.2 常用重载(C++98 / C++11))
      • [3.3 理解要点](#3.3 理解要点)
    • 四、replace:替换字符串中的一段
      • [4.1 作用](#4.1 作用)
      • [4.2 常用重载(C++98 / C++11 / C++14)](#4.2 常用重载(C++98 / C++11 / C++14))
      • [4.3 理解要点](#4.3 理解要点)
    • [五、find 与 rfind:查找内容](#五、find 与 rfind:查找内容)
      • [5.1 find:查找第一次出现的位置](#5.1 find:查找第一次出现的位置)
      • [5.2 rfind:查找最后一次出现的位置](#5.2 rfind:查找最后一次出现的位置)
      • [5.3 理解要点](#5.3 理解要点)
    • 六、substr:截取子串
      • [6.1 作用](#6.1 作用)
      • [6.2 函数签名](#6.2 函数签名)
      • [6.3 理解要点](#6.3 理解要点)
    • 七、getline:按分隔符读取输入
      • [7.1 读取方式对比](#7.1 读取方式对比)
      • [7.2 典型示例:取出最后一个单词](#7.2 典型示例:取出最后一个单词)
      • [7.3 理解要点](#7.3 理解要点)
    • 八、补充:内联和静态的可见性
      • [8.1 笔记要点](#8.1 笔记要点)
      • [8.2 遍历代码示例(范围 for 与迭代器)](#8.2 遍历代码示例(范围 for 与迭代器))
    • [九、底层理解:手写 string 的迭代器与 reserve](#九、底层理解:手写 string 的迭代器与 reserve)
      • [9.1 用指针模拟迭代器](#9.1 用指针模拟迭代器)
      • [9.2 手写 reserve:只扩容,不修改内容](#9.2 手写 reserve:只扩容,不修改内容)
      • [9.3 理解要点](#9.3 理解要点)
    • 十、总结

C++string常用接口介绍、测试及模拟

本文档基于学习笔记整理,内容覆盖:string 的追加、删除、替换、查找、取子串、getline 输入读取,以及内联/静态可见性和 string 的底层手写实现。

一、引言:string 操作总览

1.1 为什么单独研究 string

  • string 是 C++ 中最常用的容器之一,日常处理文本离不开它
  • 掌握常用成员函数,可以高效完成"增、删、改、查、截取、输入"等操作

1.2 本文知识地图

操作 成员函数 说明
append 在字符串末尾追加内容
erase 删除指定位置或区间的字符
replace 替换一段子串
find / rfind 查找第一次 / 最后一次出现位置
substr 截取子串
getline 按分隔符读取输入

1.3 重要提醒

  • 笔记中特别标注:erase 和 replace 是性能杀手,使用时要注意效率

二、append:向字符串末尾追加

2.1 作用

  • 在字符串当前值的末尾追加额外的字符,从而扩展字符串

2.2 常用重载(C++98 / C++11 / C++14)

cpp 复制代码
string& append(const string& str);
string& append(const string& str, size_t subpos, size_t sublen);
string& append(const char* s);
string& append(const char* s, size_t n);
string& append(size_t n, char c);
template <class InputIterator>
string& append(InputIterator first, InputIterator last);

2.3 理解要点

  • 可以追加:另一个 string、C 字符串、字符缓冲区、n 个相同字符、迭代器区间
  • 返回 string&,支持链式调用

三、erase:删除字符串中的内容

3.1 作用

  • 删除字符串的一部分,减少其长度
  • 笔记要点:erase 可以指定位置删除

3.2 常用重载(C++98 / C++11)

cpp 复制代码
string& erase(size_t pos = 0, size_t len = npos);   // (1) 按位置 + 长度
iterator erase(iterator p);                          // (2) 删除单个字符
iterator erase(iterator first, iterator last);       // (3) 删除迭代器区间

3.3 理解要点

  • 三种删除方式:按位置长度删、按迭代器删、按区间删
  • 默认从位置 0 删到字符串末尾
  • 属于性能杀手之一,频繁删除要考虑效率

四、replace:替换字符串中的一段

4.1 作用

  • 替换字符串中从位置 pos 开始、跨 len 个字符的部分(或区间 [i1, i2) 之间的部分)为新内容

4.2 常用重载(C++98 / C++11 / C++14)

cpp 复制代码
string& replace(size_t pos, size_t len, const string& str);
string& replace(iterator i1, iterator i2, const string& str);
string& replace(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
string& replace(size_t pos, size_t len, const char* s);
string& replace(size_t pos, size_t len, const char* s, size_t n);
string& replace(iterator i1, iterator i2, const char* s);
string& replace(iterator i1, iterator i2, const char* s, size_t n);
string& replace(size_t pos, size_t len, size_t n, char c);
string& replace(iterator i1, iterator i2, size_t n, char c);
template <class InputIterator>
string& replace(iterator i1, iterator i2, InputIterator first, InputIterator last);

4.3 理解要点

  • 两种定位方式:pos + len 方式 和 [i1, i2) 迭代器区间方式
  • 新内容可以来自 string、C 字符串、缓冲区、重复字符或迭代器区间
  • 与 erase 一样是性能杀手

五、find 与 rfind:查找内容

5.1 find:查找第一次出现的位置

cpp 复制代码
size_t find(const string& str, size_t pos = 0) const;   // (1) string
size_t find(const char* s, size_t pos = 0) const;        // (2) C 字符串
size_t find(const char* s, size_t pos, size_t n) const;  // (3) 缓冲区
size_t find(char c, size_t pos = 0) const;               // (4) 字符
  • 从 pos 位置开始向后查找,返回第一次出现的位置

5.2 rfind:查找最后一次出现的位置

cpp 复制代码
size_t rfind(const string& str, size_t pos = npos) const;   // (1) string
size_t rfind(const char* s, size_t pos = npos) const;        // (2) C 字符串
size_t rfind(const char* s, size_t pos, size_t n) const;     // (3) 缓冲区
size_t rfind(char c, size_t pos = npos) const;               // (4) 字符
  • 从后往前查找,返回最后一次出现的位置
  • 注意默认起始位置是 npos(表示字符串末尾)

5.3 理解要点

  • 都返回 size_t 下标;找不到时返回 npos
  • 四个重载分别对应:string、C 字符串、缓冲区、单个字符

六、substr:截取子串

6.1 作用

  • 生成一个子串对象,其值初始化为当前对象子串的拷贝

6.2 函数签名

cpp 复制代码
string substr(size_t pos = 0, size_t len = npos) const;

6.3 理解要点

  • 子串从 pos 位置开始,跨 len 个字符
  • 如果到字符串末尾还不足 len 个字符,则截到字符串结尾(哪个先到取哪个

七、getline:按分隔符读取输入

7.1 读取方式对比

  • cin >> str:遇到空格或换行就停止读取
  • getline(cin, str)默认分隔符是换行,读到换行才停止
  • getline 也可以自己设定分隔符 ,例如 getline(cin, str, ',') 按逗号分割

7.2 典型示例:取出最后一个单词

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

int main()
{
    string str;
    // cin >> str;              // 遇空格/换行即停
    getline(cin, str);          // 默认以换行作为分隔符

    size_t pos = str.rfind(' ');            // 找到最后一个空格
    cout << str.substr(pos + 1) << endl;    // 截取最后一个空格之后的内容
    return 0;
}

7.3 理解要点

  • 综合运用了 rfind + substr:先找最后一次出现的位置,再截取其后内容
  • 空格和换行默认被视为分割符

八、补充:内联和静态的可见性

8.1 笔记要点

  • 内联和静态只在当前文件可见
  • 这也是为什么头文件中的 inline 函数和 static 变量不会造成多文件链接冲突

8.2 遍历代码示例(范围 for 与迭代器)

cpp 复制代码
// 方式一:范围 for
for (auto e : s2)
{
    cout << e << " ";
}
cout << endl;

// 方式二:迭代器
string::iterator it = s2.begin();
while (it != s2.end())
{
    cout << *it << " ";
    ++it;
}
cout << endl;

九、底层理解:手写 string 的迭代器与 reserve

9.1 用指针模拟迭代器

  • 手写 string 类中,直接用 typedef char* iterator 模拟迭代器:
cpp 复制代码
class string
{
public:
    typedef char* iterator;

    iterator begin()
    {
        return _str;              // 指向字符串开头
    }

    iterator end()
    {
        return _str + _size;      // 指向有效字符的末尾
    }

private:
    char* _str;       // 指向堆上的字符数组
    size_t _size;     // 有效字符个数
    size_t _capacity; // 容量
};

9.2 手写 reserve:只扩容,不修改内容

cpp 复制代码
void string::reserve(size_t n)
{
    if (n > _capacity)                 // 只有 n 大于容量才需要扩容
    {
        char* tmp = new char[n + 1];   // 多开 1 个位置存放 '\0'
        strcpy(tmp, _str);             // 拷贝旧内容
        delete[] _str;                 // 释放旧空间
        _str = tmp;
        _capacity = n;                 // 更新容量
    }
}

9.3 理解要点

  • 迭代器本质是"像指针的东西":begin() 返回开头指针,end() 返回 _str + _size
  • reserve 只负责扩容,不会修改已有内容
  • 扩容流程:申请新空间 → 拷贝旧数据 → 释放旧空间 → 更新容量

十、总结

  • string 常用操作一览:append(增)、erase(删)、replace(改)、find/rfind(查)、substr(取)、getline(读)
  • erase 和 replace 是性能杀手,使用时注意场景
  • find 找第一次出现,rfind 找最后一次出现,找不到返回 npos
  • getline 默认以换行为分隔符,可自定义分隔符;空格和换行默认是分割符
  • 内联和静态只在当前文件可见
  • 通过手写 string 的 begin/end 和 reserve,能更好理解迭代器与扩容的底层原理

任何的建议和批评欢迎指出,我们共同进步!

相关推荐
geovindu4 小时前
CSharp: 万年历
开发语言·后端·c#·.net
我找到地球的支点啦5 小时前
Matlab系列(009) 一CRC循环冗余校验详解
开发语言·数据结构·算法·matlab·信息与通信
予昊5 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket
2601_962203515 小时前
【SpringAI入门】初识SpringAI
java
weixin_461408585 小时前
Mybatis-flex小记
java·开发语言·mybatis
2601_962177136 小时前
【MySQL篇】聚合查询,联合查询
android·java·mysql
それども6 小时前
IDEA接入Claude完整流程
java·ai·intellij-idea
小鹿的周先生6 小时前
Spring-AI-第2篇-ChatClient 实战:使用 DeepSeek 完成第一次 AI 对话
java·人工智能·spring
青梅味猪大肠6 小时前
【深入浅出C++】为什么虚表指针可以解决菱形继承
开发语言·c++
潘潘的嵌入式日记7 小时前
I²C 从机接收总被覆盖?双缓冲要在 STOP 时交接
c语言·开发语言·单片机