C++-带你深度理解string类的常见接口

简介: C++-带你深度理解string类的常见接口

1. 为什么学习string类?


C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。


在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本 都使用string类,很少有人去使用C库中的字符串操作函数。


2. 标准库中的string类


2.1 string类(了解)

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架。


string比STL出现的还要早,所以不包含在contain的类别里面,但也算是一种数据结构。


1. 字符串是表示字符序列的类

2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。

3. string 类是使用 char( 即作为它的字符类型,使用它的默认 char_traits 和分配器类型 ( 关于模板的更多信息,请参阅basic_string) 。

4. string 类是 basic_string 模板类的一个实例,它使用 char 来实例化 basic_string 模板类,并用 char_traits和allocator 作为 basic_string 的默认参数 ( 根于更多的模板信息请参考 basic_string) 。

5. 注意,这个类独立于所使用的编码来处理字节 : 如果用来处理多字节或变长字符 ( 如 UTF-8) 的序列,这个类的所有成员( 如长度或大小 ) 以及它的迭代器,将仍然按照字节 ( 而不是实际编码的字符 ) 来操作。

总结:

1. string是表示字符串的字符串类

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,typedef basic_string string。

4. 不能操作多字节或者变长字符的序列。

在 使用 string 类时,必须包含 #include 头文件以及 using namespace std ;

2.2 string类的常用接口说明

2.2.1string的构造

6c870f48ad4a41a99641fed0c1f25521.png

97e08afb19914a96989d3c2bf4c253c3.png

首先给大家介绍无参的string构造,以及使用字符串构造,还有拷贝构造这三种最常用的构造方式。如果想打印string类的对象直接使用cout即可,因为string类重载了流插入和流提取。

int main()
{
  //string(),构造空的string类对象s1
  string s1;
  //string(const char* s),用C格式字符串构造string类对象s2
  string s2("hello world");
  //string(string s),拷贝构造s3
  string s3(s2);
    cout<<s3<<endl;
  return 0;
}

c2fb65af216444b3970b441305ed2c77.png

2.2.2string的析构

string相当于是一个管理字符串的顺序表,也就是字符串数组,内部的数组的是动态开辟的,需要释放,但是这个析构函数是自动调用的。

1b50618f989544fcbec8216c13005523.png

2.2.3string的赋值重载


10d24af2da8c431e98f5fcac947e1e49.png

string类的赋值重载有三个,用的最多的还是前面两个。

int main()
{
  string s1("hello c++");
  string s2 = s1;
  string s3 = "hello c++";
  cout << s2 << endl;
  cout << s3 << endl;
  return 0;
}

e37ff5d0528f4969875f1c097dd67aea.png

2.2.4 string类对象的容量操作

2.2.4.1size和length

string类的size和length接口是完全一样的,只是由于STL的发展历史原因,后面才出现的size。虽说length出现的早,但是实际上size用的更多,都不包含/0。

20423a5f88c049be8aea096e551297df.png

b7cdf7097c734655b72e76ffa07c8f40.png

2.2.4.2operator[]

2301876b4ea04aca9e5ffc0f4f1a573f.png 那么我们怎么遍历一个string类的对象呢?使用[]是比较方便的,也更加容易理解,因为原始数组就是用的[]遍历的,[]就是operator[],运算符重载。

int main()
{
  string s1 = "hello world";
  for (int i = 0; i < s1.size(); i++)
  {
  cout << s1[i] << " ";
  }
  cout << endl;
  return 0;
}

87feb2ac219e43619a06061399c7c930.png

[]不仅可以读,也可以写,因为返回值是起始字符的引用。

int main()
{
  string s1 = "hello world";
  for (int i = 0; i < s1.size(); i++)
  {
  cout << s1[i];
  }
  cout << endl;
  s1[0] = 'z';
  cout << s1 << endl;
  return 0;
}

579c2aa3b3484172a78b67dfd5a4fc73.png

[]在字符串的遍历这方面也挺方便的,用起来跟数组的下标一样。

591455221f3f4f188ee4840ac18f87b6.png

2.2.4.3c++的swap

c++的库里面有一个swap函数,用起来非常的方便,库里面的swap是一个函数模板,所以可以支持各种数据类型。

395508e3d96948ebbaff3a96ed9fff36.png

2.2.4.4迭代器

c++里面还有一个东西可以支持大部分数据类型的的遍历,那就是迭代器(iterator),迭代器不仅可以遍历,还可以修改,迭代器是主流的访问容器的一种方式。下标和[]适用于物理空间上是连续的情况,链式结构,树形结构,哈希表等就只能用迭代器来遍历。

e3d50a3d15c7463e84f6b5ca71f38742.png

注意:const_iterator是const迭代器,它的目的是使迭代器指向的内容不能被修改,而不是迭代器本身不能被修改。


2.2.4.5rbegin

3492d75feed34e27a57bcd48b32e1223.png

如果我们想倒着访问string类的对象,可以使用反向迭代器reverse_iterator,rbegin指向最后一个字符,rend就是第一个字符,it++就是向前遍历。

bf65b348f1414ada9fdf2853acbfe490.png

2.2.4.6reserve

reserve就是保留的意思,可以给string预留空间,也就是开空间,在我们知道需要多少空间时,可以用reserve提前开好空间,reserve只影响容量,不会影响数据,当然各个编译器的机制不一样。

85f562efbecf476fb0fab57828dc9e04.png

2.2.4.7capacity

01f03baa95a54f0e84e306e520da7bfd.png

capacity就是容量,代表的是实际能存放多少个字符,而不是实际空间有多大,因为最后还有\0,\0不算是有效字符,是个标识符,实际空间比capacity大一,因为要留个空间存放\0。

int main()
{
  string s1 = "hello zxf";
  string::reverse_iterator it = s1.rbegin();
  while (it != s1.rend())
  {
  cout << *it;
  it++;
  }
  cout << endl;
  s1.reserve(30);
  cout << s1 << endl;
  cout << s1.capacity() << endl;
  return 0;
}

6ffb4d05c5184d2fb0cbaa94e4eb6e53.png

2.2.4.8resize

901ad341afca4328820d803286df24fd.png

大家再来看一下resize这个接口,resize既影响容量,也会影响数据,resize之后的容量肯定要比resize的数据要大,保证空间足够,size则为resize的大小,resize如果比之前的容量大,则会发生扩容,那么resize之后的数据既然是100了,那么当我们打印出来的时候,为什么什么都看不见呢?因为后面的数据全部都是\0。如果不想让后面是\0,就可以使用resize的一个重载,这个重载的第二个参数是一个字符。意思就是如果显示传了这个字符,那么后面插入的字符就是该字符,如果没有传的话,则是\0这个空字符。

fa47e8645a9e4d26bb642e1fa428d971.png

6467564297264d049849e44ad4690a59.png

在vs编译器上,如果resize的数据在size和capacity之间的话,那么size会发生变化,capacity不会变。

12faf227379a4c2a9d8c3e0b91bcf72a.png

在vs编译器上,如果resize的数据小于size,那么size会减小,并且数据会删除,capacity不会变。

578e2191788147649e6decc94f4f358e.png

总结:


1.resize数据>capacity,扩容+尾插


2.size


3.resize数据


2.2.4.9push_back

push_back这个函数一次只能尾插一个字符,效率太低了,因此我们可以使用append。

10d07bad7e63484da9e0b0caf7a5553f.png

2.2.4.10append

append函数有许多个重载,使用的方法也很简单,就不一一介绍了。

095ef17126964402a8566a9f3eeeea31.png

6840431ea9144ed18ab96528233c35e5.png


2.2.4.11operator+=

d88b69d595e2425eb25cf5fce3d99cbf.png

虽然append实现了这么多重载,但是有一个接口更加好用,就是运算符+=的重载。+=不仅更加的方便,并且代码的可读性也变强了。

5fb8aea31d1d4bfb92a4542f54bd3cf6.png

2.2.4.12insert

insert这个接口只要第一个和第三个重载用的最多,在某个位置插入字符串或者string类的对象。

e68ff7334bc9453ba39bbf2190e4a0dc.png

2.2.4.13erase

erase用法也很简单,不做过多说明。

ae734634c9664c91989f55f228889476.png

2.2.4.14assign

assign相当于赋值,也有许多个重载。

26a49b7843b6459e887a9a20f7e64d68.png

0f7f2814108741cb872833bae53ae05b.png

2.2.4.15replace

replace就是替换的意思,虽然看起来很好用,但是成本比较高,不太推荐使用。

4ae1574e2bb243ab856d5798f7c2489e.png

617dd02e2123470b8ca59bfc283a2f6d.png

2.2.4.16find

find就是查找某个字符,可以从任意位置开始查找,返回的是这个字符的下标,不给开始查找的位置则默认为0,如果找不到的话返回值是整型的最大值.

74f420bfe73b47209633bd2ebed9c0b6.png


2426a3c764cc4185819c30f1f8855606.png

2.2.4.17copy

b2c1298a493141a2bd6589e96da8296e.png

copy就是拷贝string类对象的一部分到一个数组里面去,下面这段代码就是从拷贝下标为4的位置开始拷贝,拷贝长度为6的字符。

8d6502c7b4ca4f4f9039882e616a9295.png

2.2.4.18find_first_of

find_first_of就是在string类的对象里面找到需要找的字符,并且返回下标,注意寻找的可以是多个。

4c296aa1124e4dfaac7536ad5184334c.png 2.2.4.19find_last_of

find_last_of就是从后往前找,用法和find_first_of是一样的。

4661231cb9f244a98ec5f4c596718426.png

2.2.4.20substr

substr就是从pos位置开始读出长度为len的字符串,返回的是string类。

936469ecf31849feb8cff272be5572aa.png

b59d9265989f427f9eda2f72d836b43f.png


今天的分享到这里就结束了,感谢大家的阅读!


相关文章
|
3月前
|
对象存储 C++ 容器
c++的string一键介绍
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。
77 3
|
3月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
75 0
|
3月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
73 0
|
3月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
155 0
|
5月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
154 12
|
6月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
6月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
6月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
134 11
|
6月前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
138 9
|
6月前
|
存储 JavaScript Java
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化