【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 可以直接使用auto
for (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::npos
是std::string
类中的一个静态成员变量,npos
的值通常设置为size_t
类型(无符号整形)的最大值,用于表示一个不可能在字符串中出现的位置。#include<iostream> #include<string> using namespace std; int main() { string s1("hello world"); cout << s1.find("world") << endl; //输出下标位置为6 cout << 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'最后一次出现的位置,输出下标位置9 cout << 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位置的子串赋值给s2 string 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
类的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!