<C++ Primer >学习笔记 第三章 字符串向量和数组 (下)

下半部分主要介绍迭代器和数组部分。
迭代器
迭代器类似于指针,可以间接访问对象。
迭代器的使用
迭代器拥有begin和end成员,begin是负责指向第一个元素的迭代器,end是指向一个容器根本不存在的“尾后”,begin和end成员返回的迭代器是同一个迭代器称为尾后迭代器。
标准容器迭代器的运算符

*iter              返回迭代器iter所指向元素的引用
iter->men          解引用iter并获取该元素名为men的成员,等价于(*iter).men,注意圆括号不能少。
++iter             令iter指向容器的下一个元素
--iter             令iter指向容器的上一个元素
iter1==iter2       判断两个迭代器是否相等
iter1!=iter2

在C++11中引入两个新的函数分别是cbegin和cend,这两个函数和原本的begin和end的区别是,无论对象(vector或string或其他)本身是否是常量,返回来的值都是常量类型。

迭代器的运算

iter+n      迭代器加上一个整数值仍是一个迭代器,迭代器的新位置与原来相比向前移动若干个元素。结果迭代器或者指示容器内的一个元素,或者指示容器尾元素的下一个位置
iter-n      和上面含义类似
iter+=n     将iter加n的结果返回给iter
iter-=n     和上面的含义类似
iter1-iter2 两个迭代器直接的距离

3.21 输入一组整数,使用迭代器输出vector容器的内容

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{

	vector<string> v7{10,"hi"};
	for(auto a=v7.cbegin();a!=v7.cend()&&!a->empty();a++)
	   cout<<*a<<" ";    //*解引用 

}

3.23 输入一组数字,输出数字的两倍

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	vector<int> v;
	int temp;
	cout<<"please input ten characters:"<<endl;
	for(int i=0;i<10;i++)
	  {
	    while(cin>>temp)
		v.push_back(temp);
		
     } 
	for(auto it=v.begin();it != v.end();it++)
	cout<<*it*2<<" ";
	
 } 

3.24 读入一组整数,使第一个数组加最后一个数字,第二个数字加上倒数第二个数字以此类推,最后输出结果

// 迭代器没有加法,只有减法,减法是距离含义 
#include<iostream>
#include<vector>
using namespace std;
int main()
{
	vector<int> vInt;
	cout<<"Please input charaters"<<endl;
	int i;
	while(cin>>i)
	vInt.push_back(i);
	if(vInt.begin()==vInt.end())
	 {
	 	cout<<"empty"<<endl;
	 	return -1;
	 }
	 auto beg=vInt.begin();
	 auto end=vInt.end();
	 for(auto it=beg;it!=beg+(end-beg)/2;it++)
	 cout<<*it+*(beg+(end-it)-1)<<" ";
	 
	 if(vInt.size()/2!=0)    //如果是奇数 单独处理中间的数字 
	 cout<<*(beg+(end-beg)/2);//先计算出从头到尾的元素个数,然后控制迭代器从开始向右移动1/2个元素定位到中间 
}

在这道题中我们使用了一个算法,二分搜索。里面有个小细节二分搜索使用的mid=(beg+end)/2,但是程序里却是mid=beg+(end-beg)/2。为什么要这么写呢?
是因为C++没有两个迭代器的加法运算,实际上把两个迭代器相加也是没有意义的。但是迭代器有减法运算,相减的结果是他们的距离所以mid=(beg+end)/2是不合法的,mid=beg+(end-beg)/2的含义是先计算end和beg直接的距离,也就是容器元素个数的值,然后从迭代器开始时向右移动距离的二分之一,到中间位置。

什么是二分算法

数组
数组也是存放类型相同对象的容器,这些对象本身没有名字,需要通过其所在位置访问。与vector不同的地方是,数组的大小确定不变,不能随意向数组中增加元素。
数组的声明

a[b]

其中a是数组的名字,b是数组的维度,维度说明了数组中元素的个数,因此必须大于0。
数组如何初始化
注:不存在引用的数组,但是存在数组的引用。

int &refs[10]=/*?*/        错误 这是引用的数组
int (&refs)[10]=arr;       正确 数组的引用,引用一个含有10个整数的数组

3.31 创建一个数组,令其每个元素的值就是其下标的值

#include<iostream>
using namespace std;
int main()
{
	int a[10];
	for(int i=0;i<10;i++)
	   a[i]=i;
	for(int j=0;j<10;j++)
	cout<<a[j]<<" ";
	cout<<endl;
 } 

3.32 将上题中的数组拷贝给另一个数组

#include<iostream>
using namespace std;
int main()
{
	int a[10],b[10];
	for(int i=0;i<10;i++)
	{
		a[i]=i;
		b[i]=a[i];
	   }   
	
	for(int j=0;j<10;j++)
	cout<<b[j]<<" ";
	cout<<endl;
 } 

用vector实现

#include<iostream>
#include<vector>

using namespace std;
int main()
{
	vector<int> a,b;
	for(int i=0;i<10;i++)
	{
		a.push_back(i);
	}
	for(int i=0;i<10;i++)
	{
		b.push_back(a[i]);
	}
	for(auto &i:b)
	cout<<i<<" ";
	cout << endl;
	return 0;
}

指针和数组
在使用数组时,编译器会把它转化成指针。对数组使用取地址符可以获得指向该元素的指针:

string *p=&num[0];
使用数组名的地方,编译器会自动将其替换为一个指向数组首地址的指针
string *p2=num;//等价p2=&nums[0]
auto ia2(num); //ia2是一个string型指针,指向num的第一个元素

指针也是迭代器。为了让指针使用起来更安全C++11引入两个名为begin和end的函数

int a[]={1,2,3,4};
int *beg=begin(a); //指向首地址
int *last=end(a);  //指向尾元素的下一个地址
主要尾指针不参与解引用和递增操作

指针的运算和迭代器完全一致,具体使用方法可以参考上面迭代器。
解引用与指针
指针加上一个整数所得的结果还是一个指针。假设结果指针指向一个元素,则允许解引用该结果指针:

int a[]={1,2,3,4};
int last=*(a+2);

表达式*(a+2)计算a向前2个元素后的新地址,解引用是取里面的内容,相当于a[2];
下标和指针
指针指向的是数组中的元素都可以执行下标运算:

int *p=&a[2];    //p指向索引为2的元素
int j=p[1];      //p[1]等价于*(p+1),就是a[3]表示的那个元素
int k=p[-2];     //p[-2]表示a[0]表示的那个元素

3.35 编写一段程序用指针将数组里的值全部置零

#include<iostream>
using namespace std;
int main()
{
	const int sz=100;
	int a[sz],*p;
	cout<<"The original number is"<<endl; 
	for(int i=0;i<sz;i++)
	{ 
	a[i]=rand()%100;
	cout<<a[i]<<" ";
		}
	p=begin(a);
	while(p !=end(a))
	{
		*p=0;
		p++;
	 } 
	 cout<<endl<<"The revised content is" <<endl;
	 for(auto &i:a)
	 {
	 	cout<<i<<" ";
	 }
	return 0;  
}

C风格字符串
不建议使用


版权声明:本文为qq_39446868原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。