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

文章目录

一、string介绍

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

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

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

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

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

cpp 复制代码
//常用构造方式
string s1;//无参构造
string s2("interesting");//构造
string s3(s2);//拷贝构造
string s4 = "hello world";//构造

不常用的初始化方式

cpp 复制代码
//函数原型 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()。

cpp 复制代码
int main()
{
	string s("abcde");
	cout << s.size() << endl;//5
	cout << s.length() << endl;//5
	return 0;
}

2.capacity()

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

cpp 复制代码
string s("abcde");
cout << s.capacity() << endl;//vs2019:15

3.empty()

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

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

4.clear()

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

cpp 复制代码
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()。

cpp 复制代码
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[ ]

cpp 复制代码
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使用更简单。

cpp 复制代码
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()

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

cpp 复制代码
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更方便省事。

cpp 复制代码
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。

cpp 复制代码
int main()
{
	string s("interesting");
	for (auto& ch : s)//可读 加上引用可写
	{
		ch++;
		cout << ch;
	}
	return 0;
}

6.at()

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

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

cpp 复制代码
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表示的大小为2^32^-1,即整型的最大范围。

2.rfind()

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

3.find_first_of()和find_last_of()

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

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

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

4.substr()

返回获取到的子串

cpp 复制代码
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+=

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

cpp 复制代码
int main()
{
	string s("hello ");
	s += "world";
	s += '!';
	cout << s << endl;
	return 0;
}

2.push_back()与pop_back()

尾插和尾删单个字符

cpp 复制代码
string s("abcd");
s.pop_back();//abc
s.push_back('x');//abcx

3.append()

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

cpp 复制代码
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+

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

cpp 复制代码
int main()
{
	string s1("hello");
	string s2("world");
	s1 = s1 + " " + s2;
	cout << s1 << endl;
	return 0;
}

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

输入getline

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

不指定分隔符,默认以回车结束,可以读取空格,常用来读取一行。

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s;
	getline(cin, s);
	cout << s;
	return 0;
}

第三个参数可以指定分隔符,例如指定'\r'可以读取回车,结束需按下:Ctrl+z 然后再回车

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s;
	getline(cin, s, '\r');
	cout << s;
	return 0;
}
相关推荐
白小筠1 分钟前
类和对象(提高)
c++
LeoLei80608 分钟前
LeetCode.68文本左右对齐
c++·算法·leetcode
界面开发小八哥12 分钟前
MFC扩展库BCGControlBar Pro v35.0新版亮点 - 工具栏、菜单全新升级
c++·mfc·bcg·界面控件·ui开发
程小k22 分钟前
【数据结构初阶】--- 归并排序
c语言·数据结构·c++·算法·排序算法
透明的玻璃杯1 小时前
C++ 和C#的差别
开发语言·c++
太湖鹏哥1 小时前
6.2、函数的定义
开发语言·c++·算法
太湖鹏哥2 小时前
5.3.3、二维数组案例-考试成绩统计
数据结构·c++·算法
牵牛老人2 小时前
C++中的数据结构
开发语言·数据结构·c++
LeoLei80602 小时前
深入理解TCP协议格式(WireShark分析)
网络·c++·网络协议·tcp/ip·wireshark
Navigator_Z3 小时前
C++ //练习 14.23 为你的StrVec类定义一个initializer_list赋值运算符。
开发语言·c++·算法