【C++】string基本用法(常用接口介绍)

炸掉地球 2024-07-04 17:35:02 阅读 78

文章目录

一、string介绍二、string类对象的创建(常见构造)三、string类对象的容量操作1.size()和length()2.capacity()3.empty()4.clear()5.reserve()6.resize()

四、string类对象的遍历与访问1.operator[ ]2.正向迭代器begin()和end()3.反向迭代器rbegin()和rend()4.const正向和反向迭代器5.范围for6.at()

五、string类对象的查找与修改字符串查找1.find()与npos2.rfind()3.find_first_of()和find_last_of()4.substr()

字符串修改1.operator+=2.push_back()与pop_back()3.append()4.insert()5.erase()6.replace()

六、string类非成员函数operator+输入getline

一、string介绍

string是表示字符串的字符串。它提供了一系列成员函数和操作符,使得字符串的操作更加方便和灵活。它位于标准命名空间<code>std下,因此通常需要使用using namespace std;语句或者前缀std::来引用。

string是C++的STL(standard template libaray-标准模板库)的容器之一。本篇,我们主要介绍string的基本用法。所有接口用法都可以在cplusplus参考手册中查阅。下面我们主要介绍string的一些常用接口。

string底层实际是basic_string类模板的实例化,是表示字符串类型的模板类

在这里插入图片描述

二、string类对象的创建(常见构造)

在这里插入图片描述

string重载了很多构造和拷贝构造函数,其实常用的也就4种。

<code>//常用构造方式

string s1;//无参构造

string s2("interesting");//构造

string s3(s2);//拷贝构造

string s4 = "hello world";//构造

不常用的初始化方式

//函数原型 string (size_t n, char c);

string s5(10, 'x');//10个字符x

//函数原型 string (const string& str, size_t pos, size_t len = npos);

string s6(s2, 8, 3);//打印ing 第8个位置开始拷贝3个字符

string s7(s2, 8);//打印ing 第8个位置开始拷贝后面所有字符

三、string类对象的容量操作

1.size()和length()

计算有效字符串长度,不包括\0 size()与length()的底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

int main()

{

string s("abcde");

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

cout << s.length() << endl;//5

return 0;

}

2.capacity()

返回string类对象的空间容量大小。同样的一个字符串在不同编译器下的容量可能不一样。

string s("abcde");

cout << s.capacity() << endl;//vs2019:15

3.empty()

字符串为空返回1,非空则返回0。

一般也很少用到。我们也可以用str == ""判断是否为空。

4.clear()

clear()只是将string中有效字符清空,不改变底层空间大小。 即有效数据size()清零,容量capacity()不变。

string s("abcde");

s.clear();

5.reserve()

提前申请空间,可以避免频繁扩容。有效数据size不变,容量capacity增大。 且只比指定容量要大,不会小。

在这里插入图片描述

在Windows环境下(如上图),reserve实际申请空间一般比我们指定的参数要大;而Linux的扩容空间与指定参数一样。

不同环境下,string扩容的规律也不同:Windows环境下(PJ版本STL),容量capacity每次以1.5倍的速度扩容;Linux环境下(SGI版本STL),每次以2倍速度扩容;所以频繁扩容的成本较高。reserve可以提前申请好空间,避免频繁扩容。

在这里插入图片描述

reserve可以缩容吗?

可以,但是如果原始空间有数据,则缩容无效;用clear清空有效数据,即可缩容到指定参数大小的空间。所以,想用reserve缩小空间

6.resize()

调整string容器大小,即有效数据个数size()。

<code>string s("abcde");

s.resize(3);//abc size=3;

s.resize(5, 'x');//abcxx size=5

n < size相当于尾删,size()减小到n,底层空间capacity()不变。

n > size则size增加到n,多出的空间用第二个字符参数填充,无参则默认填充’\0’。

四、string类对象的遍历与访问

1.operator[ ]

int main()

{

string s("interesting");

for (size_t i = 0; i < s.size(); i++)

{

cout << s[i];

s[i]++;

}

return 0;

}

2.正向迭代器begin()和end()

begin()返回指向字符串第一个字符的迭代器,end()返回指向字符串末尾字符’\0’的迭代器。

迭代器提供了一种遍历容器中元素的方法,迭代器是像指针一样的类型,但可能是指针,也可能不是指针,用法与指针类似。

任何容器都支持迭代器,并且用法是类似的。 迭代器是属于类域的,所以要加域作用限定符。并且对于迭代器的使用,搭配关键字auto使用更简单。

int main()

{

string s("interesting");

//auto it = s.begin();//自动识别类型

string::iterator it = s.begin();

//打印interesting

while (it != s.end())

{

cout << *it;

it++;

}

return 0;

}

3.反向迭代器rbegin()和rend()

反向迭代器与正向迭代器用法一样,可以实现逆序遍历。注意正向和反向迭代器名字不一样。

int main()

{

string s("interesting");

//auto it = s.rbegin();//自动识别类型

string::reverse_iterator rit = s.rbegin();

//打印gnitseretni

while (rit != s.rend())

{

cout << *rit;

rit++;

}

return 0;

}

4.const正向和反向迭代器

对于const修饰的string类对象,就只能用const迭代器,否则会发生权限的放大。

使用auto更方便省事。

const string s("interesting");

//正向

string::const_iterator it = s.begin();

auto it = s.begin();

//反向

string::const_reverse_iterator rit = s.rbegin();

auto it = s.rbegin();

5.范围for

C++11支持更简洁的范围for的新遍历方式。范围for的底层就是迭代器,不支持迭代器就不支持范围for。

int main()

{

string s("interesting");

for (auto& ch : s)//可读 加上引用可写

{

ch++;

cout << ch;

}

return 0;

}

6.at()

使用与operator[ ]一样,但一般很少用at()来访问string。

at()与[ ]的区别是对越界的检查不一样:[ ]越界会断言,比较暴力;at()越界会抛异常,比较温和。

int main()

{

string s("interesting");

for (size_t i = 0; i < s.size(); i++)

{

cout << s.at(i);

s.at(i)++;

}

return 0;

}

五、string类对象的查找与修改

字符串查找

1.find()与npos

find是查找字符或字符串函数,返回与字符参数匹配到的第一个字符位置下标,如果找不到则返回npos。

在这里插入图片描述

npos是string类的静态成员变量,值为-1(-1的补码全是1),因为是size_t即无符号整型,所以npos表示的大小为232-1,即整型的最大范围。

在这里插入图片描述

2.rfind()

与find()一样,只不过rfind()是从右往左查找。

在这里插入图片描述

3.find_first_of()和find_last_of()

find_first_of():只要字符串中找到字符参数中任意一个字符,则返回第一个找到的下标。

例如,下面这段代码将字符串中的aeiou全部替换成*

在这里插入图片描述

find_last_of()同理,只不过是从右往左查找。

4.substr()

返回获取到的子串

<code>int main()

{

string s1("hello world");

//第一种也是最常用的

string s2 = s1.substr(2, 3);//截取从下标2开始的3个字符

cout << s2 << endl;//llo

s2 = s1.substr(6);//截取从下标6开始后面的所有字符

cout << s2 << endl;//world

s2 = s1.substr();//截取整个字符串

cout << s2 << endl;//hello world

return 0;

}

字符串修改

1.operator+=

+= 可以尾插字符或者字符串,这个比较常用。+=操作不仅可以连接单个字符,还可以连接字符串。

int main()

{

string s("hello ");

s += "world";

s += '!';

cout << s << endl;

return 0;

}

2.push_back()与pop_back()

尾插和尾删单个字符

string s("abcd");

s.pop_back();//abc

s.push_back('x');//abcx

3.append()

尾插n个字符或者尾插指定区间的字符串

string s("hello ");

s.append(10, 'x');//尾插10个x

s.append("world", 3);//尾插字符串world的前3个字符

s.append("world", 1, 3);//尾插从下标1开始往后的3字符即orl

tip:一般push_back()和append()尾插不常用,用+=更方便省事。

4.insert()

在指定位置插入字符或者字符串

在这里插入图片描述

5.erase()

删除指定位置的字符或字符串

在这里插入图片描述

6.replace()

用新的字符或者字符串替换原字符串部分字符

在这里插入图片描述

六、string类非成员函数

operator+

尽量少用,因为传值返回,导致深拷贝效率低。

<code>int main()

{

string s1("hello");

string s2("world");

s1 = s1 + " " + s2;

cout << s1 << endl;

return 0;

}

operator>>和operator<<运算符重载也是string的非成员函数。

输入getline

cin无法读取空格和换行,getline可以弥补这个缺陷。需要包含头文件<string>

第三个参数不指定分隔符,默认以换行\n结束,可以读取空格,常用来读取一整行。

#include <iostream>

#include <string>

using namespace std;

int main()

{

string s;

getline(cin, s);

cout << s;

return 0;

}

第三个参数指定分隔符,则读取到该分隔符为止。例如指定\r则以回车作为结束符,可以读取换行符\n,结束需按下:Ctrl+z 然后再回车。

#include <iostream>

#include <string>

using namespace std;

int main()

{

string s;

getline(cin, s, '\r');

cout << s;

return 0;

}



声明

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