【C++修炼之路】8. string类详解(一)

简介: 【C++修炼之路】8. string类详解(一)

C++之string类


本节目标

1. string类概览

1.1 string的由来

1.2 string函数列表

2.string常用接口

1. 初始化

2. string::npos

3. c_str()

4. 获取长度(length、size)

5. 容量(size、capacity)

6. 插入(insert)

7. 替换(replace)

8. 添加(append、push_back、+=)

9. 赋值(assign)

10. 删除与判空(erase、clear、empty)

11. 剪切(substr)

12. 比较(compare)

13. 交换(swap)

14. 反转(reverse)

15. 迭代器(iterator)

15.1 正向迭代器

15.2 反向迭代器

15.3 const迭代器

16. 搜索与查找(find等函数)

16.1 find()函数

16.2 rfind函数

16.3 find_xxx_of()函数(功能强大,但不常用)

3. string类的应用

3.1 三种遍历方式

3.2 替换空格

3.3 通过find取后缀

3.4 getline的应用

4. string总结


本节目标


熟练掌握各种string类的函数并将其应用。

注:本文参考以下两篇优秀文章,将其结合并加上额外的知识用自己的理解进行描述:

C++之string类型详解

C++string类型详解


1.string类概览


1.1 string的由来


之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个泛型类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做串联(是不是很简单?)。我们尽可以把它看成是C++的基本数据类型。


C++中对于string的定义为:typedef basic_string string; 也就是说C++中的string类是一个泛型类,由模板而实例化的一个标准类,本质上不是一个标准数据类型。


在我们的程序中使用string类型,我们必须包含头文件 。如下:

#include using namespace std; 此语句必不可少,否则有的编译器无法识别


1.2string函数列表


begin 得到指向字符串开头的Iterator

end       得到指向字符串结尾的Iterator

rbegin 得到指向反向字符串开头的Iterator

rend 得到指向反向字符串结尾的Iterator

size   得到字符串的大小

length 和size函数功能相同

max_size 字符串可能的最大大小

capacity 在不重新分配内存的情况下,字符串可能的大小

empty 判断是否为空

operator[] 取第几个元素,相当于数组

c_str 取得C风格的const char* 字符串

data 取得字符串内容地址

operator= 赋值操作符

reserve 预留空间

swap 交换函数

insert 插入字符

append 追加字符

push_back 追加字符

operator+= += 操作符

erase 删除字符串

clear 清空字符容器中所有内容

resize 重新分配空间

assign 和赋值操作符一样

replace 替代

copy 字符串到空间

find 查找

rfind 反向查找

find_first_of 查找包含子串中的任何字符,返回第一个位置

find_first_not_of 查找不包含子串中的任何字符,返回第一个位置

find_last_of 查找包含子串中的任何字符,返回最后一个位置

find_last_not_of 查找不包含子串中的任何字符,返回最后一个位置

substr 得到字串

compare 比较字符串

operator+ 字符串链接

operator== 判断是否相等

operator!= 判断是否不等于

operator< 判断是否小于

operator>> 从输入流中读入字符串

operator<< 字符串写入输出流

getline 从输入流中读入一行


2.string常用接口


对于这些用法来说,下面传入的参数个数在同一个用法中都有所差异,这是因为每一个成员函数都支持了重载。


在介绍下述接口之前,需要知道的是,由于每一个函数都有重载,因此有的有const的重载,有的没有,其实这是以函数的需求从而判断其有无const类型的重载函数,这里提前进行总结:


只读功能函数 const版本

只写功能函数 非const版本

读写功能的函数 const+非const版本



1.初始化


初始化有两种方式,其中使用等号的是拷贝初始化,不使用等号的是直接初始化。(注释后面是打印的结果)

但对于使用等号的和str(str1),即一个变量通过另一变量初始化的,都是拷贝构造。(深拷贝


string str1 = "hello world";      // str1 = "hello world"
string str2("hello world");       // str2 = "hello world"
string str3 = str1;               // str3 = "hello world"
string str4(str2);                // str4 = "hello world"
string str5(10,'h');              // str5 = "hhhhhhhhhh"
string str6 = string(10,'h');     // str6 = "hhhhhhhhhh"
string str7(str1,6);              // str7 = "world"     从字符串str1第6个字符开始到结束,拷贝到str7中
string str_7(str1,6,3); // str_7 = "wor"     从字符串str1第6个字符开始的三个字符,拷贝到str7中
string str8 = string(str1,6);     // str8 = "world"
string str9(str1,0,5);            // str9 = "hello"     从字符串str1第0个字符开始,拷贝5个字符到str9中
string str10 = string(str1,0,5);  // str10 = "hello"
char c[] = "hello world";
string str11(c,5);                // str11 = "hello"    将字符数组c的前5个字符拷贝到str11中
string str12 = string(c,5);       // str12 = "hello"


2.string::npos


我们观察一下上面str7与str_7的区别,想必大家已经看出,这里的str7和str_7是同一个重载函数,并且这个函数具有缺省值,当我们不传入最后一个参数时,其就会一直拷贝到字符串的末尾为止。那这个缺省参数是什么呢?我们查阅文档得知,是npos:

微信图片_20230225131942.png

微信图片_20230225131901.png

我们发现,npos的值规定为-1,但实际上因为是size_t类型,所以这是一个无符号的数字,即此-1并不是十进制的-1,而是:4294967295

微信图片_20230225131904.png

因此,此位置重载在不输入数值时默认为此值,也就能够遍历到字符串的末尾了。


此外,对于内置的string类,是支持运算符重载的,因此同样的也支持流的相关重载,即cin、cout:


string str1 = "hello world";     
cout << "str1 = " << str1;    //输出: str1 = hello world

3. c_str()

微信图片_20230225132032.png

对于string类来说,其内部有这么一个成员变量,c_str,正如此图,c_str本身和指向的值均不能改变,返回值是char*实际上返回的就是string类中的内容的地址,也就是字符串的地址。

微信图片_20230225132037.png

那c_str有什么作用呢?事实上对于一些线程,网络,Linux内核等都是通过C实现的,因此c_str很好的充当了一个C++中string与C之间的互通,因为我们知道,对于string定义的变量名,不是内部字符串的地址,因此就出现了c_str()返回内容的地址,从而解决这个问题。


演示:


微信图片_20230225132106.png

结果:

微信图片_20230225132109.png


这样就将其内容正确的打开了。


4.获取长度(length、size)


length()函数与size()函数均可获取字符串长度。但除了string,其他类型就只有size()。


string str = "hello world";
cout << str.length() << str.size();     // 11   11

当str.length()与其他类型比较时,建议先强制转换为该类型,否则会意想之外的错误。

比如:-1 > str.length() 返回 true。


容量(size、capacity)


对于size和capacity来说,大家在学了顺序表之后并不陌生,size是实际长度,而capacity代表着容量的大小,对于string类来说,其也具有这样的成员变量(对应值C语言顺序表中结构体内部的的size、capacity),而这里的扩容规则在每一个平台也是不一样的,比如我的linux和vs2019二者之间就有很大的区别,不过我们并不需要关心他,因为string作为内部类,其扩容的机制已经被写在该类之中。


string str;     
str += "hello world hello world";


微信图片_20230225132225.png


微信图片_20230225132230.png


可以看出,其大概是是扩容了二倍的大小。


此外,还有其他函数也属于容量的范畴:


微信图片_20230225132314.png

resize可以改变成员的size()的大小。

reserve可以改变成员的capacity()的大小。


微信图片_20230225132341.png

而对于max_size(),这里我们只打印结果就知道其具体的含义:

微信图片_20230225132345.png


6. 插入(insert)


微信图片_20230222000856.png

string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
//s.insert(pos,n,ch)        在字符串s的pos位置上面插入n个字符ch
str.insert(6,4,'z');        // str = "hello zzzzworld"
//s.insert(pos,str)         在字符串s的pos位置插入字符串str
str.insert(6,str2);         // str = "hello hard world"
//s.insert(pos,str,a,n)     在字符串s的pos位置插入字符串str中位置a到后面的n个字符
str.insert(6,str3,6,9);     // str = "hello so happy world"
//s.insert(pos,cstr,n)      在字符串s的pos位置插入字符数组cstr从开始到后面的n个字符
//此处不可将"it is so happy wow"替换为str3
str.insert(6,"it is so happy wow",6);       // str = "hello it is world"


虽然有这样的接口,但是我们知道对于类似于顺序表的结构来说,这样的插入,实际上底层都会将后面的数据进行挪动,因此效率难免会低一些。


7.替换(replace)


替换与插入对应,对比理解更为简单。


微信图片_20230225132435.png


string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
//s.replace(p0,n0,n,ch)           删除p0开始的n0个字符,然后在p0处插入n个字符ch
str.replace(0,6,4,'z');           // str = "zzzzworld"
//s.replace(p0,n0,str)            删除从p0开始的n0个字符,然后在p0处插入字符串str
str.replace(0,6,str2);            // str = "hard world"
//s.replace(p0,n0,str,pos,n)      删除p0开始的n0个字符,然后在p0处插入字符串str中从pos开始的n个字符
str.replace(0,6,str3,6,9);        // str = "so happy world"
//s.replace(p0,n0,cstr,n)         删除p0开始的n0个字符,然后在p0处插入字符数组cstr的前n个字符
//此处不可将"it is so happy wow"替换为str3
str.replace(0,6,"it is so happy wow",6);        // str = "it is world"



8. 添加(append、push_back、+=)


append函数用在字符串的末尾添加字符和字符串。(同样与插入、替换对应理解)而push_back只适用于添加单个字符,此外,对于添加来说,如果是在末尾添加字符或者字符串我们仍然可以像初始化中的拷贝构造一样,即通过+=进行添加。


微信图片_20230225132513.png

微信图片_20230225132519.png

微信图片_20230225132522.png


string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
string str4 = "hello world"
//s.append(n,ch)           在当前字符串结尾添加n个字符c
str.append(4,'z');         // str = "hello worldzzzz"
//s.append(str)            把字符串str连接到当前字符串的结尾
str.append(str2);          // str = "hello worldhard "
//s.append(str,pos,n)      把字符串str中从pos开始的n个字符连接到当前字符串的结尾
str.append(str3,6,9);      // str = "hello worldso happy "
//append(cstr,int n)       把字符数组cstr的前n个字符连接到当前字符串结尾
//此处不可将"it is so happy wow"替换为str3
str.append("it is so happy wow",6);      // str = "hello worldit is "
str4.push_back('c'); // str4 = "hello worldc"
str4 += 'c';         // str4 = "hello worldcc"
st4 += "cdef";       // str4 = "hello worldcccdef"

9. 赋值(assign)

微信图片_20230225132615.png


赋值也是一种初始化方法,与插入、替换、添加对应理解较为简单。

string str;
string temp = "welcome to my blog";
//s.assign(n,ch)             将n个ch字符赋值给字符串s
str.assign(10,'h');          // str = "hhhhhhhhhh"
//s.assign(str)              将字符串str赋值给字符串s
str.assign(temp);            // str = "welcome to my blog"
//s.assign(str,pos,n)        将字符串str从pos开始的n个字符赋值给字符串s
str.assign(temp,3,7);        // str = "come to"
//s.assaign(cstr,n)          将字符数组cstr的前n个字符赋值给字符串s
//此处不可将"it is so happy wow"替换为temp
str.assign("welcome to my blog",7);     // str = "welcome"


10.删除与判空(erase、clear、empty)


对于clear,其具有清空的功能,也就是从任意的字符串使用clear,都会将其清空至空字符串;对于erase来说,其可以指定的删除,也就是说可以删除一部分,也可以删除全部。


string str = "welcome to my blog";
//s.erase(pos,n)           把字符串s从pos开始的n个字符删除
str.erase(11,3);           // str = "welcome to blog"
str.clear();               // str = ""
str.empty();               // 返回1

clear()实际上不会将capacity的空间也清除掉,即size会改变,但capacity并不会改变。

对于empty来说,实际上是判断是否为空的函数,是空就返回1,不是空就返回0,因此empty是根据size()是否为0判断的。

相关文章
|
8月前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
8月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
4月前
|
对象存储 C++ 容器
c++的string一键介绍
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。
88 3
|
4月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
94 0
|
4月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
82 0
|
4月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
172 0
|
6月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
183 12
|
7月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
131 16
|
7月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
153 11
|
8月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)