iterator知识点:
end()函数返回容器对象的尾部元素的下一个位置。没什么实际意义,表示我们对所有元素处理完了。
const_iterator类似常量指针,表示指向的内容不能变,只能读,而const iterator表示指针常量,指向的地址不能变。
C++11标准中,添加了两个迭代器的新函数 cbegin()&cend(), 为了便于专门得到const_iterator类型返回值。
习题:
3.24之前就采用的迭代器做的,所以在这里不做了。
3.26
答:为什么采用 mid=beg+(end-beg)/2,而不用mid=(beg+end)/2?
首先第一种写法与第二种数学上得到的结果是完全一样的,这个可以通过取整函数的方法证明。但是beg+end操作很可能会出现溢出 的风险,但是后一种写法不会出现比end要大的中间数据,所以比较安全。
2你要是看c++stl源码就会发现用的也是第二种,因为考虑 了 通用性,用第一种如果beg和end是指针或者迭代器的话是无法编译通过的,因为指针和迭代器运算不支持相加运算,却支持相减运算, 第二种相 当于相加了他们之间的距离,所以第二种通用性强。(迭代器的话要求是随机访问迭代器random access iterator)。
程序题:
#include
<iostream>
#include
<string>
#include
<vector>
using
namespace
std;
//减输出的单词变为大写采用迭代器
void
fun3_22()
{
vector <string> vec;
string word;
cout<<
"请输入单词:"
<<endl;
while
(cin>>word)
{
vec.push_back(word);
}
for
(
auto
it=vec.begin(); it!=vec.end(); ++it)
{
for
(
auto
ib=(*it).begin(); ib!=(*it).end(); ++ib)
*ib = toupper(*ib);
cout<<*it;
}
}
//输出vector数组元素的2倍
void
fun3_23()
{
vector<
int
> vec;
int
temp;
cout<<
"请输入数字:"
<<endl;
while
(cin>>temp)
{
vec.push_back(temp);
}
for
(
auto
it=vec.begin(); it!=vec.end(); ++it)
{
cout<<2*(*it);
}
}
//用迭代器实现成绩分段统计
void
fun3_25()
{
vector<
int
> vec;
vector<
int
> num(10,0);
//vs2010不支持列表初始化
int
grad;
cout<<
"请输入成绩:"
<<endl;
while
(cin>>grad)
{
vec.push_back(grad);
}
//实现分段统计
for
(
auto
it=vec.begin(); it!=vec.end(); ++it)
{
//++num[(*it)/10];
++*(num.begin()+(*it)/10);
}
for
(
auto
it=num.begin(); it!=num.end(); ++it)
cout<<*it<<endl;
}
int
main()
{
//fun3_22();
//fun3_23();
fun3_25();
return
0;
}
关于数组的知识点:
1.定义数组的时候必须指定数组的类型,不允许用auto关键字由初始值的列表推断类型。另外和vector一样,数组的元素应为对象,
因此不存在引用的数组。
2.字符串数组可以采用字符串字面值的初始化形式。当使用这种方式是一定要注意字符串字面值的结尾处还有一个空字符,该字符也会被拷贝到字符数组中去。
char
a1[] = {
'a'
,
'b'
,
'c'
};
//没有空字符
char
a2[] = {
'a'
,
'b'
,
'c'
,
'\0'
};
//初始化显示添加空字符
char
a3[] =
"abc"
;
//自动隐式添加空字符
char
a4[4] =
"abcd"
;
//没有空间存放
3.数组的内容不能拷贝,也无法使用一个数组直接初始化另一个数组(a1=a); 一些非标准的编译器拓展功能支持此种拷贝,初始化,但是这种非标准不要使用。
4.理解数组复杂声明的方法:从数组的名字开始,按照由内到外顺序阅读。
5.size_t是一种机器相关的无符号类型。它被设计的足够大,可以表示任意对象的数量。
6.数组的维度必须要是常量的,而且必须是编译时确定的,不是分配是确定的。如下:
int
len;
cout<<
"请输入数组的长度:"
<<endl;
cin>>len;
const
int
i = len;
int
a[i];
//错误,运行时 确定
const
int
j = 5;
int
b[j];
//正确
7.auto根据值来推断类型,decltype根据变量类型来推断类型。
8.与string,vector类型不一样的是,内置类型如数组的下标不是无符号类型,即也可以为负数。
9.用关键字using作为别名声明的开始,其后紧跟别名和等号,其作用是把等号左侧的名字规定 成等号右侧类型的别名,如 :
using
int_array =
int
[
4
];int_array替代匿名int[4]数组。
10.size_t是cstddef头文件中定义的一种与机器实现有关的无符号整数类型,它的空间足够大,能表示任意数组大小,
size_t和size_type是什么类型取决于编译器。都用size_t一般来说也没什么问题,因为在通常的实现里这俩是同一个类型。STL使用的是size_type(迭代器),其迭起器内部由size_t实现。
习题:
3.27 答:a错误非常量,b正确,c错误,因为c的维度是函数返回值,有可能是负数。d错误,空间不够。
3.29 答:数组不能动态变化,数组之间不能赋值。
3.30 答:下标越界。
3.33 答:不初始化,既没有分配内存,范围for循环无法执行。
3.34 答:P2-P1越界时,非法。
3.37 答:输出hallo,但此时*p继续有效,后面的为乱码。
3.38 答:没有意义相加,编译器不允许。
程序题:
#include
<iostream>
#include
<string>
#include
<vector>
#include
<cstring>
using
namespace
std;
//编写数组,数组的值就是下标的值
void
fun3_31()
{
int
arr[10];
for
(
int
i=0; i<10; ++i)
{
arr[i] = i;
cout<<arr[i]<<
" "
;
}
}
//实现数组拷贝
void
fun3_32()
{
int
arr[10];
for
(
int
i=0; i<10; ++i)
{
arr[i] = i;
}
int
brr[10];
for
(
int
i=0; i<10; ++i)
{
brr[i] = arr[i];
cout<<brr[i]<<endl;
}
}
//vector拷贝
void
fun3_32(string cs)
{
cout<<cs<<endl;
int
num;
vector<
int
> vec,vec2;
cout<<
"请输入数字:"
<<endl;
while
(cin>>num)
{
vec.push_back(num);
}
vec2 = vec;
for
(
auto
it=vec2.begin(); it!=vec2.end(); ++it)
{
cout<<*it;
}
}
//利用指针将数组元素置0
void
fun3_35()
{
int
a[10];
int
*p = a;
*p = 0;
for
(
int
i=0; i<10; ++i)
{
a[i] = *p;
cout<<a[i];
}
}
//判断连个数组是否相等
void
fun3_36()
{
int
pc = 0;
int
arr[5] = {1,2,3,4,5};
int
arr1[5] = {2,4,6,8,9};
int
arr2[5] = {1,2,3,4,5};
if
(
sizeof
(arr)==
sizeof
(arr2))
{
for
(
int
i=0; i<5; ++i)
{
if
(arr[i]==arr2[i])
++pc;
}
if
(pc==5)
cout<<
"相等"
<<endl;
else
cout<<
"不等"
<<endl;
}
vector<
int
> vec,vec1;
//vector<int> vec1 = {0, 1, 2}; vs2010不支持新标准
for
(
int
i =0; i<3; ++i)
{
vec.push_back(i);
vec.push_back(++i);
}
if
(vec==vec1)
cout<<
"vector "
<<
"相等"
;
else
cout<<
"vector "
<<
"不相等"
;
}
//比较string类型与比较 char[]类型
void
fun3_39()
{
string str =
"Linux"
;
string str1 =
"Windows"
;
if
(str == str1)
cout<<
"相等"
<<endl;
else
if
(str > str1)
cout<<
"windows大"
<<endl;
else
cout<<
"Linux大"
<<endl;
char
arr[] =
"jdja"
;
char
arr1[] =
"brbn"
;
int
result = strcmp(arr,arr1);
if
(result == 0)
cout<<
"一样大"
;
else
if
(result == 1)
cout<<
"前者大"
;
else
cout<<
"后者大"
;
}
//C字符串之间的拼接
void
fun3_40()
{
char
ar[] =
"Love has no"
;
char
br[] =
"boundaries"
;
//const int st = strlen(ar)+strlen(" ")+strlen(br)+1; //又是不支持,等过段时间换编译器
char
cr[30];
strcpy(cr,ar);
strcat(cr,
" "
);
strcat(cr,br);
cout<<cr;
}
//用整形数组初始vector对象
void
fun3_41()
{
int
arr[8] = {1,2,3,4,5,6,7};
vector <
int
> vec(arr,arr+7);
for
(
auto
it=vec.begin(); it!=vec.end(); ++it)
cout<<*it;
}
//用vector 初始化数组
void
fun3_42()
{
vector <
int
> vec(10,1);
int
arr[10];
for
(
int
i=0; i<10; ++i)
{
arr[i] = vec.at(i);
cout<<arr[i];
}
}
void
fun3_43()
{
int
ia[3][4] = {1,3,5,7,9,2,4,6,8,10,11,12};
/*
for (const int(&p)[4] : ia)
for (int q : p) cout << q << " ";
cout << endl;
*/
for
(
int
i=0; i<3; ++i)
for
(
int
j=0; j<4; ++j)
cout<<ia[i][j]<<endl;
//这个比较麻烦
/*for(int (*p)[4]=ia; p!=ia+3; ++p)
for(int *q=*p; q!=*p+4; ++q)
cout<<*q<<endl;
*/
for
(
auto
p=ia; p<ia+3; ++p)
for
(
auto
q=*p; q<*p+4; ++q)
cout<<*q<<endl;
}
int
main()
{
//fun3_31();
//fun3_32();
//fun3_32("vector实现");
//fun3_35();
//fun3_36();
//fun3_39();
//fun3_40();
//fun3_41();
//fun3_42();
fun3_43();
return
0;
}