【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨文章所属专栏:c++篇–CSDN博客

在这里插入图片描述

文章目录

  • 前言
  • 一.`std::string`对象的创建
  • 二.`std::string`对象的访问
  • 三.`std::string`对象的容量
  • 四.`std::string`对象的遍历
    • 1.使用索引(下标)进行遍历
    • 2.使用迭代器进行遍历
    • 3.使用范围for进行遍历
  • 五.`std::string`对象的增删查改
    • 1.增加
    • 2.删除
    • 3.查找
    • 4.修改
  • 六.`std::string`对象的其他函数使用

前言

在C++编程的世界里,字符串无处不在。无论是用户输入、文件处理,还是网络通信,字符串都是不可或缺的数据类型。然而,直接操作字符数组(即char字符串)不仅繁琐,而且容易出错。幸运的是,C++标准库为我们提供了std::string类,它封装了字符串的底层细节,提供了丰富的成员函数来简化字符串的处理。本篇文章将深入探讨c++中的std::string类的成员函数,包括字符串的创建,遍历,以及增删查改等,带你领略其强大的功能和便捷的操作方式。

注意:
本篇文章资料来源网站:c++:std::string

文章中出现的蓝色字符是对应函数的网站(重要的函数我会附上网站,部分函数没有,有需要的可以根据上面的这个网站自己查找噢)

一.std::string对象的创建

以下是一些常用的std::string对象的创建

  • 默认(无参)构造对象:

    创建一个无参对象,也就是空字符串。

    std::string s1;
    
  • 带参构造对象:

    创建一个非空字符串。

    std::string s2("hello world");
    //打印结果:hello world
    
  • 用指定数量的字符构造对象:

    std::string s3(5,'*');
    //打印结果:*****
    
  • 用另一个std::string对象构造:

    相当于对std::string对象拷贝构造

    std::string s2("hello world");
    std::string s3(s2);
    //打印结果:hello world
    
  • 用子字符串构造:

    从已存在的对象指定位置开始拷贝

    std::string s2("hello world");
    //从s2对象的下标为6开始拷贝,拷贝数量为5
    std::string s4(s2,6,5);
    //打印结果:world
    

二.std::string对象的访问

std::string对象常用的访问方式有下面四种:

在这里插入图片描述

其中operator []at()这两种方式是比较常用的,都是用于访问字符串中特定位置的字符。

  • at(): at()方式接受一个索引值作为参数,返回索引值上的字符,如果索引值超过字符串的有限范围,就会抛出一个std::out_of_range异常。

    在这里插入图片描述

    以下面代码为例:

    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {string s1("hello world");try {char ch = s1.at(13);}catch (const out_of_range& e) {cerr << "Caught an out_of_range exception:" << e.what() << '\n';}return 0;
    }
    

    当索引值为13时,超过字符串的有限范围,抛出异常并被捕获处理:

    在这里插入图片描述

  • operator[]:该操作符也可以接受一个索引值作为参数,返回该索引值上的字符,但是和at()方式不同的是,operator []在索引值超出字符串的有限范围时,不会抛出异常,可能会导致未定义行为,导致程序的崩溃或产生意外结果。

    在这里插入图片描述

    #include<iostream>
    #include<string>
    using namespace std;
    int main(){string s1("hello world");char ch = s1[13];cout << ch << endl;
    }
    

    在这里插入图片描述

总结:at()operator []两种方式都可以用于访问std::string对象中的字符,但at()提供了更高的安全性,而operator []则提供了更好的性能。选择使用哪个时,需要根据具体的使用场景和对安全,性能的要求来决定。

三.std::string对象的容量

在c++中std::string类提供了多种成员函数来操作和查询字符串的容量和大小等属性,以下是关于所有capacity的成员函数:

在这里插入图片描述

下面重点讲解一些常用的函数和使用方式:

  • size()/length():返回字符串有效长度(也就是字符串的字符个数),这两个函数是等价的。
using namespace std;
string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
//输出结果都为11
  • capacity():返回当前分配的存储空间的大小(空间总大小),这个值可能大于或等于size()返回的值。

    using namespace std;
    string s1("hello world");
    cout << s1.size() << endl;
    cout << s1.capacity() << endl;
    //输出结果size为11,capacity为15
    

    在这里插入图片描述

  • reserve():更改字符串的容量至少为n,该函数不会改变字符串的大小,只是确保有足够的空间来存储至少n个字符。

    using namespace std;
    string s1("hello world");
    cout << "reserve前:" << endl;
    cout << s1.size() << endl;
    cout << s1.capacity() << endl;
    s1.reserve(20);
    cout << "reserve后:" << endl;
    cout << s1.size() << endl;
    cout << s1.capacity() << endl;
    

    在这里插入图片描述

  • resize():将字符串的大小调整为n,如果n大于当前字符串的大小,则用默认字符(通常为0,如果使用reserve(n,ch)则是字符ch)填充新位置;如果n小于当前字符串的大小,则字符串截断。

    using namespace std;
    string s1("hello world");
    cout << s1 << endl;
    //0填充新位置
    s1.resize(15);
    //字符串截断
    s1.resize(6);
    cout << s1 << endl;
    

    在这里插入图片描述

    在这里插入图片描述

  • clear():清空字符串,使其大小为0。

    using namespace std;
    string s1("hello world");
    s1.clear();
    cout<<s1.size()<<endl;
    //输出结果为0
    
  • empty():检查字符串是否为空,如果为空,返回true,如果不为空,则返回false

    using namespace std;
    string s1("hello world");
    string s2;
    cout << s1.empty() << endl;
    //返回值为true(1)
    cout << s2.empty() << endl;
    //返回值为false(0)
    

四.std::string对象的遍历

当有一个字符串时,我们肯定少不了对该字符串进行遍历。

在c++中,std::string类提供了多种方法进行字符串的遍历,以下是几种常用的遍历方式:

1.使用索引(下标)进行遍历

通过前面的operator []at()两种方式可以对std::string对象进行遍历:

#include<iostream>
#include<string>
using namespace std;
int main()
{string s1("hello world");for (size_t i = 0; i < s1.size(); i++) {cout << s1[i] << " ";}cout << endl;for (size_t i = 0; i < s1.size(); i++) {cout << s1.at(i) << " ";}cout << endl;return 0;
}

打印结果如下,两种方式结果相同:

在这里插入图片描述

2.使用迭代器进行遍历

在c++中,std::string类提供了迭代器(iterators),用于遍历字符串,这些迭代器可以像访问数组一样访问字符串中的字符,以下是std::string类关于迭代器(iterators)所有的成员函数:

在这里插入图片描述

  • begin()end()

    begin()返回一个指向第一个字符的迭代器,end()返回一个指向字符串最后一个字符的下一个位置的迭代器(用于普通std::string类对象的从前往后遍历)。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello world");//iterator是像指针一样的类型(可能是指针,也可能不是),使用时需要加string::string::iterator it = s1.begin();while (it != s1.end()) {cout << *it << " ";it++;}cout << endl;return 0;
    }
    
  • cbegin()cend()

    begin(),end()功能相同,不同点是cbegin()cend()用于const std::string类对象的从前往后遍历且不能对该对象进行修改。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {const string s1("hello world");//const_iterator是像指针一样的类型(可能是指针,也可能不是),使用时需要加string::string::const_iterator it = s1.cbegin();while (it != s1.cend()) {cout << *it << " ";it++;}cout << endl;return 0;
    }
    
  • rbegin()rend()

    rbegin()返回一个指向最后一个字符的反向迭代器,rend()返回一个指向第一个字符的前一个位置的反向迭代器(用于普通std::string类对象的从后往前遍历)。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello world");//reverse_iterator是像指针一样的类型(可能是指针,也可能不是),使用时需要加string::string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()) {cout << *rit << " ";rit++;}cout<<endl;return 0;
    }
    
  • crbegin()crend():

    rbegin(),rend()功能相同,不同点是crbegin()crend()用于const std::string类对象的从后往前遍历且不能对该对象进行修改。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {const string s1("hello world");//const_reverst_iterator是像指针一样的类型(可能是指针,也可能不是),使用时需要加string::string::const_reverse_iterator rit = s1.crbegin();while (rit != s1.crend()) {cout << *rit << " ";rit++;}cout << endl;return 0;
    }
    

上面四种遍历方式的结果:

在这里插入图片描述

3.使用范围for进行遍历

在c++入门讲解的时候有关于范围for的使用讲解(详细可以看我之前的文章c++入门二),在对std::string对象进行遍历时同样可以使用范围for,而范围for的底层原理就是上面讲解的迭代器。

#include<iostream>
#include<string>
using namespace std;
int main() {string s1("hello world");//auto关键字可以自动推演ch的类型//像上面迭代器使用的类型如:string::iterator 可以直接使用autofor (auto ch : s1) {cout << ch << " ";}cout << endl;return 0;
}

在这里插入图片描述

五.std::string对象的增删查改

1.增加

  • append():在字符串的末尾追加内容,可以是c风格的字符串,std::string对象,字符数组的子串或者是单个字符。

    string s1("hello");
    s1.append(" ");
    s1.append("world");
    s1.append("!");
    cout << s1 << endl;//输出结果:hello world!
    
  • operator+=:和append()功能相似。

    string s1("hello");
    s1 += " ";
    s1 += "world";
    s1 += "!";
    cout << s1 << endl;//输出结果:hello world!
    
  • push_back():在字符串的末尾添加单个字符,push_back较为少用,没有operator+=append()使用起来方便。

    string s2("hello world");
    s2.push_back('!');
    cout << s2 << endl;//输出结果为:hello world!
    
  • insert():在字符串的指定位置插入新内容,可以是c风格的字符串,std::string对象,字符数组的子串或者是单个字符。

    string s3("hello");
    s3.insert(5, " world!");
    cout << s3 << endl;//输出结果为:hello world!
    

2.删除

  • erase():从字符串中删除指定位置或范围的字符,参数可以是单个位置,一个位置和长度或者两个位置来指定删除范围。

    string s1("hello world");
    s1.erase(8, 10);
    //删除从下标8到10位置的字符
    cout << s1 << endl;
    //输出hello wo
    s1.erase(5);
    //删除下标5之后的字符
    cout << s1 << endl;
    //输出hello
    
  • pop_back():删除字符串末尾的字符,该函数不能传参。

    string s2("hello world!");
    //删除最后一个字符'!'
    s2.pop_back();
    cout << s2 << endl;
    //输出hello world
    

3.查找

  • fand():在字符串中查找子串或者字符的首次出现位置,参数可以是要查找的子串或字符,以及可选的查找起始位置。未查找到时返回string::npos(下面三个函数同理)。

    注意:string::nposstd::string类中的一个静态成员变量,npos的值通常设置为size_t类型(无符号整形)的最大值,用于表示一个不可能在字符串中出现的位置。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello world");cout << s1.find("world") << endl;//输出下标位置为6cout << s1.find("zmh") << endl;//找不到,输出size_t类型的最大值return 0;
    }
    
  • rfand():查找子串或字符在字符串中最后一次出现的位置,参数和fand()相同。未查找到时返回string::npos

    #include<iostream>
    #include<string>
    using namespace std;
    int main(){string s1("hello world");cout << s1.rfind("l") << endl;//查找字符’l'最后一次出现的位置,输出下标位置9cout << s1.find("zmh") << endl;//找不到,输出size_t类型的最大值return 0;
    }
    
  • find_first_of():在字符串中查找任何与指定字符集中的字符首次匹配的位置,参数可以是字符集,以及可选的查找起始位置。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello world");string set("auto");size_t first_pos = s1.find_first_of(set);if (first_pos != string::npos) {cout << first_pos << endl;}else {cout << "No find" << endl;}return 0;
    }//输出结果为4,在s1字符串下标为4的位置首次与字符串set匹配
    
  • find_last_of():在字符串中查找任何与指定字符集中的字符最后一次匹配的位置,参数和find_first_of()相同。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s2("hello world");string ret("auto");size_t last_pos = s2.find_last_of(ret);if (last_pos != string::npos) {cout << last_pos << endl;}else {cout << "No find" << endl;}return 0;
    }//输出结果为7,在s1字符串下标为7的位置最后一次与字符串ret匹配
    

4.修改

  • assign():给字符串赋值,可以视为一种修改操作,参数可以是c风格的字符串,std::string对象,字符数组的子串或者是单个字符。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1;s1.assign("!");cout << s1 << endl;s1.assign("hello");cout << s1 << endl;return 0;
    }//第一次输出结果为!
    //第二次输出结果为hello
    
  • replace():替换字符串中的部分内容,参数包括要替换的起始位置和长度以及替换内容。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s2("hello world");s2.replace(6, 4, "auto");cout << s2 << endl;return 0;
    }
    //从下标为6的位置开始,替换长度为4的auto的字符
    //输出结果为hello autod
    
  • substr():返回一个子串,虽然substr()本身不能进行修改,但可以通过它获得子串并进行修改,然后可能需要将修改后的子串重新赋值给原字符串的一部分。

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello world");//获取s1字符串下标6到10位置的子串赋值给s2string s2 = s1.substr(6, 10);cout << s2 << endl;return 0;
    }//输出结果为world
    

六.std::string对象的其他函数使用

  • operator+:运算符+重载,用于将两个字符串对象连接在一起,并返回一个连接后的字符串,operator+operator+=的区别是,operator+不改变原字符串,operator+=改变原字符串

    #include<iostream>
    #include<string>
    using namespace std;
    int main() {string s1("hello");string s2(" world");string result = s1 + s2;cout << s1 << endl;cout << s2 << endl;cout << result << endl;return 0;
    }
    //第一个输出结果为hello
    //第二个输出结果为 world
    //第三个输出结果为hello world
    
  • operator<<:流插入运算符<<重载属于标准库std::ostream中的,是一个非成员函数,他接受一个std::ostream的引用和一个std::string的引用作为参数,并将std::string对象中的内容写入到输出流中。这个运算符返回对std::ostream的引用。

  • operator>>:流提取运算符>>重载属于标准库std::istream中的,是一个非成员函数,他接受一个std::istream的引用和一个std::string的引用作为参数,并将std::string对象中的内容写入到输入流中。再从输入流中提取数据,返回对std::istream的引用。

#include<iostream>
#include<string>
using namespace std;
int main() {string name;cout << "请输入姓名:" << endl;cin >> name;cout << name;return 0;
}
  • c_str():将std::string对象内部存储的字符串数据转换为一个以空字符’\0’为结尾的c格式字符串(const char*)类型。

    string s1("hello\0world");
    cout << s1.c_str() << endl;//输出结果为hello
    //遇到空字符结束
    

以上就是关于c++中std::string类的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458852.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读取有空格的string对象(getline)

文章目录 读取有空格的string对象1.使用标准库中的iostream来写2.**使用getline读取一整行** 读取有空格的string对象 1.使用标准库中的iostream来写 #include<iostream> using namespace std; int main() {string s;cin >> s;cout << s << endl;ret…

探索Python安全字符串处理的奥秘:MarkupSafe库揭秘

文章目录 探索Python安全字符串处理的奥秘&#xff1a;MarkupSafe库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;MarkupSafe是什么&#xff1f;第三部分&#xff1a;如何安装MarkupSafe&#xff1f;第四部分&#xff1a;MarkupSafe的简单使用方法1. 使用escape函数2.…

Tomcat安装与使用

Tomcat优点 1、开源免费&#xff1a;是一个免费、开源的Web服务器&#xff0c;可以在任何环境下自由使用&#xff0c;无需支付任何费用。 2、轻量级&#xff1a;是一个轻量级的Web服务器&#xff0c;其核心仅有几百K&#xff0c;启动速度非常快。 3、易于安装和配置&#xff1a…

【笔记】LLM位置编码之标准位置编码

标准位置编码 起源原理证明&#xff1a;对于任何固定的偏移量 k k k&#xff0c; P E p o s k PE_{posk} PEposk​可以表示为 P E p o s PE_{pos} PEpos​的线性函数。计算 P E p o s k 与 P E p o s PE_{posk} 与PE_{pos} PEposk​与PEpos​的内积结论 通俗理解缺点 起源 由…

深度学习之降维和聚类

1 降维和聚类 1.1 图解为什么会产生维数灾难 ​ 假如数据集包含10张照片&#xff0c;照片中包含三角形和圆两种形状。现在来设计一个分类器进行训练&#xff0c;让这个分类器对其他的照片进行正确分类&#xff08;假设三角形和圆的总数是无限大&#xff09;&#xff0c;简单的…

Typora一款极简Markdown文档编辑器和阅读器,实时预览,序列号生成!免费!最新可用!

文章目录 一、Typora下载和安装二、Typora序列号生成 Typora是一款Markdown编辑器和阅读器&#xff0c;风格极简&#xff0c;实时预览&#xff0c;所见即所得&#xff0c;支持MacOS、Windows、Linux操作系统&#xff0c;有图片和文字、代码块、数学公式、图表、目录大纲、文件管…

异常处理与调试:如何编写稳健的代码(8/10)

目录 异常处理与调试&#xff1a;如何编写稳健的代码&#xff08;8/10&#xff09; 介绍 异常概述 常见的异常类型 使用 try...except 处理异常 基本结构 示例&#xff1a;读取文件内容 捕获多个异常 自定义异常 示例&#xff1a;自定义异常类 调试代码 使用 print…

AI跟踪报道第62期-本周AI新闻: 微软推出Copilot的AI Agent和Computer Control

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

重写(外壳不变)

重写&#xff1a;是子类对父类非静态、非private修饰、非final修饰、非构造方法等的实现过程进行重新编写返回值和形参都不能改变。 重写的好处&#xff1a;子类可以根据需要&#xff0c;定义专属于自己的行为。&#xff08;子类能够根据需要实现父类的方法&#xff09; 方法…

封装echarts组件,即插即用(附源码)

前言&#xff1a;最近一个项目刚收工&#xff0c;分享一个常用的封装echarts的组件。 一、直接上组件代码 <template><el-card class"echart-card" shadow"hover"><template v-slot:header><div class"card-header">&…

JS面试八股文(三)

&#x1f60a;文章目录 21.说一下事件循环22.ajax是什么&#xff1f;怎么实现&#xff1f;23.get和post有什么区别&#xff1f;24.Promise的内部原理是什么&#xff1f;它的缺点是什么&#xff1f;25.Promise和async await的区别是什么&#xff1f;26.浏览器的存储方式有哪些&a…

python实战(二)——房屋价格回归建模

一、任务背景 本章将使用一个经典的Kaggle数据集——House Prices - Advanced Regression Techniques进行回归建模的讲解。这是一个房价数据集&#xff0c;与我们熟知的波士顿房价数据集类似&#xff0c;但是特征数量要更多&#xff0c;数据也要更为复杂一些。下面&#xff0c;…

Linux 命令行查看当前目录的总大小/总磁盘空间/磁盘清理

一、du 查看目录空间大小 &#xff08;一&#xff09; du 命令解析 在Linux命令行可以使用 du 命令来查看当前目录的总大小。du 是 disk usage 的缩写&#xff0c;表示磁盘使用情况。 命令解释&#xff1a;总结每个文件的磁盘使用情况&#xff0c;递归地用于目录。 使用格式…

以通俗易懂的仓库来讲解JVM内存模型

JVM内存模型可以想象成一个大型的仓库&#xff0c;这个仓库被分成了几个不同的区域&#xff0c;每个区域都有特定的用途和规则。下面我们用一个仓库的比喻来介绍JVM内存模型&#xff1a; 仓库大门&#xff08;JVM启动&#xff09;&#xff1a; 当JVM启动时&#xff0c;就像打开…

自动化抖音点赞取消脚本批量处理

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

多个立方体盒子组成

效果&#xff1a; 知识了解&#xff1a; 在同一水平上&#xff0c;盒子经纬度计算&#xff1a;经度有误差&#xff0c;纬度没有误差 纬度计算&#xff1a;lat50/111320 约等于0.000449 经度计算&#xff1a;lon50/111320*cos(纬度) 约等于0.000519 一个立方体&#xff1a; // 添…

CentOS进入单用户模式进行密码重置

一、单用户模式介绍 单用户模式是一种特殊的启动模式&#xff0c;主要用于系统维护和故障排除。在单用户模式下&#xff0c;系统以最小化的状态启动&#xff0c;只有最基本的系统服务会被加载&#xff0c;通常只有root用户可以登录。这种模式提供了对系统的完全控制&#xff0…

模型训练识别手写数字(一)

一、模型训练数据集 1. 导入所需库 import numpy as np from sklearn.datasets import fetch_openmlnumpy 是用于数值计算的库。 fetch_openml 是用于从 OpenML 下载数据集的函数。 2. 获取 MNIST 数据集 X, y fetch_openml(mnist_784, version1, return_X_yTrue)fetch_ope…

Spring Boot与Flyway实现自动化数据库版本控制

一、为什么使用Flyway 最简单的一个项目是一个软件连接到一个数据库&#xff0c;但是大多数项目中我们不仅要处理我们开发环境的副本&#xff0c;还需要处理其他很多副本。例如&#xff1a;开发环境、测试环境、生产环境。想到数据库管理&#xff0c;我们立刻就能想到一系列问…

Ovis原理解读: 多模态大语言模型的结构嵌入对齐

论文&#xff1a;https://arxiv.org/pdf/2405.20797 github:https://github.com/AIDC-AI/Ovis 在多模态大语言模型 (MLLM) 中&#xff0c;不同的嵌入策略有显著的区别。以下是使用基于连接器的方法与 Ovis 方法的比较&#xff1a; 基于连接器的方法-优缺点(connector-based …