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

Filex; 2024-09-30 16:35:03 阅读 96

文章目录

一、STL的简述1.STL的框架2.STL版本

二、string1、string的介绍2、为什么string类要实现为模板?

三、string的构造接口四、string的容量相关的接口五、string对象修改相关的接口1、insert2.earse3、assign4、replace

六、string对象字符串运算相关接口1、c_str2、find查找+substr返回子串

七、部分非成员函数接口八、string对象与其他类型互相转换1、stoi2、to_string

九、元素访问1、使用operator[]实现数组下标式的访问2、迭代器读写2.1正向迭代器2.2反向迭代器2.3const正向迭代器(不能改变*it)2.4const反向迭代器(不能改变*it)

3、范围for读写

一、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是管理字符数组的类。

<code>typedef basic_string<char> string;

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

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

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

类型 编码 类型
string UTF-8 char
wstring Unicode wchar_t
u16string UTF-16 char16_t
u32string UTF-32 char32_t

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

string类模板的大概框架:

<code>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

<code>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

<code>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,

<code>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[]实现数组下标式的访问

<code>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;

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。