C++基础(7) —— 数组的定义、使用、存储、数组作为函数参数、对象数组

数组的定义与使用

数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。

  • 数组的定义: 类型说明符 数组名 【常量表达式 】【常量表达式】……;

    数组名的构成方法与一般变量名相同。

  • 数组元素的使用

    数组必须先定义,后使用;

    可以逐个引用数组元素。

//举例说明数组的定义和元素使用
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 = 5char 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 (1020)
Moving the point to (1121)
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;
                     }
发布了76 篇原创文章 · 获赞 30 · 访问量 5855

猜你喜欢

转载自blog.csdn.net/weixin_45926367/article/details/104384024