首页 > 其他分享 >STL之string

STL之string

时间:2024-09-28 08:50:18浏览次数:3  
标签:string STL auto str 字符串 我们 size

STL之string

1. 为什么学习string类?

1.1 C语言中的字符串

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

1.2 两个面试题(暂不做讲解)

https://www.nowcoder.com/practice/1277c681251b4372bdef344468e4f26e?tpId=13&&tqId=11202&rp=6&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

https://leetcode-cn.com/problems/add-strings/

2. 标准库中的string类

2.1 string类(了解)

前置:
1、在使用string类时,必须包含#includ,这里与C语言区别没有.h
2、string里的字符串是以类似于字符顺序表的形式存储的。

首先在学习STL这一节查文档必不可少,有两个文档供我们查找,一个是cplusplus,还有一个是官方文档,但是官方文档对初学者会特别的不友好,所以我们选择cplusplus。我们怎么查呢?在这里插入图片描述
大家按照图中的方式,先打开reference,然后打开other中的string。这里面就是string的所有内容,里面我们只会选一些重要的来学习,其他的大家可以自己看看。

我们首先学一些基础操作:
在这里插入图片描述

我们需要点进string。
在这里插入图片描述
然后我们再点进下面的constructor
在这里插入图片描述
c++98里的函数就是我们目前需要学的

那我们就先来简单的使用一下string,再来学上面的函数

#include<iostream>
using namespace std;

int main()
{
	string s1;//默认构造
	string s2("1111111");//传参构造
	string s3(s2);//拷贝构造

	cin >> s1;
	cout << s1 << endl;

	return 0;
}

在这里插入图片描述
大家可以看到string是重载了流插入与流提取的,所以我们是可以直接使用cin>>与cout<<的。

现在我们开始看文档,在这个文档里下面的英文部分是对上面函数的使用方式说明
在这里插入图片描述
在读文档时,这里的技巧是“蒙”,当然不是毫无根据的蒙,我们是有根据的蒙,例如 string (const string& str, size_t pos, size_t len = npos):
pos在英文中是position的前面的部分,那我们就猜测它是定位的意思,len是lenth的缩写,那我们就猜测是长度的意思,那连起来我们就猜测这个函数是拷贝指定位置后的len个长度到目标string里,那我们就来试一下?

在这里插入图片描述
这里我们有个问题,上面我们只拷贝了5个字符,那要是我们拷贝6个或者更多(字符长度不够)会发生什么呢?这个时候我们需要看文档,看文档需要我们下来自己完成,这里我们直接给结论,只会将该字符串读完,并且如果我们我不写len的长度,该函数也会有一个npos,它是直接从pos位置直接将字符串读完。
在这里插入图片描述
大家可能会好奇npos是什么呢?
在文档中可以看到,npos=-1,但这里是补码,它转换为无符号会变为整形最大值。
在这里插入图片描述

前四个我们其实已经完成了,我们来看第5个函数(string (const char* s, size_t n);)(拿前n个字符初始化),这里就不带大家一步一步来看了,大家自己读一下文档。
在这里插入图片描述

string (size_t n, char c),这个函数我们通过读文档大概可以知道,它的意思是n个字符c来初始化。
在这里插入图片描述

然后我们来看string的析构,就是进入下面这个。

在这里插入图片描述
上面我们说了,string底层是动态开辟的数组,那我们需要析构吗?析构函数是自动调用的,这一块我们可以不用管,当然有兴趣可以下来自己了解。

下面我们来看一个string特别牛的东西:
在这里插入图片描述
它的底层大概是这样的:

class string
{
private:
	char* _str;
	size_t _size;
	size_t _capacity;
public:
	char& operator[](size_t i)
	{
		return _str[i];
	}
};

也就是我们可以直接通过[]来访问任意位置的字符,并且我们返回的时引用,所以我们是可以修改的。
示例:
在这里插入图片描述
这一块在后续的学习中会非常的方便。

下面我们来学习遍历输出字符串:
(1)下标加[]
首先string是有很多函数的,其中有个叫做size的可以返回字符串中字符个数
在这里插入图片描述
其他的函数大家下来自己去看文档来使用,那我们就可以通过上面的方式来遍历输出字符。

(2)迭代器(***重点)

string::iterator it = s1.begin();
while (it != s1.end())
{
	cout << *it << ' ';
	it++;
}

我们可以将it理解为指针,但它并不一定是指针,begin是首字符的地址,end是尾字符下一个字符的地址(也就是’\0’),当it不为指针时,* 可能是运算符重载 (在list里我会介绍)

迭代器是一个很重要的东西,因为所有的容器,迭代器都可以使用,例如链表:

list<int> lt = { 1,2,3,4,5,6,7 };
list<int>::iterator lit = lt.begin();
while (lit != lt.end())
{
	cout << *lit << ' ';
	++lit;
}

上面的iterator我们称之为正向迭代器,此外还有一个东西叫做反向迭代器,reverse_iterator,它的用法如下:

在这里插入图片描述
反向迭代器可以用于链表,图,树等结构。

const迭代器,如果我们的字符串加了const修饰,那么我们的迭代器就不可以使用了,因为在上面的迭代器中我们的串可读可写,这时候就需要const迭代器(只可读)

const string s1("hello world");
string::const_iterator cit = s1.begin();
while (cit != s1.end())
{
	cout << *cit << ' ';
	cit++;
}
cout << endl;

const反向迭代器是一样的,大家自己下来写一下就行。

总结一下:迭代器一般有四种。

(3)范围for

下面讲。

然后我们来看capacity部分
在这里插入图片描述
1、首先lenth与size其实都是一样的(求字符长度),lenth是c++早期为了适应c语言而使用的,但在c++更新了STL后,在图等数据结构中lenth是不太合理的,所以c++就更新了size,总而言之size适用范围更广。

2、max_size是字符能开多少空间,这个用处不大

3、capacity,字符数组当前容量(不包含\0)

在这里插入图片描述
这段代码可以简单的来观察一下容量的变化,大家可以看到从15到31,实质上是16->32,因为数组最后一个空间存“\0”,只有这一部分是成2倍增长的,之后是成1,5倍增长的,这是为什么呢?

class String
{
private:
	char buffer[16];
	char* _str;
	size_t _size;
	size_t _capacity;
public:
};

string在官方库里是有一个buffer的数组的,如果字符串小于16就存于这里,如果大于就会存在下面的动态数组里,buffer就会被销毁。在linix环境下是标准的2倍增,且没有buffer数组。

当然扩容不建议扩的次数太多,因为扩容也会有消耗,所以c++引入了reserve(将空间一次性开好)
在这里插入图片描述
如果我们开100空间,这个100是不包括\0,所以如果不整数对齐的话也会开101。
此外如果我们要申请的空间如果小于当前的capacity,那空间会不会缩水呢?
结论:一般是不会的,但是不能
n<10不会缩
10<n<20不确定
大于20一定会扩
4、clear(清空)
在这里插入图片描述
这里明白clear清空,只清空数据,不清空容量就行了。

5、empty(判空)

这里大家自己简单了解一下就行。

6、shrink_to_fit(缩容),将capacity缩到size

2.2 auto和范围for(重点)

在这里插入图片描述
这里的auto在c++里叫做“自动推导”,它也很好用,它的特性是自动赋值,自动迭代,自动结束。
它虽然看起来很厉害,但它的底层就是迭代器,所以所有的容器也支持范围for。

除此之外迭代器是支持运算的:
在这里插入图片描述
大家可以看这里,迭代器转换后原来的字符串被改变了,但是我们让范围for恢复却并没有成功,这是因为ch是s1的拷贝,如果我们希望其能够改变的话,需要加&引用。
在这里插入图片描述

                                auto关键字
在这里补充2个C++11的小语法,方便我们后面的学习。
1、在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个
不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型
指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期
推导而得。
2、用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际
只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
3、auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
4、auto不能直接用来声明数组

auto最大的作用是简化代码。
此外auto还可以用来简化数组的输出,例如:

int arr[] = { 1,2,3,4,5 };
for (auto& it : arr)
	cout << it << ' ';
cout << endl;

总结一下范围for适用于容器与数组。

我们再介绍一个东西叫做typeid,这个函数可以来查看变量的类型,例如:

在这里插入图片描述

2.3 string类的常用接口说明(注意下面我只讲解最常用的接口)

1、插入型接口。
在这里我只简单的介绍一下字符插入与字符串插入;
(1)push_back(1个字符插入)
(2)append(字符串插入)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这两个接口实际用的比较多,但是string重载了+=运算符,我们可以通过+=来插入字符或字符串。
在这里插入图片描述

上面的函数都是尾插,我们如果要实现任意位置插入怎么办呢?
(3)insert(给定位置插入)
在这里插入图片描述
这里比较冗余,我们只需要记住3、4这两个方式即可,一个是在pos前插入一个字符,一个是插入n个字符,如果pos为字符串首个位置,这就是头插了。

string str1;
str1.insert(0, "hello school");//头插
cout << str1 << endl;
str1.insert(12, "!");//尾插
cout << str1 << endl;

(4)erase(删除字符或字符串)
在这里插入图片描述

void test4()
{
	string str("hello world");
	str.erase(0, 1);//第0个位置开始,删除一个字符,也就是头删
	str.erase(0, 3);//删除3个字符
	cout << str << endl;

	str.erase(str.begin());//迭代器版本头删
	cout << str << endl;

	str.erase(--str.end());//尾删
	cout << str << endl;
}

(5)replace(替换)
在这里插入图片描述
在这里插入图片描述
(6)find(查找字符)
在这里插入图片描述
这个函数我们是需要关心它的返回值的。
在这里插入图片描述
这里的意思就是如果找到了就返回第一个所找字符的下标,如果没有找到的话就返回npos。
在这里插入图片描述
上面替换这道题当空格特别的多的时候,程序就会特别的低效,我们可以使用另一种思路:

//现在有这样一个题目就是将字符串中空格全部替换为%,这时候就可以使用find+replace。
string str("h l l o !");
size_t z = str.find(" ");
while (z != string::npos)
{
	str.replace(z, 1, "%");
	z = str.find(" ",z+1);//z是替换的位置
}
cout << str << endl;
//第一种思路,如果替换不多可以使用

string tep;
for (auto e : str)
{
	if (e == ' ')
		tep += '%';
	else
		tep += e;
}
cout << tep << endl;
//第二种以空间换时间

(7)rfind从尾查找,substr(字串)

string str("test.cpp");
size_t pos = str.rfind('.');
string sub = str.substr(pos);//从pos开始取子串,如果后面不给参数,默认取完
cout << sub << endl;

(8)
在这里插入图片描述

这四个接口大家下来自己读文档解决。(不太重要)
(9)非成员函数
在这里插入图片描述
第一个重载+,为什么这里将它设置为非成员函数呢?这是为了满足如下操作:
在这里插入图片描述
如果将其设置为成员函数,我们之前讲过成员函数的第一个参数是隐式的this,那样就不能字符串+string了。

swap就是直接交换即可。

最后就是getline这个函数
我们需要在题目中来看:
在这里插入图片描述
这道题我们直接使用rfind找到最后一个空格的位置,然后用size来减即可。
在这里插入图片描述
大家可以看到正确但是应该是1,但是这里是5,这是为什么?
在流输入中编译器会默认使用空格或者\0来分割字符串,空格会存在缓冲区,并且空格不会被使用,所以s1只存了asull这5个字符,所以这里需要我们使用getline这个函数
在这里插入图片描述
它的作用是默认将\0作为字符串结束标志,此外getline是支持其他的字符串结束标志的

在这里插入图片描述
我们只需要在最后补上我们需要作为字符串结束标志的字符即可。

这一部分就是string的使用介绍,下一章我们就来尝试来写string。

标签:string,STL,auto,str,字符串,我们,size
From: https://blog.csdn.net/2401_87257864/article/details/142610422

相关文章

  • 【C++】string中常用的接口
    目录前言常用接口1.有/无参string2.字符串相加3.string类对象的访问及遍历操作3.1普通遍历3.2迭代器遍历3.3范围for4.string类对象的修改操作前言今天分享一些个人认为string常用的接口,大多数资料来自于cplusplus,其他不常用的平常查阅资料使用即可。需要测试代......
  • STL05——手写一个简单版本的红黑树(500+行代码)
    STL05——手写一个简单版本的红黑树题目描述在STL中,红黑树是一个重要的底层数据结构,本题需要设计一个RedBlackTree类,实现如下功能:1、基础功能构造函数:初始化RedBlackTree实例析构函数:清理资源,确保无内存泄露2、核心功能在RedBlackTree中插入一个节点在RedBlack......
  • STL之vector篇(下)(手撕底层代码,从零实现vector的常用指令,深度剖析并优化其核心代码)
    文章目录1.基本结构与初始化1.1空构造函数的实现与测试1.2带大小和默认值的构造函数1.3使用迭代器范围初始化的构造函数(建议先看完后面的reserve和push_back)1.4拷贝构造函数1.5赋值操作符的实现(深拷贝)1.6析构函数1.7`begin`与`end`迭代器2.容量管理2.1`re......
  • 【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
    文章目录从零实现C++Vector前言1.基本结构与初始化细分1.1空构造函数的实现与测试实现代码:测试用例:输出:1.2带大小和默认值的构造函数实现代码:测试用例:输出:1.3拷贝构造函数实现代码:测试用例:输出:1.4赋值操作符的实现实现代码:测试用例:输出:2.容量管理的实现与测......
  • C++ 标准模板库(STL)之集合(set)
    啊,哈喽,小伙伴们大家好。我是#张亿,今天呐,学的n钱买n鸡是集合(set)C++标准模板库(STL)之集合(set)(下面代码中的std::要去掉)在C++标准模板库(STL)中,set 是一种非常有用的容器,用于存储唯一元素的集合。set 内部自动对元素进行排序,通常使用红黑树(Red-BlackTree)实现,以保证元素以升......
  • 将对象的属性为数值型的转换为String
    将对象的属性为数值型的转换为String1、新建一个类//注意:此处为待转换的类型,returntrue不好用,必须将待转换的类型一一列出usingNewtonsoft.Json;namespaceWinFormsApp1.Common{publicclassToStringConverter:JsonConverter{publicoverrideboo......
  • C标准库<string.h>-str、strn开头的函数
    char*strcat(char*dest,constchar*src)函数功能strcat函数用于将一个字符串追加到另一个字符串的尾部。参数解释dest:指向目标字符串的指针,这个字符串的尾部将被追加 src 字符串的内容。src:指向源字符串的指针,其内容将被追加到 dest 字符串的尾部。返回值返回......
  • C标准库<string.h>-mem开头的函数
    void*memchr(constvoid*str,intc,size_tn)函数功能在参数str所指向的内存区域的前n个字节中搜索第一次出现字符c(转换为无符号字符类型)的位置。参数解释str:指向要被搜索的内存区域的指针。c:要搜索的字符,以整数形式给出,但会被转换为无符号字符类型进行搜索。n:指定要搜......
  • 易优CMS为何我安装完提示这个报错?:Array and string offset access syntax with curly
    当你遇到类似 Arrayandstringoffsetaccesssyntaxwithcurlybracesisdeprecated 的报错时,通常是因为当前使用的PHP版本较高,而程序代码中使用了一些已弃用的语法。原因分析PHP版本过高:当前使用的PHP版本(如PHP7.4或更高版本)不再支持某些旧的语法形式。代码使......
  • .net 将string字符串转为json对象的两种方法
    1)将string直接转为json【注:适合信息量比较少的情况】  stringstr="{\"id\":\"s001\",\"name\":\"张三\",\"gender\":\"男\"}"    【注:上述中\起转义作用】2)将string信息转为list对象后再通过list对象转为json【注:适合信息量比较少的情况......