string类对象的修改操作

340 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

4、string类对象的修改操作
函数名称功能说明
push_back在字符串后尾插字符 c
append在字符串后追加一个字符串
operator+= —— 重点在字符串后追加字符串 str
c_str —— 重点返回 c 格式字符串
find + npos —— 重点从字符串 pos 位置开始往后找字符 c,返回该字符在字符串中的位置
rfind从字符串 pos 位置开始往前找字符 c,返回该字符在字符串中的位置
substr在 str 中从 pos 位置开始,截取 n 个字符,然后将其返回
在这里插入图片描述
#include<string>
#include<iostream>
using namespace std;
void test_string1()
{
	//1、push_back | append | operator +=
	string s1("hello");
	string s2("world");
	s1.push_back('+');
	s1.append("world");
	cout << s1 << endl;
	s1 += '+';
	s1 += "bit+";
	s1 += s2;
	cout << s1 << endl;
	cout << "----------cut----------" << endl;
	//2、insert | erase
	string s3("hello");
	s3.insert(0, "bit ");
	cout << s3 << endl;
	//s3.erase(5);//从5删到nops
	s3.erase(5, 2);//从5往后删2个
	cout << s3 << endl;
	cout << "----------cut----------" << endl;
}
void test_string2()
{
	//要求取出文件的后缀
	string file1("test.txt");
	string file2("test.c");
	string file3("test.txt.zip");//对test.txt文件打了个包
	size_t pos1 = file1.find('.');
	if(pos1 != string::npos)//当find的返回值不等于npos就找到了
	{
		//1、substr
		string sub1 = file1.substr(pos1);//同substr(pos1, file1.size()-pos1);,但没必要,因为这里是取后缀,而substr有缺省参数npos
		cout << sub1 << endl;
	}
	size_t pos2 = file2.find('.');
	if(pos2 != string::npos)
	{
		string sub2 = file2.substr(pos2);
		cout << sub2 << endl;
	}
	//由此可见对于file3,以上代码不适用
	size_t pos3 = file3.find('.');
	if(pos3 != string::npos)
	{
		string sub3 = file3.substr(pos3);
		cout << sub3 << endl;
	}
	//更适用的来说取文件的后缀应当使用另一个接口rfind
	size_t pos4 = file3.rfind('.');
	if(pos4 != string::npos)
	{
		string sub4 = file3.substr(pos4);
		cout << sub4 << endl;
	}
	cout << "----------cut----------" << endl;
}
void test_string3()
{
	//取出url中的protocol、domain、uri ———— 网址 = 协议 + 域名 + 资源定位
	string url("http://www.cplusplus.com/reference/string/string/find/");
	size_t i1 = url.find("://");//find也可以找串
	if(i1 != string::npos)
	{
		string protocol = url.substr(0, i1 - 0);
		cout << "protocol:" << protocol << endl;
	}
	size_t i2 = url.find('/', i1 + 3);//find的第四个版本
	if(i2 != string::npos)
	{
		string domain = url.substr(i1 + 3, i2 - (i1 + 3));  
		cout << "domain:" << domain << endl;
	}
	size_t i3 = url.find('/', i2);
	if(i3 != string::npos)
	{
		string uri = url.substr(i3);
		cout << "uri:" << uri << endl;	
		printf("uri:%s\n", uri.c_str());//C语言去输出string做不到,但是提供了c_str
	}
}
int main()
{
	test_string1();
	//3、find
	test_string2();
	test_string3();
	return 0;
}

📝说明

push_back | append | operator+= ❗

如果你要尾插一个字符用 push_back,如果你要尾插一个字符串用 append。个人感觉这是 string 设计的不好的地方,为什么不再重载一个 push_back 呢,非要去搞一个 append 来恶心人,而 append 又重载了六个版本,也没啥太大的价值,比较常用的也就三、四版本。

相对于 push_back、append 更推荐使用 operator+=,因为它可以追加一个字符,也可以追加一个字符串,还可以追加一个对象。

这里我们发现 string 里面没有头插、头删,但它有中间插入、删除。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 insert | erase ❗

可以看到实现了七个版本,这里就了解了解较为常用的,其余简单提一下。

它不仅仅可以中间插入、也可以在头上插入,还可以在尾部插入。

但是对于 insert 能不用就不用,因为效率比较低,它需要挪动数据。 在这里插入图片描述 与 insert 对应的是 erase。 在这里插入图片描述 erase 的第一个版本参数中的 npos 比较特殊,它给的是一个缺省参数,nops 是这个类里的静态成员变量,它是 -1,但实际上不是 -1,因为这个 -1 给了 size_t,所以它转换为补码就是整型的最大的值。 在这里插入图片描述 find | rfind ❗

对于 find 的返回值,一般是 int,找到返回下标,找不到返回 -1。这里用 size_t 的想法是,找到返回下标,找不到会返回 nops,但是正常的字符不可能有那么长。 在这里插入图片描述 查找字符串中内容的最后一次出现: 在这里插入图片描述

substr ❗

生成子串。 在这里插入图片描述 c_str ❗

它可以和 C语言配合使用。 在这里插入图片描述

5、string类非成员函数
函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> —— 重点输入运算符重载
operator<< —— 重点输出运算符重载
getline —— 重点获取一行字符串
relational operators —— 重点大小比较
在这里插入图片描述
#include<string>
#include<iostream>
using namespace std;
int main()
{
	string s1("hello");
	s1 + "world";
	cout << s1 << endl;
	s1 += "world";
	cout << s1 << endl;
	cout << "----------cut----------" << endl;
	return 0;
}

📝说明

operator+ 和 operator+= ❗

它们的作用都是尾插,但是 operator+= 会改变当前字符串,而 operator+ 不改变当前字符串。 在这里插入图片描述 relational operators ❗

string 还提供了比较大小的接口,可以看到非常多的版本,比如对象跟对象比、字符串跟对象比,自我感觉比较冗余。

因为字符串是可以被隐式类型转换成 string 的:

string s1("hello");//正常写法,string支持单参数的构造函数
string s2 = "world";//隐式类型转换,先将字符串构造一个string,再将string拷贝构造s2。最后优化成直接构造

所以这里是想说就算是字符串跟对象比,字符串也可以隐式转换成对象,没必要再实现一个版本。

在这里插入图片描述

6、补充
函数功能说明
to_string数值转字符串
stoi字符串转数值
#include<string>
#include<iostream>
using namespace std;
int main()
{
	int i = 1234;
	string str = to_string(i);
	cout << str << endl;
	int j = stoi(str);
	cout << j << endl;
	return 0;
}

📝说明

to_string | stoi ❗

将数值转换为字符串(注意它不是 string 的成员函数,而是全局函数): 在这里插入图片描述 在 C语言中有类似的函数 itoa,它需要自己提供空间,且有些 OJ 上还不支持,因为它不是标准的 C库,所以不够好用。

可以看到它还提供了将字符串转成整数: 在这里插入图片描述