C++ string(二)

size()

size:获取它有多少个字符
size_t size() const;

int main()
{
	string s1("hello world");

	size_t ret = s1.size();
	//计算的是\0前面的字符个数
	cout << ret << endl;//11

	return 0;
}

三种遍历string的方式

1.下标 + [ ]
仅支持数组不支持链表

int main()
{
	string s1 = ("hello world");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	//h e l l o   w o r l d
	cout << endl;

	return 0;
}

2.迭代器
迭代器(iterator):像指针一样的东西,不一定是指针
迭代器可以用来访问所有容器(数据结构,链表,树)

it不一定是指针,如果不是指针,*和++会进行重载
begin():返回开始位置的迭代器
end():返回最后一个有效字符的下一个位置
在这里插入图片描述

int main()
{
  string::iterator it = s1.begin();
  while (it != s1.end())
 {
	cout << *it << " ";
	++it;
 }
 cout << endl;
 return 0;
}

3.范围for
C++11提供的范围for
可以支持所有的容器
自动从s1中取每个值给ch变量,auto自动推导类型
auto:自动赋值,自动迭代,自动判断结束

int main()
{
  for (auto ch : s1)
  {
	cout << ch << " ";
  }
 cout << endl;
 return 0;
}

编译后自动替代为迭代器,底层都是迭代器,范围for的优点是更加方便

<1>.for(auto ch : s)
拷贝不影响string本身
<2>.for(auto& ch : s)
引用会影响string本身

auto

1.auto 可以用来简化代码(类型)
可以用auto来替换长类型

<3>.string::iterator it = s2.begin();
string::iterator:是类型
<3>可以写成
auto it = s2.begin();

2.auto推导类型
根据函数的返回值或右边的类型推导
auto e;(x)

auto c = 'a';
cout << typeid(c).name() << endl;
//char 
c:可以是类型或者是对象都打印出类型

auto arrary[] = {4,5,6};
auto 不能定义数组

auto a = 1,b = 2(v)
auto a = 3,b = 3.1(x)

auto 不能做参数
void func2(auto a) (x)
{}

auto 可以做返回值,但要谨慎使用
auto func3()
{
  return 1;
}
谨慎使用,如果多层返回
int func1()
{
  return 10;
}
auto func2()
{
  return func1();
}
auto func3()
{
  return func2();
}

int main()
{
  auto ret = func3();
  return 0;
}

范围for:遍历数组和容器只是为了方便
1.用于容器的使用
2.用于数组的使用可以简化代码

for(auto& e : array)
{
   //改变了array中的值,引用
   e *= 2;
}
for(auto e : array)
{
   e:变量
   array:对象
   cout << e << " " << endl;
   //拷贝不改变原数组的内容
}

底层替换成了指针,数组没有迭代器
auto 在预处理阶段不做处理,在编译阶段处理
预处理阶段:比如宏,条件编译,头文件包含
编译阶段:auto,模版

auto y = &x;
//右边可以是任何类型
auto* z = &x;
//右边必须是指针(地址),因为左边是指针类型

迭代器

迭代器分为正向迭代器反向迭代器

正向迭代器:iterator 正向走(数组向右走)
反向迭代器:reverse_ iterator 反向走(数组向左走)

反向迭代器
在这里插入图片描述
这里可以倒着打印数据

int main()
{
  	string s1 = ("hello world");

	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	// d l r o w   h e l l 0

	return 0;
}

++肯定封装进一个类中了,不然++不可能倒着走
树,链表倒着遍历必须用这个
下标+[ ]只能用于数组

四种迭代器:
1.普通迭代器(iterator begin() ):可读可写
2.const 迭代器(const_iterator begin() const; ):只能读不能写
const迭代器类似于const int* 只能改变指针的指向,不能改变指向的内容
3.反向迭代器(reverse_iterator rbegin(); )
4.const 反向迭代器(const_reverse_iterator() const; )

int* const 只能改变指向的内容,不能改变指向

capacity

1.size() -> 计算大小,具有通用性
2.length() -> 计算string的大小,具有局限性,不能计算树的大小
length 是string中的size,size比较好用,length是在STL之前就存在的,要向前兼容

string s2("hello world");
cout << s2.length() << endl;
//11
cout << s2.size() << endl;
//11

3.max_size:可以存储的最大的大小(size)
max_size基本不使用

string s2("hello world");
cout << s2.max_size() << endl;
整型的最大值,不同平台、不同容器也不同

4.capacity:空间大小
打印出的是有效字符的个数,不把\0的空间显示出来

string s2("hello world");
cout << s2.capacity() << endl;//15

VS中有数组int buff[16]的存在,第一次是两倍的扩容,后面是1.5倍扩容,但是整体认为扩容2倍

char _buff[16];
char* _arr;
int _size;
int _capacity;

第一次开不超过16字节的空间在buff上,不在堆上,超过buff的空间,会把buff的空间不要,在堆上重新开一块空间,把原数据拷贝过去,但是buff的空间还是存在的

5.reserve:保留,存储

void reserve (size_t n = 0);
会开好比n大的空间( >= n),开的是有效的字符的空间,不包含 \0,提前开好空间

s.reserve(100);
要开100,至少要101的空间
capacity不含\0,底层要比capacity多一个空间
reverse:提前开空间,避免扩容,提高效率

reverse不能改变size(大小)和内容
比如:
size(长度) 10 capacity(空间) 20
1.n < 10
2.10 < n < 20
3.n > 20 扩容
会不会缩容呢?
1 和 2 VS不缩容 : 空间换时间
1 和 2 g++(Linux)缩容 : 珍惜空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值