string类的函数讲解

发布时间:2023年12月26日

标准库中的string类

首先关于string类的了解,我先给出官方的string类的讲解,以便于大家的学习:链接: http://www.cplusplus.com/reference/string/string/?kw=string
这个网站是C++官方网站,里面对于各个关键字和库函数的讲解都是很官方的,大家有需要的时候可以参考

我们对string类进行一个简单的总结:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列。

这里有一个需要注意的点:
在使用string类时,必须包含#include头文件以及using namespace std;

下面我们就对string类的一些常用的接口进行讲解:

string类的常用接口说明
string类对象的常见构造

在这里插入图片描述
首先我们看看创建一个空的string类,就是一个空的字符串:

#include<iostream>
using namespace std;
int main()
{
	string s1;
	cout << s1 << endl;
	return 0;
}

输出为空:
在这里插入图片描述
构造string类对象:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
拷贝构造:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	string s2(s1);
	cout << s2 << endl;
	return 0;
}

在这里插入图片描述
将n个字符放入一个string类中:

#include<iostream>
using namespace std;
int main()
{
	string s1(5,'a');
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
去一个string类中的字符存入另一个string类:
例如,将s1中第六个字符开始往后取三个字符放入s2
这里注意:
如果这里的要取字符的数量大于字符串的字符个数的话,能取多少取多少

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	string s2(s1, 6, 3);
	cout << s2 << endl;
	return 0;
}

在这里插入图片描述

string类对象的容量操作

在这里插入图片描述
我们这里的size和lenth的作用是一样的,只是在后期的语言发展中为了适应需要,例如,如果是一个二叉树,用lenth合适吗,所以就引出了size
注意,这里计算出来的是有效字符个数,也就是说不包括’\0’

用法如下:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.length() << endl;
	cout << s1.size() << endl;
	return 0;
}

在这里插入图片描述
capacity是返回空间的大小:
至于容量为什么是15,这就是底层实现的原因了,一些编译器是基于1.5倍的扩容,比如我们的vscode,而linux的终端里是以2倍的扩容,其实不必太过于纠结这一点,我们只需要了解到这一点即可
但是各自的容量起点也不一样!

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.capacity() << endl;
	return 0;
}

在这里插入图片描述
empty函数的用法很简单:
例如,不为空返回0

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.capacity() << endl;
	cout << s1.empty() << endl;
	return 0;
}

在这里插入图片描述
clear的作用就是清空字符串:
清理之后输出空行,字符串被清空

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	s1.clear();
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
这里有一个重点内容:
reserve和resize的区别
其实二者都是用来提前开空间的,因为扩容会影响程序的效率
例如:
可以看到二者都成功地开辟了空间
在这里插入图片描述
在这里插入图片描述
并且使用resize时还可以填充多余的空间:
在这里插入图片描述
但其实这不是重点,重点在于:
这是resize:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;
	s1.resize(30);
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;
	return 0;
}

在这里插入图片描述

这是reserve:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;
	s1.reserve(30);
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;
	return 0;
}

在这里插入图片描述
大家可以发现:
用reserve来提前开辟空间,capacity改变,size不变,而用resize则是capacity和size都会发生改变!

下面给大家一个小的总结:

注意:

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
    致,一般情况下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
    string的底层空间总大小时,reserver不会改变容量大小。
string类对象的访问及遍历操作

在这里插入图片描述
operator[],就是返回该位置的字符,其实就是用于循环:
但是要注意一点,如果访问越界,就会直接报错,导致程序终止
并且该函数一般只适用于数组结构

#include<iostream>
using namespace std;
int main()
{
	string const s1("hello world");
	for (int i = 0; i < s1.length(); i++)
	{
		cout << s1[i];
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
迭代器:
迭代器有两种,还有一个叫做反向迭代器,就是从尾部开始遍历
在这里我们暂且把begin认为是指针来理解
我们使用正向的迭代器的时候要引出string类里面的iterator
begin就默认是从零开始输出记得用解引用,指针向后移动

我们给出一张对比图:
在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	for (string::iterator i = s1.begin(); i != s1.end(); i++)
	{
		cout << *i;
	}
	return 0;
}

在这里插入图片描述
而反向迭代器就是从后开始往前移动:
这里要引出的是 reverse_iterator 其实这里的rbegin已经不在字符串的第一个位置了二者是有区别的,并且,这里的指针也是++,不然怎么会叫做反向迭代器呢?

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	for (string::reverse_iterator i = s1.rbegin(); i != s1.rend(); i++)
	{
		cout << *i;
	}
	return 0;
}

在这里插入图片描述
另外大家记住一个点:
for循环的底层实现就是迭代器!

string类对象的修改操作

在这里插入图片描述
尾插字符:
尾插很简单

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	s1.push_back('!');
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
追加字符串:
相比较push_back,append只能追加字符串,而前者只能追加字符

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	s1.append(" hhhh!");
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
但是operator+=能够把上面两个函数一起实现,并且函数的可读性更高,所以我们一般选择使用+=来实现对对象的追加:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	s1+=(" hhhh!");
	cout << s1 << endl;
	s1 += ('x');
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
返回C字符串:

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.c_str() << endl;
	return 0;
}

在这里插入图片描述
返回字符串中的位置:
返回位置既可以从前往后找又可以从后往前找
find是从前往后,rfind是从后往前,npos是字符串的长度
在这里插入图片描述
在这里插入图片描述
如果找不到的话这里的npos是-1
但是find函数返回的是无符号整形,所以-1进行了转换
在这里插入图片描述
截取字符:
从pos位置开始往后截取n个字符
如果n大于length-pos,能截取多少就截取多少

#include<iostream>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1.substr(3, 4) << endl;
	cout << s1.substr(3, 12) << endl;
}

在这里插入图片描述

下面我们对于string类的修改操作做一个小总结:

  1. 在string尾部追加字符时,s.push_back? / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
string类非成员函数

在这里插入图片描述
其实这里用的不多,不做过多的讲解
但是这个getline函数是可以用到一些题目中来读取字符串的,他遇到换行符就会停止读取,遇到空格不会:

int main()
{
	std::string name;

	std::cout << "Please, enter your full name: ";
	std::getline(std::cin, name);
	std::cout << "Hello, " << name << "!\n";

	return 0;
}

在这里插入图片描述
好了,今天的分享到这里就结束了,谢谢大家的支持!

文章来源:https://blog.csdn.net/weixin_63966442/article/details/135207419
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。