C++中string使用

目录

介绍

使用

迭代器(Iterator)

begin,end

rbegin,rend

容量(Capacity)

size,length

capacity

empty

clear

resize

reserve

[元素访问(Element access)](#元素访问(Element access))

operator[]

at

front,back

修饰符(Modifier)

opreator+=

push_back

insert

erase

pop_back

操作(operation)

c_str

copy

find

rfind

substr


介绍

string属于STL(Standard Template Library,标准模板库)中容器的一部分。容器是用来存储和管理数据的对象。

string表示字符串的字符串类。string的出现的时间比STL还要早所以里面的有些接口就会有点冗余。要使用string的话要加上名为<string>的头文件。这是关于使用string的网址:string,这里我就只是简单介绍一下某些接口的使用。

使用

迭代器(Iterator

迭代器(iterator)是一种用于遍历容器中元素的对象。它提供了一种统一的方式来访问不同类型容器中的元素,无需了解容器的内部实现细节。这是封装的一种体现。

begin,end

begin:返回字符串第一个字符的迭代器,end:返回字符串最后一个字符的迭代器。

如果是空字符串使用它们会返回指向该空字符串起始位置的迭代器。利用它们就可以实现字符串的遍历。例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

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

int main()
{
	string s("hello world");

	print(s);
	return 0;
}//下面会频繁用到print这个函数

大家可能注意到了这个:

第一个it前面有个*号,第二个it后面面有个++。这里大家可能猜到了这就是指针!这里的迭代器也确实可以简单认为是指针,因为string开辟的空间是连在一起的。但是后面得list开辟的空间不是连续的就不能简单认为迭代器是指针。但是后面的list用迭代器遍历也是这样写的因为使用了运算符重载。

如果不用对字符串里的内容修改就可以用cbegin,cend。这时候迭代器就要改为const_iterator。

cpp 复制代码
int main()
{
	string s("hello world");

	string::const_iterator it = s.cbegin();
	while (it != s.cend())
	{
		cout << *it;
		it++;
	}
	return 0;
}

rbegin,rend

前面的r其实是reverse("反转""颠倒""逆向"),所以rbegin:返回最后一个字符的迭代器,rend:返回第一个字符的迭代器。这时候迭代器就要改为reverse_iterator。这时就可以实现逆序打印字符串。例:

cpp 复制代码
int main()
{
	string s("hello world");

	string::reverse_iterator it = s.rbegin();
	while (it != s.rend())
	{
		cout << *it;
		it++;
	}
	return 0;
}

大家可能好奇为什么不设计--来实现逆序打印。其实是为了保持语言的一致性、清晰性、可维护性。

如果不用对字符串里的内容修改就可以用crbegin,crend。这时候迭代器就要改为const_reverse_iterator。

容量(Capacity

size,length

以字节为单位返回有效字符串的长度。

size和length的功能是一样的,这是因为string设计的比STL要早原来的string里没有size为了实现统一性就设计了size。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	cout << s.size();

	return 0;
}

capacity

以字节为单位返回当前为字符串分配的存储空间大小。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	cout << s.capacity();

	return 0;
}

empty

这是判断字符串是否为空。为空则真,否则为假。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	cout << s.empty();

	return 0;
}

clear

将字符串里的所有的字符删除。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.clear();

	print(s);
	return 0;
}

resize

将字符串调整为长度为 n 个字符。

  • 如果n小于字符串的长度

如果n小于字符串的长度,会保留第一个到第n个之间的所有字符,后面的字符都会被移除。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.resize(5);

	print(s);
	return 0;
}
  • 如果n大于或等于字符串的长度

如果n大于或等于字符串的长度就会从最后一个字符开辟n - l(字符串的长度)。可以在最后一个字符的后面新增新的字符,也可以不新增。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.resize(15, 'a');

	print(s);
	return 0;
}

reserve

用于预分配n个字符数量的内存空间以容纳字符串内容,使其能够容纳最多 n 个字符。

如果 n 大于当前字符串的容量,这个函数会使容器增加其容量到 n 个字符(或更多)。其他情况下,它被视为一个非约束性的请求来缩小字符串容量(一般不会缩小)。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.reserve(20);
	cout << s.capacity();

	return 0;
}

大家可能发现了这里的值是31并不是20。因为扩容是按照固定的倍数扩的编译器具体扩多大是由它决定的。我们想把容量变成20其实对于编译器来说就只是一个建议,编译器可能会扩成20也有可能扩成比它大的某数字。

元素访问(Element access

operator[]

获取字符串中pos位置的字符,并返回字符串中 pos 位置的字符的引用。

如果访问超出字符串长度的位置,会导致未定义行为。可能出现程序崩溃、产生错误的结果等。这个就很像是数组里的下标运算符。事实上它就是重载了数组里的下标运算符。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	for (size_t i = 0; i < s.size(); i++)
	{
		cout << s[i];
	}

	return 0;
}

at

at和上面的operator[]几乎一样,也是访问字符串里的字符并返回该字符引用。如果访问的位置超出字符串长度就会抛异常。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	for (size_t i = 0; i < s.size(); i++)
	{
		cout << s.at(i);
	}

	return 0;
}

front,back

front,back和上面的begin,end几乎一样只不过,front:返回的是第一个字符的引用,back:返回的是最后一个字符的引用。空字符串里不能使用它们。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.front() = 'A';
	s.back() = 'A';

	print(s);
	return 0;
}

修饰符(Modifier

对字符串进行各种操作和变换,以满足不同的需求。

opreator+=

在字符串末尾添加字符或字符串,并增加有效长度。该接口会返回字符串类的引用。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s += ' ';
	s += "abc";

	print(s);
	return 0;
}

push_back

在字符串末尾添加字符,使有效地将其长度增加一个。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.push_back('a');

	print(s);
	return 0;
}

insert

在字符串的指定pos位置之前插入字符或字符串。

第一个参数是插入位置的下标,如果插入位置的下标超出字符串长度就会抛异常。第二个参数可以是字符串,可以是字符但要在字符写要插入字符的长度。该接口返回字符串类的引用。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	const char* str = "---";
	s.insert(0, 1, 'a');
	s.insert(1,str);

	print(s);
	return 0;
}

erase

擦除字符串的一部分,减少其有效长度。

第一个参数是要擦处位置的下标,如果擦除位置的下标超出字符串长度就会抛异常 。第二个参数是要删除字符的长度。如果要删除字符的长度不写或超出字符串有效长度就会把后面的所有的字符都删除。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.erase(0, 1);

	print(s);
	return 0;
}

如果没接len:

pop_back

在字符串末尾删除字符,使有效地将其长度减少一个。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	s.pop_back();

	print(s);
	return 0;
}

操作(operation

对字符串进行一些操作例如查找,复制等。

c_str

该接口会返回一个指向字符数组的指针。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	const char* p = s.c_str();
	printf("%p", p);
	cout << endl << p;

	return 0;
}

大家可能注意到了cout << p直接就打印了p的内容了,这是因为string里重载了<<。

copy

将字符串里的内容拷贝到字符数组里,需要注意的是并不会拷贝'\0'。该接口返回实际拷贝的字符数。

第一个参数的位置是字符数组指针,第二个参数是要拷贝字符的长度,第三个参数是字符串里开始拷贝位置的下标(默认是0)。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	char buffer[20];
	size_t len = s.copy(buffer, 5);
	buffer[len] = '\0';
	cout << buffer;

	return 0;
}

find

查找pos位置之后第一次出现的字符和字符串。

第一个参数是要查到的字符串或字符,第二个参数是查找的起始位置pos(默认是0)。如果找到会返回该下标位置,否则返回npos。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	size_t i = s.find('o');
	i != s.npos ? cout << "找到了,下标是" << i: cout << "没找到";

	return 0;
}

npos:

  1. 当在字符串的成员函数中作 len 参数的缺省值时,这时意味着"直到字符串的末尾"。
  2. 作为返回值,它通常用于表示没有匹配。
  3. 这个常量被定义为值 -1,由于 size_t 是一个无符号整数类型,所以这是该类型的最大可表示值。

rfind

查找pos位置之前第一次出现的字符和字符串。

第一个参数是要查到的字符串或字符,第二个参数是查找的起始位置pos(默认是npos)。如果找到会返回该下标位置,否则返回npos。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	size_t i = s.rfind('o');
	i != s.npos ? cout << "找到了,下标是" << i : cout << "没找到";

	return 0;
}

substr

从字符串里提取子字符串。

第一个参数是子字符串开始的位置,第二个参数是提取子字符串的长度(如果不写会从起始位置到字符串结束)。该接口返回字符串类。使用例子:

cpp 复制代码
int main()
{
	string s("hello world");

	string str = s.substr(0, 5);
	print(str);

	return 0;
}

上面我所提到的接口一定要多练习,千万不要只看不练。

相关推荐
hope_wisdom5 分钟前
C++网络编程之SSL/TLS加密通信
网络·c++·ssl·tls·加密通信
erxij9 分钟前
【游戏引擎之路】登神长阶(十四)——OpenGL教程:士别三日,当刮目相看
c++·经验分享·游戏·3d·游戏引擎
Lizhihao_22 分钟前
JAVA-队列
java·开发语言
林开落L40 分钟前
前缀和算法习题篇(上)
c++·算法·leetcode
远望清一色41 分钟前
基于MATLAB边缘检测博文
开发语言·算法·matlab
何曾参静谧1 小时前
「Py」Python基础篇 之 Python都可以做哪些自动化?
开发语言·python·自动化
Prejudices1 小时前
C++如何调用Python脚本
开发语言·c++·python
单音GG1 小时前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
我狠狠地刷刷刷刷刷1 小时前
中文分词模拟器
开发语言·python·算法
wyh要好好学习1 小时前
C# WPF 记录DataGrid的表头顺序,下次打开界面时应用到表格中
开发语言·c#·wpf