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

【C++】深入理解substr()函数


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C++

文章目录

  • 💯前言
  • 💯函数概述
    • 参数说明:
    • 返回值:
  • 💯基础用法示例
    • 示例1:从指定位置提取到字符串末尾
    • 示例2:从指定位置提取固定长度的子串
  • 💯`substr()`与`find()`函数的结合
    • 示例3:配合`find()`提取子串
    • 注意事项
  • 💯越界问题
    • 示例4:越界示例
  • 💯`find()`的返回值校验
    • 示例5:`find()`未找到子串
    • 扩展阅读:`npos`的意义
    • 示例6:`npos`的基本使用
  • 💯小结


在这里插入图片描述


💯前言

  • 在C++语言的学习中,字符串处理是一个非常重要的内容,而substr()函数作为std::string类中的成员函数,为我们提供了提取子字符串的便捷操作。在本文中,我们将深入解析substr()函数的用法,包括其函数原型、参数意义、使用场景以及常见的错误和注意事项。同时,还会拓展substr()与其他函数(如find())的配合使用,以帮助读者更好地理解和掌握字符串操作的技巧。
    本文内容基于一节关于substr()函数的课程整理而成,并进行了优化和拓展,以便于初学者和进阶学习者参考。
    C++ 参考手册
    在这里插入图片描述

💯函数概述

substr()函数用于截取字符串中指定位置和长度的子串。其函数原型如下:

string substr(size_t pos = 0, size_t len = npos) const;

参数说明:

  1. pos: 指定子字符串的起始位置(从0开始计数)。如果未传入参数,则默认从字符串的起点(pos = 0)开始。
  2. len: 子字符串的长度。若未传入参数,则默认值为npos,表示从起始位置一直截取到字符串的末尾。

返回值:

返回截取得到的子字符串,类型为std::string


💯基础用法示例

示例1:从指定位置提取到字符串末尾

以下代码展示了如何从字符串的某个位置开始提取到末尾的子串:

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello world hello everyone";
    string s1 = s.substr(7);
    cout << s1 << endl;  // 输出: "orld hello everyone"
    return 0;
}

解析

  • s.substr(7)表示从下标7处(字符o)开始,一直截取到字符串的末尾。
  • 输出结果为:orld hello everyone

示例2:从指定位置提取固定长度的子串

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello world hello everyone";
    string s2 = s.substr(7, 6);
    cout << s2 << endl;  // 输出: "orld h"
    return 0;
}

解析

  • s.substr(7, 6)表示从下标7处(字符o)开始,提取长度为6的子串。
  • 输出结果为:orld h

💯substr()find()函数的结合

在实际开发中,substr()常常与find()函数配合使用。find()的作用是查找子串在字符串中的起始位置,然后通过substr()提取目标子串。

示例3:配合find()提取子串

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello world hello everyone";
    size_t n = s.find("world");  // 查找子串"world"的起始位置
    if (n != string::npos) {      // 确保子串存在
        string s3 = s.substr(n, 10);  // 从找到的位置开始提取10个字符
        cout << s3 << endl;  // 输出: "world hell"
    }
    return 0;
}

解析

  1. find()函数的返回值是子串在字符串中的起始位置。如果未找到子串,返回string::npos
  2. substr()从查找到的位置开始提取目标长度的子串。
  3. 代码中,s.find("world")返回位置6,s.substr(6, 10)则提取了从位置6开始的10个字符,结果为world hell

注意事项

💯越界问题

如果传入的pos参数超出了字符串的长度范围,substr()会抛出一个std::out_of_range异常。因此,在调用substr()时,应确保起始位置合法。

示例4:越界示例

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello";
    try {
        string s4 = s.substr(10);  // 起始位置超出字符串长度
        cout << s4 << endl;
    } catch (const out_of_range& e) {
        cerr << "Exception: " << e.what() << endl;  // 输出异常信息
    }
    return 0;
}

输出

Exception: basic_string::substr: __pos (which is 10) > this->size() (which is 5)

💯find()的返回值校验

在使用find()时,如果未找到目标子串,返回值为string::npos,应在调用substr()之前进行检查,否则会导致意想不到的行为。

示例5:find()未找到子串

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello world";
    size_t pos = s.find("everyone");
    if (pos == string::npos) {
        cout << "Sub-string not found" << endl;
    } else {
        string s5 = s.substr(pos);
        cout << s5 << endl;
    }
    return 0;
}

输出

Sub-string not found

扩展阅读:npos的意义

npos是一个常量,定义在std::string中,表示一个无效的位置(即不存在的位置)。它的实际值是一个size_t类型的最大值(通常为-1的无符号表示)。

在以下场景中,npos非常有用:

  1. find()未找到子串时返回npos
  2. substr()的默认参数中用npos表示一直截取到字符串的末尾。

示例6:npos的基本使用

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "hello world";

    // 检查npos
    if (s.find("everyone") == string::npos) {
        cout << "Sub-string not found" << endl;
    }

    // substr的默认值npos
    string s6 = s.substr(6, string::npos);  // 从下标6开始提取到末尾
    cout << s6 << endl;  // 输出: "world"

    return 0;
}

💯小结

通过本文的学习,我们详细剖析了C++中substr()函数的用法及其与find()等函数的配合操作,同时讨论了常见的错误和注意事项。从基础的函数用法到进阶的拓展应用,substr()为字符串操作提供了极大的便利。希望通过这篇文章,读者能够更加熟练地使用C++中的字符串处理函数,为日后的程序开发打下坚实的基础。

如有疑问,欢迎进一步交流探讨!


在这里插入图片描述


在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

1. 理解C++的基础
学习重点:

  1. 掌握基本语法
    • 学会声明变量、条件语句、循环、函数等核心语法。
    • 掌握数组、指针、引用等基础知识。
  2. 熟悉标准输入输出
    • 掌握 cincout 的用法。
    • 理解格式化输出,例如 std::setwstd::fixed
  3. 记住编译器的角色
    • 理解源代码如何通过编译器转换为可执行程序,选择一款好的IDE(如Visual Studio、Clion、VSCode)。

建议:用大量小程序练习这些基础语法,比如写一个计算器、模拟猜数字游戏等。


2. 深入学习C++的特性
学习重点:

  1. 面向对象编程(OOP)
    • 理解类和对象,熟悉如何定义类、成员变量和成员函数。
    • 掌握封装、继承、多态三大核心特性。
  2. 内存管理
    • 理解指针的用法,掌握动态内存分配(newdelete)。
    • 学习如何避免内存泄漏,熟悉智能指针(如std::unique_ptrstd::shared_ptr)。
  3. 标准模板库(STL)
    • 熟悉常用的容器(如vectormapset)和算法(如sortfind)。
    • 掌握迭代器的用法。
  4. 异常处理
    • 学习使用try-catch块处理异常。
    • 理解异常的用途以及如何设计健壮的代码。

建议:尝试开发一个小型项目,比如一个学生管理系统,综合应用类、STL、指针和动态内存分配。


3. 掌握进阶内容
学习重点:

  1. 模板
    • 理解函数模板和类模板,掌握泛型编程思想。
    • 学习模板特化和模板元编程的基本概念。
  2. 多线程与并发
    • 学习 C++11 提供的多线程支持(如std::thread)。
    • 熟悉互斥锁(std::mutex)和条件变量(std::condition_variable)。
  3. C++与C的兼容性
    • 学习如何在C++中使用C语言代码,理解C和C++的区别。
    • 掌握C风格字符串(char[])和C++字符串(std::string)的转换。

建议:在这一阶段,可以挑战更复杂的项目,比如开发一个小型的HTTP服务器,学习网络编程并结合多线程。


4. 学习资源与实践方法
学习资源:

  1. 书籍
    • 《C++ Primer》:非常适合初学者的经典书籍。
    • 《Effective C++》:进阶学习C++最佳实践的指南。
    • 《The C++ Programming Language》:Bjarne Stroustrup(C++之父)的权威著作。
  2. 在线课程
    • Coursera 上的 C++ 编程课程。
    • YouTube 上免费的 C++ 系列教程。
  3. 社区与文档
    • 参与C++相关的论坛(如CSDN、Stack Overflow)。
    • 阅读官方文档(https://en.cppreference.com)。

实践方法:

  1. 多写代码,多调试
    • 每学一个概念后,写至少两个示例代码并进行调试。
  2. 做小项目
    • 从简单的控制台程序开始,比如文件读写、计算器、小游戏等。
    • 慢慢过渡到图形界面或网络程序开发。
  3. 阅读他人代码
    • 阅读开源项目的代码,理解优秀代码的设计思路。
  4. 参加编程比赛
    • 比如 LeetCode 或 Codeforces,可以帮助你提升算法能力和C++的熟练度。

5. 保持耐心与兴趣
学习C++可能会面临以下困难:

  1. 复杂的语法:如模板、智能指针、多线程等。
  2. 调试困难:指针错误、内存泄漏、未定义行为可能让人头疼。

如何应对:

  • 将大问题拆解成小问题,逐步解决。
  • 不断重复基础知识,以加深理解。
  • 保持兴趣,尝试一些有趣的项目,比如写一个游戏、制作一个简单的图形程序。

小结
学习C++需要一个循序渐进的过程,从基础语法到面向对象编程,再到进阶的模板和并发编程,每一步都需要耐心和实践。通过充分利用学习资源、进行大量编码练习,以及挑战实际项目,你一定可以成为C++的高手。记住,学习的核心在于理解,而非死记硬背。

祝你学有所成,享受C++编程的乐趣!



http://www.kler.cn/a/501303.html

相关文章:

  • LeetCode 热题 100 | 滑动窗口
  • 关于使用FastGPT 摸索的QA
  • 新版AndroidStudio通过系统快捷创建带BottomNavigationView的项目踩坑记录
  • ASP.NET Core 中,Cookie 认证在集群环境下的应用
  • [离线数仓] 总结二、Hive数仓分层开发
  • 【开发日记】Docker修改国内镜像源
  • 解锁最新专业版005,内置序列免安装!
  • 腾讯云AI代码助手编程挑战赛-厨房助手之AI大厨
  • 【灵码助力安全2】——利用通义灵码辅助复现未公开漏洞的实践
  • Android车机DIY开发之软件篇(三)编译Automotive OS错误(2)
  • Github上传项目
  • 反弹SHELL不回显带外正反向连接防火墙出入站文件下载
  • 基于DFT与IIR-FIR滤波器的音频分析与噪声处理
  • 服务提供模式:App、API 和 Agent —— 重新定义服务交付方式
  • 4.3.3 最优二叉树+二叉查找树
  • 机器学习之支持向量机SVM及测试
  • WebGIS城市停水及影响范围可视化实践
  • k8s 安装ingress并配置flink服务
  • 《系统爆破:MD5易破,后台登录可爆破?》
  • KG-CoT:基于知识图谱的大语言模型问答的思维链提示
  • 青龙面板脚本开发指南:高效自动化任务的实现
  • 一学就废|Python基础碎片,文件读写
  • MySQL存储引擎、索引、索引失效
  • Django项目集成审计日志与界面美化
  • 基于Springboot + vue实现的购物推荐网站
  • 完整化安装kubesphere,ks-jenkins的状态一直为init