String(二)————迭代器及相关接口使用

目录

string构造接口(Construct string object)

string的元素访问(读写)

 迭代器


string构造接口(Construct string object)

string相比于C语言的字符数组要好用的多,无论是在初始化还是在读写方面都方便许多。

以basic_string<char> 为例,来看一下它的构造接口:

1、 第一个string():无参类型的构造,字符串长度为0。

2、string (const string& str) :拷贝构造

3、string (const string& str, size_t pos, size_t len = npos)

以一个字符串的第pos个字符为起始,长度为len构造一个字符串:

 如果构造字符串的过程超过了目标字符串最后一位,那么将拷贝到最后一位停止:

4、string (const char* s) :以字符串为参数构造,有两种形式。

5、string (const char* s, size_t n)  :拷贝一个字符串的前n个字符

6、string (size_t n, char c) :构造n个c字符的字符串:

7、string (InputIterator first, InputIterator last) :从first开始到 last结束进行构造字符串:

此外对多个字符串还能进行拼接,使用重载运算符 += 即可:

上面所讲,红色标注的为重点,其他的了解用法即可。

string的元素访问(读写)

 string中也对运算符 [  ]进行了重载,使得可以通过下标来访问元素。

[ ] 运算符重载原型如下:

    char& operator[](size_t i)
    {
        assert(i < s0.size() );
        return _str[i];
    } 

 并且相比于静态数组,它可以防止溢出。

 这里也可以使用范围for:

 看起来范围for好像是比用下标访问要方便一点,但是有的情况下用下标访问比较好,比如需要逆置上面的数组时:

 迭代器

上面的数组还有第三种表示方式,就是迭代器。

迭代器是string类里定义的类型,但不是内部类,只是在其中定义,属于string类。

迭代器 iterators是一种行为像指针的类型,但它底层是不是指针不确定,具体要看实现,但是它的用法很像指针,且看他如何访问数组元素:

	string s0("abcd1234");
	string::iterator it = s0.begin();
	while (it != s0.end())
	{
		*it += 1;
		++it;
	}
	it = s0.begin();
	while (it != s0.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

it 是迭代器的对象,迭代器里面都有begin和end,分别表示第一个元素和最后一个的下一个元素。

这是正向迭代器,还有反向迭代器

	string::reverse_iterator rit = s0.rbegin();
	while (rit != s0.rend())
	{
		*rit += 1;
		++rit;
	}
	rit = s0.rbegin();
	while (rit != s0.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

 与正向相对,反向开始是rbegin,结束是rend,它是倒着遍历的。

看到迭代器的示例,有人会问 “这迭代器看上去非常麻烦,不好理解而且难记,不如直接用下标访问的方式 ”

————下标访问的方式在string和vector(顺序表)中可以使用,但是在其他容器(如map)就无法使用了。而迭代器是一种容器通用的遍历方式,具有普遍性。

迭代器还有const修饰类型的,上面讲的迭代器对数据可读可写,const修饰的是只读属性,像print这种接口就要写成const修饰的。

void print(const string& s)
{
	string::const_iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
int main()
{
	string s0("abcd");
	print(s0);
	return 0;
}

string::const_iterator it = s.begin(); 这里要用const修饰迭代器对象,防止修改迭代器里的内容(*it)注意:这里不能写成 const string::iterator it = s.begin(); 这种是防止修改 it本身,而我们要遍历是需要修改 it 的,而 it 指向的内容不能修改。

const修饰的迭代器有正向的,也就有反向的。

void Test1()
{
	string s0 = "qwer";
	string::const_reverse_iterator rit = s0.rbegin();
	while (rit != s0.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
}

看上去确实长了点,但是有的时候是不可避免的,只要意思表达清楚即可,何况库里面也是这么使用的。

总结:正向、反向迭代器可以读取和修改容器数据,而const正向、反向迭代器可以读取容器数据。

那么什么时候需要const版本,什么时候需要非const版本呢?

1、只读功能函数,只需要const版本;

2、只写功能函数,只需要非const版本;

3、可读可写功能函数,两个都需要。

可读可写功能的函数,因为有可能是只读对象调用它,也可能是可读可写对象调用它,而const修饰的只读的对象只能调用const版本的函数,  只写的 \ 可读可写的对象可以不需要const版本的函数,因此需要提供两个版本。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值