C++——string的使用

string的使用

  • [1. STL](#1. STL)
  • [2. string](#2. string)
    • [2.1 初始化和遍历](#2.1 初始化和遍历)
    • [2.2 容量相关](#2.2 容量相关)
    • [2.3 串的修改](#2.3 串的修改)
    • [2.4 其他接口](#2.4 其他接口)

1. STL

STL全称 standard template libaray------标准模板库 ,内部包含了很多数据结构和算法,数据结构包括栈,队列,树,链表等,算法包括交换,排序,查找,逆置等。是一个C++标准库的重要组成部分。STL不止含有这两部分,接下来就慢慢进入STL的学习,先从使用开始。

这里有一个网址,大家可以在这个网址上学习

https://legacy.cplusplus.com/

2. string

string就是字符串,它其实是类模板实例化出来的一个类,存储的是字符

2.1 初始化和遍历

初始化是通过构造函数进行的,先来看看有哪些吧

第一个默认构造;第二个拷贝构造,通过一个已存在的对象初始化;第三个通过存在对象的部分内容初始化;第四,五个都是通过字符串来初始化;第六个是通过n个字符初始化;最后一个是通过迭代器区间初始化。用的比较多的是第2,3,4,5个。

在string和vector(顺序表)中迭代器的使用和指针基本类似。后续会介绍迭代器具体是什么。

遍历方式1:下标 + [ ]

string类重载了operator[ ],可以通过类似数组那样的方式遍历string对象。

遍历方式2:范围for循环遍历

遍历方式3:迭代器遍历

迭代器类似指针

begin可以获得string第一个字符的地址,end可以获得string最后一个字符的下一个位置的地址。

rbegin可以获得string反向的第一个字符的地址,即最后一个字符的地址;rend可以获得string的反向的最后一个字符的下一个位置的地址。如下图

最后四个是对const对象新增的函数,但是前四个已经重载了const版本的,所以后四个不需要使用。

并且每一种容器都有迭代器,因此使用时,需要指定类域。返回值类型大家可以点进去自行查看。

对于这三种遍历,给出如下实例代码。

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;
void test2()
{
	//使用字符串来初始化,for循环+下标+ [ ]遍历
	string s1("ABCDEFG");

	//for循环
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i];
	}
	cout << endl;

	//拷贝构造初始化,范围for遍历
	string s2(s1);
	for (auto ch : s2)
	{
		cout << ch;
	}
	cout << endl;

	//n个字符初始化,迭代器遍历
	string s3(10, 'B');
	string::iterator i = s3.begin();
	while (i != s3.end())
	{
		cout << *i;
		i++;
	}
	cout << endl;

    //反向遍历
	const string s4 = s1;
	string::const_reverse_iterator ci = s4.rbegin();
	while (ci != s4.rend())
	{
		cout << *ci;
		ci++;
	}
	cout << endl;
}

int main()
{
	test2();
	return 0;
}

运行结果如下图

总结:推荐使用下标 + [ ] ,可以正向遍历,也可以逆向遍历;范围for不支持逆向遍历。迭代器可读性较差。对于后续的无法使用下标 + [ ] 遍历的,就要使用迭代器遍历了。

2.2 容量相关


sizelength都是获得字符串的大小;

string s("ABCDEFG");

cout<<s.size()<<endl;

max_size是获得可初始化的最长字符串的长度(没有什么作用);

resize 是更新string对象size的大小。
capacity是获得string对象capacity的大小,vs上默认是16

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;
void test3()
{
	string s("ABCDEFG");
	cout <<"更新前size = "<< s.size() << endl;
	cout <<"更新前capacity = "<< s.capacity() << endl;
	s.resize(20);
	cout << "更新后size = " << s.size() << endl;
	cout << "更新后capacity = " << s.capacity() << endl;
	
}

int main()
{
	test3();
	return 0;
}

运行结果如下

当更新的size超过15时,会更改capacity的大小,原因是空间不够需要扩容。

下面这段代码可以观察vs是如何扩容的。

cpp 复制代码
void test_capacity()
{
	string s;
	//保留原大小
	size_t capacity = s.capacity();
	cout << "capacity:" << s.capacity() << endl;
	//循环插入字符A,空间不够会扩容
	for (int i = 0; i < 200; i++)
	{
		s += 'A';
		//扩容时打印
		if (capacity != s.capacity())
		{
			cout <<  s.capacity() << endl;
			capacity = s.capacity();
		}
	}
}

运行结果如下

起始值是15,第一次扩容为2倍,后续都是1.5倍。扩容的消耗很大,因此如果事先能知道需要多少空间,可以一次开完全就不会造成这样的消耗了。

reserve可以扩充容量,用法如下

string s;

s.reserve(扩容后的大小)

还是上面的代码,如果实现就给好200个空间。那么就不需要扩容了。

运行结果可以看出,没有扩容,但是容量不是200,它可能多给空间,但不会少给。

但是给的数值如果小于原来的空间,这个函数就不做处理。

总结:resize会改变size,可能改变capacity;reserve会改变capacity,不会改变size

clear 可以将字符串内容清空,使之变成空串,改变size(变为0),不改变capacity
empty 判断是否是空串。
shrink_to_fit可以缩小串的容量(不建议使用,因此不做详谈)

2.3 串的修改

**operator+=**是重载的运算符,可以尾插一个字符串或字符或string对象

push_back 尾插一个字符
append 用法较多,但不如operator+=方便,可读性也不如operator+=,因此不做过多介绍。
insert 用法也比较多,这里介绍和演示几个较为常用的。

第一个 :在pos位置插入一个string对象;第三个 :在pos位置插入一个字符串;第四个 :在pos位置插入字符串的n个字符;第五个:在pos位置插入n个字符


assign 是给该字符串一个新的值,替换当前的内容,用法和初始化很类似。
erase 为删除字符

第一个 :删除pos位置的len个字符,不给实参 或者len超过字符串的长度 时,将全部删除。npos为整型的最大值。
第二个 :删除一个迭代器位置的字符
第三个:删除一段迭代器区间

swap 为交换两个string对象
pop_back为删除最后一个字符

2.4 其他接口


c_str和data 可以获得c类型的字符串。如下图

这两个函数获得的是**_str**,因为有些C语言的接口操作的是字符串,不是string对象。

find和rfind 分别是正向和反向找第一个符合条件的字符或字串。找到返回下标,找不到返回npos

比如我们要打印这句英文的第一个和最后一个单词Life is full of possibilities可以这样写。

cpp 复制代码
void test_string2()
{
	string s = "Life is full of possibilities";
	size_t pos = s.find(' ');  //拿到第一个空格的下标,即4

	string sbegin = s.substr(0,pos);//拿到字串,从下标为0到下标为pos位置之前,左闭右开 [0 ,pos)
	cout << sbegin << endl;
	size_t pos1 = s.rfind(" ");//拿到最后一个空格的下标
	string send = s.substr(pos1 + 1);//拿到字串,从pos1+1开始,没有右区间,就会取完全部字符
	cout << send << endl;
}

运行结果如下

substr为获取字串,上面已经有介绍用法了,这里看下函数原型,就不多解释了。

compar 为比较两个串的大小,原理和strcmp一样。

其他函数用的很少,大家可以自己对照文档了解。关于string常用函数接口的解释就到这里了。

相关推荐
Манго нектар25 分钟前
JavaScript for循环语句
开发语言·前端·javascript
程序猿小D34 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
阿华的代码王国42 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–01 小时前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student1 小时前
everyday_question dq20240731
开发语言·arm开发·php
卑微求AC2 小时前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
程序猿小D2 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
Yvemil72 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
潘多编程2 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring