【C++】简述STL——string类的使用

一、STL的简述

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

1.STL的框架

在这里插入图片描述

2.STL版本

原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本–所有STL实现版本的始祖

P. J. 版本
由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

RW版本
由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

SGI版本
由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。
我们后面学习STL要阅读部分源代码,主要参考的就是这个版本。

二、string

1、string的介绍

string是管理字符数组的类。

typedef basic_string<char> string;

basic_string是模板。将basic_string这个实例重命名为string。

2、为什么string类要实现为模板?

string类本身就是一个模板,为什么要把string写成模板?是因为字符串的数组涉及编码问题,字符数组编码不同。所以需要模板。

类型编码类型
stringUTF-8char
wstringUnicodewchar_t
u16stringUTF-16char16_t
u32stringUTF-32char32_t

对于字符串的多种类型,设计了basic_string模板。

string类模板的大概框架:

template <class T>
//动态增长字符数组
class basic_string
{
private:
	T* _str;
	size_t _size;
	size_t _capacity;
};

使用string类的时候,我们要包含头文件#include

下面我们开始说一说string类常用的接口,对于常用接口我们需要熟练使用,其他的即可查阅学习。

三、string的构造接口

函数名称功能说明
string() (重点)无参的构造,构造空字符串
string(const char* s) (重点)用C_string字符串构造对象
string(size_t n, char c)用n个字符创建对象
string(const string& s) (重点)拷贝构造
string (const string& str, size_t pos, size_t len = npos)用对象构造,下标为pos至len位置
string (const char* s, size_t n)用字符串的前n个构造对象
template
string (InputIterator first, InputIterator last);
迭代器区间构造
int main()
{
    string s1;//无参的构造      
    string s2("hello world");//用C_string字符串构造对象    
    string s3(3, 'x');//用3个字符创建对象
    string s4(s2);//拷贝构造
    string s5(s2, 2, 7);//用s2对象构造,下标为2开始,共7个字符构造s5,结果为llo wor
    string s6("hello world", 7);//用字符串构前7个字符构造
    string s7(s2.begin(),s2.begin()+3);//迭代器区间构造
    string s8 = "hehe";//构造+拷贝构造----直接构造
    return 0;
}

四、string的容量相关的接口

函数名称功能说明
size(重点)返回字符串的长度,不包含’\0’
length返回字符串的长度,不包含’\0’
capacity返回数组容量
empty(重点)字符串的判空
clear(重点)将size置为0,不改变容量
reserve(重点)用于预先开好空间
resize(重点)调整size的大小,可能会改变容量。多出来的位置用’\0’填充

注意:
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, charc)用字符c来填充多出的元素空间。

注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参
数小于string的底层空间总大小时,reserver不会改变容量大小。

1.reserve(调整容量)

在这里插入图片描述
reserve用于预先开好空间,如果预开空间小于现有空间,将不会改变容量。

2.resize(调整size)

在这里插入图片描述

reserve和resize扩容时不会对已有的数据做改变,但缩容时会放弃超出空间的已有数据。

五、string对象修改相关的接口

函数名称功能说明
push_back尾插一个字符
append尾插字符串
operator+=(重点)字符、字符串尾插
insert在pos位置插入
earse在pos位置删除
assign对原有字符串清空后赋值
replace替换

1、insert

string& insert (size_t pos, const string& str);//pos位置插入string对象
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);//pos位置插入字符对象的一部分
string& insert (size_t pos, const char* s);//pos位置插入字符串
string& insert (size_t pos, const char* s, size_t n);//pos位置插入字符串的前n个
string& insert (size_t pos, size_t n, char c);//在pos位置插入n个字符
void insert (iterator p, size_t n, char c);
iterator insert (iterator p, char c);
 
template <class InputIterator>
void insert (iterator p, InputIterator first, InputIterator last);

2.earse

string& erase (size_t pos = 0, size_t len = npos); //从pos位置删除len个字符
iterator erase (iterator p);
iterator erase (iterator first, iterator last);

对于默认值npos:
在这里插入图片描述
这里的npos是-1,但是这里是无符号,实际并不是-1,是4294967295。

3、assign

在这里插入图片描述
assign可以理解成将原字符对象清空,重新进行赋值操作。

4、replace

在这里插入图片描述
repalce是对字符对象的部分取代。

六、string对象字符串运算相关接口

函数名称功能说明
c_str(重点)返回C格式字符串
find(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr(重点)在str中从pos位置开始,截取n个字符,然后将其返回

1、c_str

void Teststring()
{
	string str("hello");
	str.push_back('X'); // 在str后插入X
	str.append("world"); // 在str后追加一个字符"world"
	str += 'C'; // 在str后追加一个字符'C'
	str += "PP"; // 在str后追加一个字符串"PP"
	cout << str << endl;
	cout << str.c_str() << endl; // 以C语言的方式打印字符串
}

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

2、find查找+substr返回子串

size_t find (const string& str, size_t pos = 0) const;//从pos位置开始,在string对象中找str
size_t find (const char* s, size_t pos = 0) const;//从pos位置开始,在string对象中找s
size_t find (const char* s, size_t pos, size_t n) const;//从pos位置开始,在string对象中匹配s的前n个
size_t find (char c, size_t pos = 0) const;//从pos位置开始,在string对象中找字符

举例:查找.后边的内容:

//取文件后缀
//rfind()和substr
void test4()
{
	string file;
	cin >> file;
	size_t pos = file.rfind('.');
	if (pos != string::npos)
	{
		string sub = file.substr(pos);
		cout << sub << endl;
	}
}

七、部分非成员函数接口

函数名称功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)输入运算符重载
operator<< (重点)输出运算符重载
getline (重点)获取一行字符串

对于流插入和流提取都是以空格、换行作为结束标志的(scanf也是这个样子的)。
在这里插入图片描述
为了解决这个问题,我们可以采用getline,

istream& getline (istream& is, string& str, char delim);//从流提取中取出字符至str中,直至遇到delim或'\n'
istream& getline (istream& is, string& str);//从流提取中取出字符至str中

getline(std::cin,str);
遇到\n才会结束。

这个有什么用呢。比如计算 字符串最后一个单词的长度:

#include <iostream>
using namespace std;
#include <string>
int main() {
    string str;
    getline(cin,str);
    size_t pos = str.rfind(' ');
    cout<<str.size()-pos-1<<endl;
}

八、string对象与其他类型互相转换

1、stoi

在这里插入图片描述

将一个string对象转化为int类型的数字。

idx如果不传或者为nullptr,则表示不使用这个参数;反之,&idx指向string对象数字字符的后一个位置。

在这里插入图片描述

2、to_string

能够把内置类型转化为string对象。
在这里插入图片描述
在这里插入图片描述

九、元素访问

1、使用operator[]实现数组下标式的访问

int main()
{
	string s("hello world");//构造
	for (size_t i = 0; i < s.size(); ++i)//读
	{
		cout << s[i] << " ";//等价于cout << s.operator[](i) << " ";
	}
	cout<<endl;
	for (size_t i = 0; i < s.size(); ++i)//写
	{
		cout << (s[i] += 1) << " ";
	}
	return 0;
}

operator[]和at的区别在于operator[]是断言,at是抛异常。主要release版本assert失效。

2、迭代器读写

2.1正向迭代器

int main()
{
	string s("hello world");
	string::iterator it = s.begin();
	//遍历访问
	while (it != s.end())
	{
		cout << *it;
		++it;
	}
	cout << endl;
	it = s.begin();//将it重新置为s.begin位置
	//遍历修改
	while (it != s.end())
	{
		*it += 1;
		cout << *it;
		++it;
	}
	return 0;
}

2.2反向迭代器

int main()
{
	string s("hello world");
	string::reverse_iterator rit = s.rbegin();
	//遍历访问
	while (rit != s.rend())
	{
		cout << *rit;
		++rit;
	}
	cout << endl;
	//遍历修改
	rit = s.rbegin();//将rit重新置为s.rbegin位置
	while (rit != s.rend())
	{
		*rit += 1;
		cout << *rit;
		++rit;
	}
	return 0;
}

2.3const正向迭代器(不能改变*it)

void test(const string& s)
{
	string::const_iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it;
		++it;
	}
}

2.4const反向迭代器(不能改变*it)

void test(const string& s)
{
	string::const_reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit;
		++rit;
	}
}

3、范围for读写

int main()
{
	string s("hello world");
	//范围for的遍历访问
	for (auto e : s)
	{
		cout << e;
	}
	cout << endl;
	//范围for的遍历修改
	for (auto& e : s)
	{
		e += 1;
		cout << e;
	}
	return 0;
}
  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Filex;

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值