从零开始的C++生活——第五讲——02

这一讲,我们接着介绍string类的使用。

首先,我来讲解一下string的尾插

这三个函数都可以用来尾插,我们先介绍push_back

push_back是最直接的函数,它能实现的功能只有一个那就是在字符串的后边追加一个字符,只能追加一个字符,这要和后边讲解的方法做一个区分。

cpp 复制代码
void test_push_back()
{
	string s("hello world");
	s.reserve(100);

	for (int i = 0; i < 100; i++)
	{
		s.push_back('x');
	}
	cout << s << endl;
	cout << s.size() << " " << s.capacity() << endl;
}

接下来介绍一下append

这里提供了很多种重载,我只介绍一些常用的。

和push_back不同的是,append支持追加字符串,不止是string类型的字符串还可以追加C语言风格的char*类型的字符串。

此外,append还支持追加string字符串的指定子串,用第二种方式传指定区域,若超出范围则追加到末尾位置。

当然,append也可以实现追加单个字符的功能,但设计的比较麻烦,如上图第五种,只能指定n和char两个参数,意为传入n个字符c,如果你只想追加一个,并没有因此设计单独的接口,只能传1,c。

cpp 复制代码
void test_append()
{
	//追加字符串
	//string
	string s("hello world");
	string s1("abcde");
	s.append(s1);
	cout << s << endl;
	//const char*
	s.append("xxxx");
	cout << s << endl;
	//追加单个字符
	s.append(1, 'k');
	cout << s << endl;
	//追加n个字符
	s.append(7, 'z');
	cout << s << endl;
}

接下来介绍一下+=,这是运算符重载函数。

+=是最简约,也是最容易理解的尾插方式。

显然这三种情况分别对应插入string,C语言风格的字符串,单个字符。

cpp 复制代码
void test_operator1()
{
	//operator+=
	string s("hello world");
	s += 'c';
	cout << s << endl;
	s += " askfhlak";
	cout << s << endl;
	string s1(" qqqqqq");
	s += s1;
	cout << s << endl;
}

那么尾插就已经介绍完了,接下来我介绍一下普通的插入。

普通插入其实和append有点像,也是实现了很多种重载。和尾插的本质区别是指定位置。

唯一有差别的是当我们想要插入单个字符或者多个重复字符时,需要指定位置,指定插入个数,换言之并没有为插入单个字符做单独接口。

cpp 复制代码
void test_insert()
{
	string s("hello world");
	s.insert(0, "fasf");
	cout << s << endl;
	string s1("qqqqxxxx");
	s.insert(5, s1);
	cout << s << endl;
	s.insert(0, 1, 'd');
	cout << s << endl;
	s.insert(4, 10, 's');
	cout << s << endl;

}

值得注意的是,insert还支持迭代器传参。但是迭代器传参只能插入单个字符或者多个重复字符

插入讲完后我来讲一下删除,删除主要用的是erase函数

erase提供的三种重载,第一种是从指定位置默认是第一个位置开始往后删除len长度的字符,如果len长度超出范围,则删除到结尾为止。第二种则是删除指定位置的字符,这里是迭代器传参。第三种则是删除指定区间的字符。

cpp 复制代码
void test_erase()
{
	string s("123456dfasssssssssssfhqqqqxxxxello world1654321");
	s.erase(0, 3);
	cout << s << endl;
	s.erase(s.begin());
	cout << s << endl;
	s.erase(s.end()-1);
	cout << s << endl;
	s.erase(5, 13);
	cout << s << endl;
	s.erase(s.begin(), s.end() - 1);
	cout << s << endl;
}

这里写的还是挺复杂的,稍不留神就会出现意料之外的效果。

对于头删,我们这里的实现方式可以是传坐标也就是erase(0,1),代表从0位置开始删长度为1,也可以直接传begin的迭代器。对于迭代器删除,值得注意的是删除的是当前迭代器所指位置地字符,但是第三种地范围则是左闭右开,假如我们要尾删,第二种必须传end()-1,但是如果要删除包含尾元素,第三种就必须传end()。

插入删除介绍完后我介绍一下查找相关的操作

首先c_str

该函数意味着将string类型转变为C语言支持的字符串类型。

swap意味着交换两个string类型变量的值。

接下来介绍一下find函数

四种重载方式,第一种第二种分别是从指定位置开始查询,查询的内容是string类型以及C语言字符串类型即const char* ,第三种是从某一位置出发,查找指定长度。第四种是查找指定的字符,其中,当从pos位置查找,若成功则返回第一个串的起始下标,若失败则返回npos。

cpp 复制代码
void test_find()
{
	string s("hello worldhellohellohello");
	size_t pos = s.find("hello");
	cout << pos << endl;
	cout << s.find("hello", pos + 1) << endl;
	string s1("hello");
	cout << s.find(s1) << endl;
	cout << s.find('c', 0) << endl;
	cout << s.find(' ', 0) << endl;

}

讲到这里不妨顺带提一下npos

npos虽然赋值为-1但其实是一个很大的数字,因为-1在内存中以补码存储。

介绍了find,rfind其实是一样的就不讲解了。

cpp 复制代码
void test_rfind()
{
	string s("hello worldhellohellohello");
	size_t pos = s.rfind("hello");
	cout << pos << endl;
	cout << s.rfind("hello", pos - 1) << endl;
	string s1("hello");
	cout << s.rfind(s1) << endl;
	cout << s.rfind('c') << endl;
	cout << s.rfind(' ') << endl;

}

接下来看一下这两组

先看第一个find_first_of函数,感觉从字面意思上理解这个函数,他达成的效果和find没什么区别,找第一个嘛,但其实并没有这么简单。

和之前类似,就不过多讲解,简单看一下达成效果。

cpp 复制代码
void test_find_first_of()
{
	string s("The quick brown fox jumps over the lazy dog.");
	string s1("aeiou");
	size_t found = s.find_first_of(s1);
	while (found != string::npos)
	{
		s[found] = '*';
		cout << s << endl;
		found = s.find_first_of(s1);
	}

}

所以,find_first_of其实是find_first_any_of,在我们传入的字符串中,匹配到其中任意一个字符即返回其坐标。

其他三者区别不大,我只提供测试代码,不做具体讲解。

cpp 复制代码
void test_find_first_of()
{
	string s("The quick brown fox jumps over the lazy dog.");
	string s1("aeiou");
	size_t found = s.find_first_of(s1);
	while (found != string::npos)
	{
		s[found] = '*';
		cout << s << endl;
		found = s.find_first_of(s1);
	}

}
void test_find_last_of()
{
	string s("The quick brown fox jumps over the lazy dog.");
	string s1("aeiou");
	size_t found = s.find_last_of(s1);
	while (found != string::npos)
	{
		s[found] = '*';
		cout << s << endl;
		found = s.find_last_of(s1);
	}

}
void test_find_last_not_of()
{
	string s("The quick ");
	string s1("aeiou*");
	size_t found = s.find_last_not_of(s1);
	while (found != string::npos)
	{
		s[found] = '*';
		cout << s << endl;
		found = s.find_last_not_of(s1);
	}

}
void test_find_first_not_of()
{
	string s("The quick ");
	string s1("aeiou*");
	size_t found = s.find_first_not_of(s1);
	while (found != string::npos)
	{
		s[found] = '*';
		cout << s << endl;
		found = s.find_first_not_of(s1);
	}

}

接下来介绍一下substr

截取子串,传参从某个位置开始置某个位置结束。

cpp 复制代码
void test_substr()
{
	string s("hello worldhellohellohello");
	cout << s.substr(3, 7) << endl;
	cout << s.substr(15) << endl;

}

接下来我讲一下+的运算符重载

和以往不同的是+重载并没有在string类中实现,因为如果在类中实现,第一个操作数默认是自己类型的引用,但+应该支持第一个参数为字符或者字符串。

一般来讲=赋值运算符重载函数是相当常用的,它支持传入字符stringC风格字符串三种。

cpp 复制代码
void test_operator2()
{
	string s("auifhk");
	s = s + "xxxxxxxxxxx";
	cout << s << endl;
	s = s + '9';
	cout << s << endl;
	string s1("[[[[[[[");
	s = s + s1;
	cout << s << endl;

}

最后,我简单介绍一下getline函数

这是用来指定输入时边界符的,一般来讲我们输入一个' ',就会默认停止,用这个可以自己指定,默认是'\n'

关于string类的使用至此结束。

接下来会讲一下模拟实现

相关推荐
宝绿特塑业再生科技5 小时前
板材收缩率不稳,户外家具装配尺寸为何对不上:从切割尺寸变化到接缝不一的系统性排查与对策
笔记·科技·学习·生活·户外家具·hdpe再生颗粒·hdpe
2601_967287576 小时前
浚县自建房空调凝水管:坡度、水封与接法怎么定
生活
宝绿特塑业再生科技11 小时前
尺寸稳定性重构:改性再生HDPE破解户外家具热胀冷缩困局
经验分享·学习·生活·户外家具
2601_967287571 天前
自建房双水源给水系统:倒流防止器选型与水锤防护参数
生活
fox06331 天前
预约类平台的责任边界建模:从一个证件办理预约平台的流程设计说起
大数据·数据库·搜索引擎·全文检索·生活
邦泰生物BONTAC1 天前
前沿综述|NAD+在长寿与绝经健康中的双重角色与递送破局
科技·生活·健康医疗
greencherry_2 天前
大连模屿石膏课模具配比全固定,调色浇注之外还缺什么?
算法·生活
宝绿特塑业再生科技3 天前
改性HDPE再生颗粒在户外家具挤出发泡板材中的色差控制与高品质价值重构
经验分享·科技·学习·生活·1024程序员节·户外家具
Stringzhua3 天前
向后理解,向前生活
生活