数组的定义与使用
数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。
-
数组的定义: 类型说明符 数组名 【常量表达式 】【常量表达式】……;
数组名的构成方法与一般变量名相同。
-
数组元素的使用
数组必须先定义,后使用;
可以逐个引用数组元素。
//举例说明数组的定义和元素使用
int a[10]; //表示a为整型数组,有十个元素,为a[0]…a[9]
int a[5][3]; //表示a为二维整型数组,可以存放5行3列的整型数据表格,元素15个
a[0] = a[5]+a[7]-a[2*3];
b[1][2] = a[2][3]/2;
//例 循环语句
#include<iostream>
using namespace std;
int main(){
int a[10],b[10];
for(int i = 0;i < 10;i++){
a[i] = i*2-1;
b[10-i-1] = a[i];
}
for(int i = 0;i < 10;i++){
cout << "a[" << i << "] = " << a[i] << " ";
cout << "b[" << i << "] = " << b[i] << endl;
}
return 0;
}
数组的存储
1. 一维数组的存储
- 数组元素在内存中顺次存放,它们的地址是连续的。
- 元素间物理地址上的相邻,对应着逻辑次序上的相邻。
- 数组名字是数组首元素的内存地址。
- 数组名是一个常量,不能被赋值。
2. 一维数组的初始化
- 列出全部元素的初始值。例如,static int a【10】= {0,1,2,3,4,5,6,7,8,9};
- 可以只给一部分元素指定初值。例如,static int a【10】= {0,1,2,3,4};
- 列出全部元素初值时,可以不指定数组长度。例如,static int a【】= {0,1,2,3,4,5,6,7,8,9};
3. 二维数组的存储
- 按行存储。例如,float a【3】【4】; 存储顺序为00 01 02 03 10 11 12 13 20 21 22 23.
4. 二维数组的初始化
-
将所有初值写在一个{}内,按顺序初始化。
例如,static int a【3】【4】= {0,1,2,3,4,5,6,7,8,9,10,11};
-
分行列出二维数组元素的初值。
例如,static int a【3】【4】= {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
-
可以只对部分元素初始化。
例如,static int a【3】【4】= {{0}, {4,5}, {8,9,1}};
-
列出全部初值时,第一维下标个数可以省略。
例如,static int a【】【4】= {0,1,2,3,4,5,6,7,8,9,10,11};
或static int a【】【4】= {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
-
如果不作任何初始化,局部作用域的非静态数组中会存在垃圾数据,static数组中的数据默认初始化为0。
-
如果只对部分元素初始化,剩下的未显式初始化的元素,将自动被初始化为0.
//例1 求斐波那契数列的前20个数。
#include<iostream>
using namespace std;
int main(){
int f[20] = {1,1}; //初始化第0、1个数
for(int i=0;i<20;i++) //求第2—19个数
f[i]=f[i-1]+f[i-2];
for(int i=0;i<20;i++){
if(i%5==0) cout<<endl; //输出,每行5个数
cout.width = 12; //设置输出宽度为12
cout << f[i];
}
return 0;
}
//例2 循环从键盘读入若干组选择题答案,计算并输出每组答案的正确率,直到输入ctrl+z为止。
//每组连续输入5个答案,每个答案可以是abcd。
#include<iostream>
using namespace std;
int main(){
const char key[] = {'a','c','b','a','d'};
const int NUM_QUES = 5;
char c;
int ques = 0,numCorrect = 0;
cout << "Enter the " << NUM_QUES <<"question tests:" << endl;
while(cin.get(c)){
if(c!='\n'){
if(c==key[ques]){
numCorrect++;
cout<<' ';
}
else
cout<<"*";
ques++;
}
else{
cout<<"Score "<<static_cast<float>(numCorrect)/NUM_QUES*100<<"%";
ques = 0;
numCorrect = 0;
cout << endl;
}
}
return 0;
}
运行结果:
Enter the 5 question tests:
acbba
** Score 60%
acbad
Score 100%
5. 数组作为函数参数
数组元素做实参,与单个变量一样;
数组名做参数,形参实参都应当是数组名,类型要一样,传送的是数组首地址。对形参数组的改变会直接影响到实参数组。
//例 使用数组名作为函数参数
//主函数中初始化一个二维数组,表示一个矩阵,并将每个元素都输出。然后调用子函数,分别计算每一行的元素之和,将和直接存放到每行的第一个元素中,返回主函数之后输出各行元素的和。
#include<iostream>
using namespace std;
void rowSum(int a[][4],int nRow){ //计算二维数组a每行元素的值的和
for(int i=0;i<nRow;i++){
for(int j=1;j<4;j++)
a[i][0]+=a[i][j];
}
}
int main(){
int table[3][4] = {{1,2,3,4},{2,3,4,5},{3,4,5,6}};
for(int i=0;i<3;i++){ //输出数组元素
for(int j=0;j<4;j++)
cout << table[i][j] <<" ";
cout<<endl;
}
rowSum(table,3); //调用子函数,计算各行的和
for(int i=0;i<3;i++)
cout << "Sum of row " << i << " is" << table[i][0] << endl;
return 0;
}
运行结果:
1 2 3 4
2 3 4 5
3 4 5 6
Sum of row 0 is 10
Sum of row 1 is 14
Sum of row 2 is 18
6. 对象数组
对象数组的定义和访问
- 定义对象数组: 类名 数组名【元素个数】;
- 访问对象数组元素: 通过下标访问:数组名【下标】.成员名
对象数组初始化
- 数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。
- 通过初始化列表赋值。例 Point a[2] = {Point(1,2),Point(3,4)};
- 如果没有为数组元素指定显式初值,数组元素使使用默认值初始化(调用默认构造函数)。
数组元素的构造和析构
- 构造数组时,元素所属的类未声明构造函数,则采用默认构造函数。
- 各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。
- 各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。
- 当数组中每一个对象被删除时,系统都要调用一次析构函数。
//例 对象数组应用举例
//Point.h
#ifndef_POINT_H
#define_POINT_H
class Point{
public:
Point();
Point(int x,int y);
~Point();
void move(int newX,int newY);
int getX() const{return x;}
int getY() const{return y;}
static void showCount(); //静态函数成员
private:
int x,y;
};
#endif//_POINT_H
//Point.cpp
#include<iostream>
#include"Point.h"
using namespace std;
Point::Point():x(0),y(0){
cout << "Default Constructor called." << endl;
}
Point::Point(int x.int y):x(x),y(y){
cout << "Constructor called." << endl;
}
Point::~Point(){
cout << "Destructor called." << endl;
}
void Point::move(int newX,int newY){
cout << "Moving the point to (" << newX << "," << newY << ")" << endl;
x = newX;
y = newY;
}
//6_3.cpp
#include<iostream>
#include"Point.h"
using namespace std;
int main(){
cout << "Entering main…" << endl;
Point a[2];
for(int i=0;i<2;i++)
a[i].move(i+10,i+20);
cout << "Exiting main…" << endl;
return 0;
}
运行结果:
Entering main…
Default Constructor called.
Default Constructor called.
Moving the point to (10,20)
Moving the point to (11,21)
Entering main…
Destructor called.
Destructor called.
//基于范围的for循环举例
int main(){
int array[3] = {1,2,3};
int *p;
for(p=array;p<array+sizeof(array)/sizeof(int);++p){
*p += 2;
std::cout << *p << std::endl;
}
return 0;
}
int main(){
int array[3] = {1,2,3};
for(int &e:array){
e += 2;
std::cout << e << std::endl;
}
return 0;
}