前言
hello,大家好。这期文章我们来分享三种访问和遍历string类对象的方法,闲言少叙,让我们开始啦。
1. 下标+[]
1.1 代码实现
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
for (size_t i = 0; i < s1.size(); ++i)
{
cout << s1[i];
}
return 0;
}
1.2 细节解析
这种方法其实就像访问数组一样去访问string类的对象。不过我们要注意,这种方法本质上是一种函数调用。s1【i】相当于s1.operator【】(i)。这就会返回第i个位置的字符的引用。并且这种方法不仅可以遍历字符,也可以写入字符,比如像下面这样。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
for (size_t i = 0; i < s1.size(); ++i)
{
s1[i]='x';
}
cout << s1 << endl;
return 0;
}
代码中的size_t,也许你好奇它是什么。我们来看一下
size_t是基本无符号整数类型之一的别名。它是一种能够以字节表示任何对象大小的类型:size_t是sizeof操作符返回的类型,在标准库中广泛用于表示大小和计数。
也就是说size_t就相当于unsigned int类型。size_t i=0,就是定义了一个无符号整形的i,i=0。 而s1.size()中的size()则是返回字符串长度的函数,所以i<s1.size()就是i<字符串的长度的值。 解释到这里,我们就更清晰的理解这种方法和访问数组的类似之处了。
1.3 题目应用
题目的链接在这里 找出字符串中第一个只出现一次的字符 对于这个题目,首先我们要知道每一个字符出现的次数,于是我们要设计一个计数器,然后我们只要找到第一个出现一次的字符就好了。来看代码
class Solution
{
public:
int firstUniqChar(string s)
{
int count[26]={0};
for (size_t i = 0; i < s.size(); ++i)
{
count[s[i]-'a']++;
}
for (size_t i = 0; i < s.size(); ++i)
{
if(count[s[i]-'a']==1)
return i;
}
return -1;
}
};
在这段代码中,我们利用了两次下标遍历。就完美地实现了这个题目,注意count[s[i]-‘a’],我们要这样写的原因是ASCII值,s[i]是一个字母,可以默认为小写,小写字母减去a的ASCII码,就是会得到它在0到26之间的位置。这个位置对应的数字是0.只要出现这个位置一次,就代表这个位置对应的字母出现一次。
2. 迭代器
什么是迭代器呢?我们在后续的文章中会进行详细的介绍,在这里我们只需要简单了解一下迭代器就好
迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。
我们在这里呢,就只需要记住用迭代器遍历string类对象的写法就可以了。我们可以把迭代器想象为指针。
2.1 begin+end 正向迭代器
2.1.1 代码实现
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it;
++it;
}
return 0;
}
2.1.2 细节解析
begin是返回字符串第一个字符的迭代器,而end则是返回一个指向字符串后一个字符的迭代器。注意,end返回的是指向字符的下一个字符的迭代器。C++中的迭代器一般是左闭右开区间。
2.2 反向迭代器
2.2.1 代码实现
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit;
++rit;
}
return 0;
}
2.2.2 细节解析
我们发现,反向迭代器输出的是正向迭代器相反的结果。在反向迭代器中,rbegin指向字符串的最后一个字符(即字符串的反向开头)。rend返回一个反向迭代器,指向字符串第一个字符(被认为是字符串的反向端)前面的理论元素。正向迭代器与反向迭代器的不同还在于,正向迭代器的++是向尾部走的,而反向迭代器则向头部走。
2.3 可读可写
无论是正向迭代器还是反向迭代器也都是可以写入字符的,我们以正向迭代器为例。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
string::iterator it = s1.begin();
while (it != s1.end())
{
*it='a';
cout << *it;
++it;
}
return 0;
}
3. 范围for
3.1 代码实现
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello,world";
for (auto e : s1)
{
cout << e;
}
return 0;
}
3.2 细节解析
范围for是C++11的作品。它在底层是根据迭代器来实现的。它会依次取容器中的数据,赋值给e,会自动判断结束。但是注意,范围for是不支持写入的,因为我们是从容器里取出来,就相当于从箱子里拿出一个个小球放到我们眼前,这个过程中是无法改变小球的大小和颜色的。
后记
好的,我们这期文章就分享到这里了。希望对大家有所帮助。老规矩,这个系列的文章最后都是要分享一首诗的,今天我们的分享是《Shut Out That Moon》如下:
Close up the casement, draw the blind,
Shut out that stealing moon,
She wears too much the guise she wore
Before our lutes were strewn
With years-deep dust, and names we read
On a white stone were hewn.
Step not forth on the dew-dashed lawn
To view the Lady's Chair,
Immense Orion's glittering form,
The Less and Greater Bear:
Stay in; to such sights we were drawn
When faded ones were fair.
Brush not the bough for midnight scents
That come forth lingeringly,
And wake the same sweet sentiments
They breathed to you and me
When living seemed a laugh, and love
All it was said to be.
Within the common lamp-lit room
Prison my eyes and thought;
Let dingy details crudely loom,
Mechanic speech be wrought:
Too fragrant was Life's early bloom,
Too tart the fruit it brought!
by Thomas Hardy
|