C++ 带你吃透string容器的使用

这篇具有很好参考价值的文章主要介绍了C++ 带你吃透string容器的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

接下来我们就要正式进入C++中STL的学习当中了
今天我们介绍的是STL中的string容器
我们对于STL的学习可以借助文档去学习:
我们今天就要通过cplusplus这个网站来介绍string容器

一.string容器概述

首先我们要了解的是:
什么是string容器?
c++find函数用法,爱上C++,c++,STL,string,迭代器
注意:使用string容器需要包含头文件:<string>
在了解了string容器之后,我们先来学习一下string容器的使用

二.string容器的使用

1.string容器的默认成员函数

我们先来介绍string容器的默认成员函数,这里只显示了构造函数(其中也包含拷贝构造函数),析构函数,赋值运算符重载这4个默认成员函数.
至于剩下的那两个取地址运算符重载函数则不是很重要,我们平常也不需要特别关心那两个默认成员函数
那么下面我们就去介绍这4个默认成员函数
c++find函数用法,爱上C++,c++,STL,string,迭代器

1.构造函数和拷贝构造函数

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们一一演示,并说明用法

第一种和第二种:
c++find函数用法,爱上C++,c++,STL,string,迭代器

//这是最常用,最常见的两种用法
string s1;//第一种用法:无参构造
string s2("hello string");//第二种用法:含参构造,使用常量字符串来初始化s2
string s3 = s2;//注意:拷贝构造,而不是赋值运算符重载!
s3 = s1;//这个才是赋值运算符重载
string s4(s3);//拷贝构造

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来看第三种用法:
c++find函数用法,爱上C++,c++,STL,string,迭代器

string s2("hello string");
string s4(s2, 1, 6);//ello s
string s5(s2, 0, 100);//hello string

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面来看第4种用法
c++find函数用法,爱上C++,c++,STL,string,迭代器
其实这个重载版本没什么太大的价值
因为string容器的构造函数支持单参数的构造函数的隐式类型转换
C++类和对象下(初始化列表,静态成员,explicit关键字,友元)
关于单参数的构造函数的隐式类型转换的问题,大家可以看我的这篇博客,在介绍explicit关键字的时候有详细的介绍

const char* ptr = "hello C string";
string s6(ptr);

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面来看第5种用法
c++find函数用法,爱上C++,c++,STL,string,迭代器

const char* ptr = "hello C string";
string s7(ptr, 4);

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面来看第6种
c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
至于第7种:
c++find函数用法,爱上C++,c++,STL,string,迭代器
这个是跟迭代器有关的,我们目前先不谈,因为我们还没有介绍迭代器呢
在文章的最后的时候,我们就会揭开string容器的迭代器的神秘面纱

2.赋值运算符重载

c++find函数用法,爱上C++,c++,STL,string,迭代器

string s9("hello operator=");
s9 = "hello world";

const char* s = "hello wzs";
s9 = s;

char ch = 'w';
s9 = ch;

c++find函数用法,爱上C++,c++,STL,string,迭代器

3.析构函数

c++find函数用法,爱上C++,c++,STL,string,迭代器

2.string容器的遍历和访问元素

这里要首先介绍两个函数
c++find函数用法,爱上C++,c++,STL,string,迭代器

1.operator[]运算符重载

c++find函数用法,爱上C++,c++,STL,string,迭代器
也就是说我们可以像访问数组一样来访问string容器
c++find函数用法,爱上C++,c++,STL,string,迭代器

string s1 = "hello string";
for (int i = 0; i < s1.size(); i++)
{
	cout << s1[i] << " ";
}
cout << endl;
cout << s1 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
同理因为s1没有被const修饰,所以调用的是operator[]的第一种重载版本

char& operator[] (size_t pos);

因此也可以进行修改

string s1 = "hello string";
for (int i = 0; i < s1.size(); i++)
{
	s1[i] ++;
	cout << s1[i] << " ";
}
cout << endl;
cout << s1 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
介绍完operator[]的用法之后
让回到这个问题:为什么要重载两种版本呢?
因为会有const string这种类型的需求
c++find函数用法,爱上C++,c++,STL,string,迭代器
重载了两个版本之后:这样就可以保证s1这个被const修饰的字符串不被[]所修改了

2.iterator迭代器

1.begin()和end()

首先我们要先介绍两个特殊的迭代器:begin()和end()
c++find函数用法,爱上C++,c++,STL,string,迭代器
在这个位置处,我们可以暂时把iterator迭代器当做指针去使用,因此我们就可以这样去遍历访问元素了

string s2 = "hello iterator";
string::iterator it = s2.begin();
while (it != s2.end())//注意:我们使用iterator访问和遍历时要注意左闭右开使用[begin,end)
{
	cout << *it << " ";//这里可以暂时理解为像是指针解引用的用法一样
	it++;//这里可以暂时理解为像是指针自增(也就是后移)的用法一样
}
cout << endl;
cout << s2 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
同样的,这个迭代器也可以用来改变这个string具体位置的元素的值

string s2 = "hello iterator";
string::iterator it = s2.begin();
while (it != s2.end())//注意:我们使用iterator访问和遍历时要注意左闭右开使用[begin,end)
{
	*it += 1;//(*it)++;这样也可以,不过不要忘了加小括号(运算符优先级的问题)
	cout << *it << " ";//这里可以暂时理解为像是指针解引用的用法一样
	it++;//这里可以暂时理解为像是指针自增(也就是后移)的用法一样
}
cout << endl;
cout << s2 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器

const string s2 = "hello iterator";
string::const_iterator it = s2.begin();
while (it != s2.end())//注意:我们使用iterator访问和遍历时要注意左闭右开使用[begin,end)
{
	//*it += 1;
	(*it)++;//err
	cout << *it << " ";//这里可以暂时理解为像是指针解引用的用法一样
	it++;//这里可以暂时理解为像是指针自增(也就是后移)的用法一样
}
cout << endl;
cout << s2 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

2.rbegin()和rend()

迭代器也可以倒着遍历,就像这样:
c++find函数用法,爱上C++,c++,STL,string,迭代器
可能这个英文解释不是很好理解,下面我们来演示一下:

//反向迭代器:rbegin(),rend()
string::reverse_iterator it = s1.rbegin();
while (it != s1.rend())
{
	cout << *it << " ";
	it++;
}
cout << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
同理,这个rbegin()和rend()也分为const迭代器和非const迭代器,
在这里就不赘述了,因为刚才讲begin()和end()的时候说明过区别

不过实际当中这个rbegin()和rend()并不常用
远远没有begin()和end()的出场率高

下面大家可能有疑问,这个迭代器访问元素哪有我直接下标访问香啊
这个迭代器也不过如此嘛
下面我们来说一下iterator的真正价值

3.iterator的真正价值

c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
除此之外,借助迭代器还可以使用很多库函数的功能
比如:使用reverse逆置string,vector,list等等
c++find函数用法,爱上C++,c++,STL,string,迭代器

#include <list>
#include <vector>
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	vector<int>::iterator vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;

	list<double> lt;
	lt.push_back(1.1);
	lt.push_back(1.2);
	lt.push_back(1.3);
	lt.push_back(1.4);
	lt.push_back(1.5);
	list<double>::iterator lit = lt.begin();
	while (lit != lt.end())
	{
		cout << *lit << " ";
		lit++;
	}
	cout << endl;

	//对string逆置
	string s1("hello string");
	cout << s1 << endl;
	reverse(s1.begin(), s1.end());//依旧是给左闭右开:begin和end
	cout << s1 << endl;

	reverse(v.begin(), v.end());//这个reverse算法也可以适用vector,list
	vit = v.begin();
	while (vit != v.end())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;

	reverse(lt.begin(), lt.end());
	lit = lt.begin();
	while (lit != lt.end())
	{
		cout << *lit << " ";
		lit++;
	}
	cout << endl;
	return 0;
}

c++find函数用法,爱上C++,c++,STL,string,迭代器

4.范围for

string容器也支持范围for的用法
关于范围for的知识,请看这篇博客:C++入门3+类和对象上

for (auto& e : s1)
{
	cout << e << " ";
}
cout << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

5.at()

关于at(),它跟[]的用法很像

string s1("hello world");
for (int i = 0; i < s1.size(); i++)
{
	cout << s1.at(i) << " ";
}

c++find函数用法,爱上C++,c++,STL,string,迭代器
但是它们之间也存在一些差异
c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来演示一下:
这是[]来越界访问
c++find函数用法,爱上C++,c++,STL,string,迭代器
这是at来越界访问
c++find函数用法,爱上C++,c++,STL,string,迭代器

3.string容器与容量相关的函数

1.capacity,size,length

size()和length()我们前面提到过了,这里就不赘述了
c++find函数用法,爱上C++,c++,STL,string,迭代器
接下来是容量capacity这个概念
c++find函数用法,爱上C++,c++,STL,string,迭代器

2.reserve

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来演示一下,顺便看一下在VS2019中的扩容机制

string s1;
int old_capacity = s1.capacity();
cout << old_capacity << endl;
for (int i = 0; i < 100; i++)
{
	s1.push_back('w');//将'w'这个字符尾插进入s1当中
	if (old_capacity != s1.capacity())
	{
		cout << s1.capacity() << endl;
		old_capacity = s1.capacity();
	}
}

c++find函数用法,爱上C++,c++,STL,string,迭代器

string s1;
s1.reserve(100);
int old_capacity = s1.capacity();
cout << old_capacity << endl;
for (int i = 0; i < 100; i++)
{
	s1.push_back('w');//将'w'这个字符尾插进入s1当中
	if (old_capacity != s1.capacity())
	{
		cout << s1.capacity() << endl;
		old_capacity = s1.capacity();
	}
}

c++find函数用法,爱上C++,c++,STL,string,迭代器
然后我们将插入的数据改为1000
看一下扩容的区别

string s1;
int old_capacity = s1.capacity();
cout << old_capacity << endl;
for (int i = 0; i < 1000; i++)
{
	s1.push_back('w');//将'w'这个字符尾插进入s1当中
	if (old_capacity != s1.capacity())
	{
		cout << s1.capacity() << endl;
		old_capacity = s1.capacity();
	}
}

c++find函数用法,爱上C++,c++,STL,string,迭代器
扩容的机制在不同编译器下是不一样的
下面我们以Linux环境下的g++编译器来演示一下
c++find函数用法,爱上C++,c++,STL,string,迭代器
一模一样的代码,我们来看一下运行结果
c++find函数用法,爱上C++,c++,STL,string,迭代器
大家需要了解reserve的常见使用场景:提前扩容
c++find函数用法,爱上C++,c++,STL,string,迭代器

3.resize

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来演示一下:
第一种情况:
n<size:在VS编译器下不会改变容量,只会改变size

string s1("hello world");
//1.n<size
s1.resize(4);
cout << s1;

c++find函数用法,爱上C++,c++,STL,string,迭代器
第二种情况:
size<n<capacity 此时相当于尾插字符c或者’\0’

string s1("hello world");
//2.size<n<capacity
cout << s1.capacity() << endl;
s1.resize(13);
cout << s1;

c++find函数用法,爱上C++,c++,STL,string,迭代器
可见,的确是用’\0’来填充的
刚才我们看到:s1的容量是15
c++find函数用法,爱上C++,c++,STL,string,迭代器
第三种情况:
n>capacity: 此时相当于先扩容,然后尾插字符c或者’\0’
c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来介绍一下resize的常见使用场景:
c++find函数用法,爱上C++,c++,STL,string,迭代器

4.clear,empty

c++find函数用法,爱上C++,c++,STL,string,迭代器
这两个函数都很简单,大家了解即可

4.尾插操作

下面这几个尾插操作都是自动扩容的,不需要我们操心

1.push_back

c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器

2.append

c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
关于其他的用法,平常并不常用,大家知道即可
比如使用迭代器来append一段区间
c++find函数用法,爱上C++,c++,STL,string,迭代器

3.+=运算符重载

真正常用的是这个+=运算符重载
c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器

5.指定位置的修改操作

1.insert

c++find函数用法,爱上C++,c++,STL,string,迭代器
关于单参数隐式类型转换的问题,请看这篇博客当中的explicit关键字部分的介绍
C++类和对象下(初始化列表,静态成员,explicit关键字,友元)
下面我们来演示一下insert的用法

string s("[hello world]");
s.insert(0, 1, 'w');//从0位置头插一个字符:'w'
s.insert(0, "20231122");//从0位置头插一个字符串
cout << s << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

string s("[hello world]");
s.insert(2, "0123456789", 3, 4);//在s串的下标为2的位置开始插入一个子串
//这个子串是"0123456789"的从下标为3的位置开始,长度为4的子串:也就是3456
cout << s << endl;//[h3456ello world]

c++find函数用法,爱上C++,c++,STL,string,迭代器
因为insert的插入效率不高(因为string是顺序表,物理空间是连续的,插入一个字符或者删除一个字符会造成大量数据的挪动,因此效率不高)

所以insert能少用就少用

2.erase

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来演示一下:

string s("0123456789");
s.erase(3, 4);//从3号下标位置开始删除4个字符,也就是删除了3456
cout << s << endl;
s.erase(2);//默认从2号下标开始的删除所有字符
cout << s << endl;
s.erase();//默认删除所有字符
cout << s << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
跟insert一样,效率低,能少用就少用

3.replace

c++find函数用法,爱上C++,c++,STL,string,迭代器
其实replace并不好用,因为效率低
频繁挪动数据,偶尔用一次就算了
但是不建议一次性使用很多次,效率会非常低,因为会造成数据频繁重复性地挪动
我们介绍完find之后会结合find跟replace来介绍一个场景
在那里我们将会对replace的低效性,重复性有更深的理解

下面我们先来演示一下replace的用法

string s1 = "ABCDEFGHI";
string s2 = "abcdefghi";
s1.replace(2, 3, s2);//把s1的从下标为2位置开始长度为3的字符替换为字符串s2
//也就是把CDE替换为abcdefghi
cout << s1 << endl;
s2.replace(s2.begin() + 2, s2.begin() + 4, "------");//把s2的[2,4)区间内的字符(也就是cd)替换为"------"
cout << s2 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

6.查找,交换,截取操作

1.find

c++find函数用法,爱上C++,c++,STL,string,迭代器

string s1("abcd 1234 xxxx");
size_t index1 = s1.find("cd", 1);//从1号下标开始查找字符串cd
cout << index1 << endl;
size_t index2 = s1.find("cdef", 1, 2);//从1号下标开始查找字符串cdef的前2个字符:cd
cout << index2 << endl;
size_t index3 = s1.find(' ', 1);//从1号下标开始查找字符' '
cout << index3 << endl;

//查不到的情况:
size_t index4 = s1.find("abcd", 1);//从1号下标开始查找字符串abcd  ->  查不到,返回npos
cout << index4 << endl;//无符号整形最大值

c++find函数用法,爱上C++,c++,STL,string,迭代器

2.其他跟find相关的函数

用法相同,注意跟find的区别即可

1.rfind

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面的这几个大家知道有这么个函数即可
不常用

2.了解即可

c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
下面是cplusplus网站上的几个用例
大家可以了解一下

//这个功能就是把所有的aeiou都替换为空格
string str("abcdefghigklmnopqrstuvwxyz");
size_t found = str.find_first_of("aeiou");
while (found != std::string::npos)
{
	str[found] = ' ';
	found = str.find_first_of("aeiou", found + 1);
}
cout << str << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

void SplitFilename(const std::string& str)
{
	std::cout << "Splitting: " << str << '\n';
	std::size_t found = str.find_last_of("/\\");
	std::cout << " path: " << str.substr(0, found) << '\n';
	std::cout << " file: " << str.substr(found + 1) << '\n';
}
注意:
1.C语言中'\'是转义字符
比如'\0','\n'等等,但是'\0','\n'都是一个字节,也就是说被转义字符修饰的字符仍然是一个字符,而不是两个
如果我们想要表示这个字符的话,就要对这个转义字符进行转义
也就是说'\\'这个才是真正的'\'

2.文件路径分隔符
Windows下的文件路径分隔符是'\'
Linux下的文件路径分隔符是'/'
而这个SplitFilename函数的作用就是既可以分割Windows下的文件路径,也可以分割/Linux下的文件路径
int main()
{
	std::string str1("/usr/bin/man");
	std::string str2("c:\\windows\\winhelp.exe");

	SplitFilename(str1);
	SplitFilename(str2);

	return 0;
}

c++find函数用法,爱上C++,c++,STL,string,迭代器

3.find和replace的应用场景

《剑指offer》上面有这么一道题:
c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们先使用find和replace来实现一下:

string s("We are happy");
cout << s << endl;
size_t pos = s.find(' ');
while (pos != string::npos)
{
	s.replace(pos, 1, "%20");
	pos = s.find(' ');
}
cout << s << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们调试看看过程
c++find函数用法,爱上C++,c++,STL,string,迭代器
我们可以看出,每次执行replace,对应空格之后的字符都要向后挪动
这就会导致出现频繁的空格移动
如果是比较长的字符:像是这样的
那这个效率就太低了
c++find函数用法,爱上C++,c++,STL,string,迭代器
大家也可以用计算空格数来扩容后移的方法去做
但是那样还是比较麻烦的

下面介绍一种非常好用的方法:
空间换时间:

string s("We are happy and i am wzs and today is 2023 11 22");
cout << s << endl;
string s1;
for (auto& e : s)
{
	if (e == ' ')
	{
		s1 += "%20";
	}
	else
	{
		s1 += e;
	}
}
s = s1;
cout << s << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
效率高,而且非常好实现

4.swap

c++find函数用法,爱上C++,c++,STL,string,迭代器
这个swap的底层实现类似于这样:

void swap(string& s)
{
	//这里调用的是std(标准库中的那个swap函数)
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

这里的swap的实现其实就是
交换指针,交换_size和_capacity
这样做的好处是无需再去拷贝string了,而是直接交换指针即可,大大优化了swap的效率
可见这个设计是非常巧妙的

5.substr

c++find函数用法,爱上C++,c++,STL,string,迭代器
下面我们来演示一下:
c++find函数用法,爱上C++,c++,STL,string,迭代器

6.find和substr的应用场景

find和substr也能够很好地放到一起使用
比方说下面这个场景

对于这个网址来说:
http://www.baidu.com/index.html?name=mo&age=25#dowell

我们想要截取它的
1.协议:http
2.域名:www.baidu.com
3.剩下的这个 index.html?name=mo&age=25#dowell
(包括:端口、路径(虚拟路径)、携带的参数、哈希值)
浏览器地址栏的完整URL都包含哪些内容都各代表什么?
大家感兴趣的话可以看看这位大佬的文章
这些东西我们以后会介绍的

下面我们回归这个需求,开始实现一下

string s("http://www.baidu.com/index.html?name=mo&age=25#dowell");
string substr1, substr2, substr3;
//我们的目标是:
//substr1:http
//substr2:www.baidu.com
//substr3:index.html?name=mo&age=25#dowell
size_t pos1 = s.find(':', 0);//从0下标开始出发查找':'
substr1 = s.substr(0, pos1 - 0);//[0,pos1):左闭右开的区间:长度是右区间-左区间 也就是pos1-0
size_t pos2 = s.find('/',pos1 + 3);//pos1位置此时是':'  我们下一次要从pos1+3的位置开始查找 也就是第一个'w'的位置
substr2 = s.substr(pos1 + 3, pos2 - (pos1 + 3));//[pos1+3,pos2):这个区间内的子串
substr3 = s.substr(pos2 + 1);//从pos2+1开始一直截取到最后即可
cout << substr1 << endl;
cout << substr2 << endl;
cout << substr3 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器
还有一个场景:
取文件后缀名
这是我随便编的一个文件

string s("filename.cpp.txt.zip");
//它的真实后缀名是zip
//我现在就是只想要它的真实后缀名
//你给我放到str1这个string中
size_t pos = s.rfind('.');
string str1 = s.substr(pos);
cout << str1 << endl;

c++find函数用法,爱上C++,c++,STL,string,迭代器

7.string类型转为const char*类型

1.c_str

我们在文件操作的时候提到过fopen函数
今天我们想这样去读取一个文件:
c++find函数用法,爱上C++,c++,STL,string,迭代器
这时c_str就排上用场了
c++find函数用法,爱上C++,c++,STL,string,迭代器
这时关于fgetc函数的使用:读取一个文件的内容
关于C语言文件操作的内容,大家可以看我的这一篇博客:
C语言文件操作详解
c++find函数用法,爱上C++,c++,STL,string,迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
这样我们就成功读取了

2.data

c++find函数用法,爱上C++,c++,STL,string,迭代器

8.非成员函数

1.比较运算符重载

c++find函数用法,爱上C++,c++,STL,string,迭代器

2.+运算符重载

c++find函数用法,爱上C++,c++,STL,string,迭代器

3.getline

要介绍这个getline
我们可以通过一道题目来深刻理解getline的价值
c++find函数用法,爱上C++,c++,STL,string,迭代器
牛客:字符串最后一个单词的长度

#include <iostream>
using namespace std;
int main() {
    string s;
    cin>>s;
    size_t pos=s.rfind(' ');
    //没有找到,返回npos
    //说明该字符串只有一个单词,返回size即可
    if(pos==string::npos)
    {
        cout<<s.size()<<endl;
    }
    //找到了
    //hello nowcoder
    //pos指向空格  size指向'\0'  最后一个单词是:(pos,size)左开右开区间内的
    //长度是右侧-左侧-1  也就是size-pos-1
    else 
    {
        cout<<s.size()-pos-1<<endl;
    }
    return 0;
}

c++find函数用法,爱上C++,c++,STL,string,迭代器
我们发现,我们输出的答案总是第一个单词的长度,为什么呢?
因为:
c++find函数用法,爱上C++,c++,STL,string,迭代器

string s;
getline(cin,s);//getline的用法
#include <iostream>
using namespace std;
int main() 
{
    string s;
    getline(cin,s);//getline的用法
    size_t pos=s.rfind(' ');
    if(pos==string::npos)
    {
        cout<<s.size()<<endl;
    }
    else 
    {
        cout<<s.size()-pos-1<<endl;
    }
    return 0;
}

c++find函数用法,爱上C++,c++,STL,string,迭代器

4.<< 和 >>

对于流插入和流提取
我们只需要知道可以直接对string容器进行cout和cin即可

9.其他不太重要的函数

1.assign

c++find函数用法,爱上C++,c++,STL,string,迭代器

2.copy

c++find函数用法,爱上C++,c++,STL,string,迭代器

三.揭秘string容器的迭代器

1.string容器迭代器的本质

其实对于string容器来说
我们完全可以使用一个char*指针去自己实现这个迭代器
也就是这样:

typedef char* iterator
iterator begin()
{
	return _str;
}
iterator end()
{
	return _str + _size;
}

然后我们就可以使用了

2.iterator迭代器使用

在这里我先模拟实现了string的构造函数,析构函数,还有这个迭代器
关于string的模拟实现,我们以后会单独出一篇博客的

namespace wzs
{
	class string
	{
	public:
		//构造函数
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		//析构函数
		~string()
		{
			delete[]_str;
			_str = nullptr;
			_size = 0;
			_capacity = 0;
		}
		//迭代器和范围for
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
	private:
		char* _str;
		int _size;
		int _capacity;
	};
	void test()
	{
		string s2 = "hello iterator";
		string::iterator it = s2.begin();
		while (it != s2.end())
		{
			(*it)++;
			cout << *it << " ";
			it++;
		}
		cout << endl;
		for (auto& e : s2)
		{
			cout << e << " ";
		}
	}
}
int main()
{
	wzs::test();
	return 0;
}

然后我们就可以自己去玩这个迭代器了
c++find函数用法,爱上C++,c++,STL,string,迭代器
我们仅仅使用我们的这个string类,就可以实现iterator和范围for了

3.范围for的本质

其实范围for就是迭代器
c++find函数用法,爱上C++,c++,STL,string,迭代器
我们可以通过查看反汇编看到begin()和end()的身影
c++find函数用法,爱上C++,c++,STL,string,迭代器
为什么说范围for式"傻瓜式"的替换呢?
因为我们只有当我们遵守迭代器的规范
把迭代器命名为begin(),end()时才会有用
否则就没用了
比如我现在给它改名为Begin
c++find函数用法,爱上C++,c++,STL,string,迭代器

4.iterator的补充

但是所有的iterator都是指针吗?
并不是这样的
string容器之所以可以使用char*来当作迭代器是因为string容器在物理空间上是连续的
对于那些物理空间并不连续的容器来说,迭代器就不是这么简单了
对于那些容器的迭代器我们以后会说明的

补充最前面的构造函数的最后一个重载版本

c++find函数用法,爱上C++,c++,STL,string,迭代器
了解了string容器的迭代器之后
我们再来谈一下最后一个构造函数的重载版本
这个其实就是传入迭代器区间进行构造
c++find函数用法,爱上C++,c++,STL,string,迭代器

注意:get_allocator以后会介绍

这个get_allocator涉及到适配器的知识,我们以后会介绍的

以上就是C++ 带你吃透string容器的使用的全部内容,希望能对大家有所帮助!文章来源地址https://www.toymoban.com/news/detail-751515.html

到了这里,关于C++ 带你吃透string容器的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mysql中的find_in_set() 函数用法详解及使用场景

    一、find_in_set() 函数详解 示例: 相信大家看完以上示例就知道这个函数的大概作用了,以下是MySQL手册中官方说明 概括一下就是(前一个字符串是A,后一个字符串是B): 如果B字符串包含A字符串:则返回大于0的值,这个值就是A字符串在B字符串的所在位置; 如果B字符串不

    2024年02月13日
    浏览(43)
  • 【C++】STL容器——string类的使用指南(含代码演示)(8)

    前言 大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《初学者易

    2024年02月08日
    浏览(45)
  • 【MATLAB】find函数及其用法

            返回一个包含数组 X 中每个 非零元素的线性索引向量 。         如果 X 为向量,则 find 返回方向与X相同的向量。如果 X 为多维数组,则 find 返回由结果的 线性索引组成的列向量 。如果 X 包含非零元素或为空,则 find 返回一个空数组。         线性索引组

    2023年04月09日
    浏览(46)
  • 如何使用JDBC操作数据库?一文带你吃透JDBC规范

    大家好,我是橙子。最近又肝了几个大夜,总结了 JDBC 完整版的基础教程和实战案例训练。快来看看这些 Java 基础性的代码你有没有忘记? 在 Java 开发中,使用 Java 语言操作数据库是非常重要的一部分,那么 Java 语言是如何操作数据库的呢? 我们需要使用不同厂商的数据库

    2024年02月03日
    浏览(246)
  • 【C++ • STL】一文带你走进string

    ヾ(๑╹◡╹)ノ\\\" 人总要为过去的懒惰而付出代价 ヾ(๑╹◡╹)ノ\\\" STL (standard template libaray- 标准模板库 ):是C++标准库的 重要组成部分 ,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。 STL六大组件 开源的:linux、git、STL、mysql、安卓……【开源会发

    2024年02月09日
    浏览(47)
  • 【C++】:string用法详解

    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关string的基本用法,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏: C语言:从入门到精通 数据结构专栏: 数据结构 个  人  主  页 : stackY、 C + + 专 栏   : C++ Linux 专

    2024年02月08日
    浏览(42)
  • C++ | string用法指南

    目录 前言 一、初始string 1、string是什么 2、string的使用 (1)构造函数 (2)赋值重载 (3)容量相关接口 (4) 迭代器 (5)元素访问 (6)修改 (7)其他类型函数 (8)非成员函数         本文主要介绍STL容器之一  ----  string,在学习C++的过程中,我们要将C++视为一个

    2024年02月06日
    浏览(35)
  • C++中string类用法

    在C语言中,我们对于对于字符数组的认识,仅仅局限于字符串,我们对于该数组进行一些操作的时候,往往要配合str系列的库函数来使用,但是这些库函数比较繁琐,底层空间需要用户来维护,有可能会在操作中越界访问。 C++中提供了string类,来完善对于字符串的使用和处

    2024年02月16日
    浏览(33)
  • Python字符串函数及用法 [string]

    一.内置字符串处理方法 在python解释器的内部,所有数据类型都采用面向对象方法实现,封装为一个类. 字符串也是一个类 .字符串类型共包含 43个内置方法. 二、16个常用函数 方法 描述 str.len() 返回str字符串的长度 str.lower() 返回字符串str的副本,全部字符 小写 str.upper() 返回字符

    2023年04月09日
    浏览(45)
  • 【C++】一篇文章带你深入了解string

    C语言中,字符串是以’\\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。 string的文档介绍 字符串是表示字符序列的类

    2024年04月08日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包