跳转至

C++ 基础语法 - 4 数组

也许你会感到疑惑,怎么样才能方便地维护多个数据呢?目前我们已经掌握了变量,但如果我想维护 $100$ 个数,那用 $100$ 个变量是不是太麻烦了?

—— 于是我们就有了数组。

数组是一种用来存储相同类型数据元素的集合。如果变量是一个盒子,你可以把数组比喻成柜子。一个叫做 $arr$ 的柜子中有 $n$ 个格子,你可以很容易地去访问第 $1, 2, 3, ..., n$ 个格子,即 $arr_1, arr_2, arr_3, ..., arr_n$。我们称 $arr$ 的下标(如 $1, 2, 3, ..., n$)为数组的索引,我们可以通过索引访问或修改这一项的元素,是很方便的。

4.1 创建数组

数组和变量一样,是需要定义类型的。目前我们已经知道了 int 类型,那我们暂且也用 int 类型举例。创建数组的方式是 变量类型 数组名[数组大小];,如:int a[1000];

我们用 a[i] 表示数组中 $a_i$ 这项。对 $a_i$ 的修改和访问其实和变量是一样的,你可以对它赋值,比如 a[i] = 10;或者输出 $a_i$ 对应的数,如 std::cout << a[i] << std::endl;

在多数情况,我们都配合循环对数组的这一项进行修改和访问,如当我们要将长度为 $len$ 的数组 $a$ 的每一项都赋值为 $0$ 时,我们可以这样做:

for (int i = 0; i < len; i++) {
    a[i] = 0;
}

请注意,数组的索引是从 $0$ 开始的,所以数组第一个元素的索引是 $0$,第二个元素的索引是 $1$,以此类推。

当然,你也可以不使用数组的 $0$ 号位,这可以取决于你的个人习惯。而且在不同的算法中,要不要从 $0$ 号位开始使用数组是需要想清楚的,不然可能会很麻烦。

如何从 $1$ 号位开始使用数组呢?其实很简单,只需要把初始化表达式的循环变量设置为 $1$ 即可。

for (int i = 1; i <= len; i++) {
    a[i] = 0;
}

我们还可以像这样 a[i + 1] = 0;,为数组当前的索引的后面几个格进行修改或查询。这就不得不提到像这样 a[i++] = 0;a[++i] = 0; 的区别了:前者的意思是 a[i] = 0; i++;,是先在当前 $a_i$ 中赋值一个数,然后将 $i$ 自增;后者的意思是 i++; a[i] = 0;,是先自增 $i$,然后为 $a_i$ 赋值(注意此时 $i$ 已经自增过了)。

4.2 [NOIP2005 普及组] 陶陶摘苹果

简单学习过数组了,我们如何使用数组呢?让我们从一道基础的题目来练习。这道题来源于 NOIP 2005 普及组的第一题。

题目描述

陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 $10$ 个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 $30$ 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。

现在已知 $10$ 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹果的数目。假设她碰到苹果,苹果就会掉下来。

输入格式

输入包括两行数据。第一行包含 $10$ 个 $100$ 到 $200$ 之间(包括 $100$ 和 $200$)的整数(以厘米为单位)分别表示 $10$ 个苹果到地面的高度,两个相邻的整数之间用一个空格隔开。第二行只包括一个 $100$ 到 $120$ 之间(包含 $100$ 和 $120$)的整数(以厘米为单位),表示陶陶把手伸直的时候能够达到的最大高度。

输出格式

输出包括一行,这一行只包含一个整数,表示陶陶能够摘到的苹果的数目。

样例输入 #1

100 200 150 140 129 134 167 198 200 111
110

样例输出 #1

5

这个问题我们这么解决:

先做输入,先输入 $10$ 次,将第 $i$ 个值保存到 $a_i$ 中;然后输入陶陶把手伸直能达到的最大高度 $h$。题目中说过,陶陶有一个 $30$ 厘米高的小板凳,那么我们就把小板凳的高度也加在 $h$ 中,就是她能够到的最大高度,所以有 h += 30

我们再做一次循环,对于每一次计算,我们要判断 $a_i \le h$ 是否成立:如果成立,说明陶陶能够到苹果,反之不能。如果成立,那我们将陶陶能摘到的苹果数 $ans$ 加 $1$,所以有 ans++;

最后,输出 $ans$ 为最终的答案。

代码如下:

#include <iostream>

using namespace std;

int main() {
    int a[15];
    for (int i = 0; i < 10; i++) {
        cin >> a[i];
    }
    int h;
    cin >> h;
    h += 30; // 加上小板凳的高度 30 cm

    int ans = 0;
    for (int i = 0; i < 10; i++) {
        if (a[i] <= h) {
            ans++; // 如果可以够到,那 ans 增加 1
        }
    }

    cout << ans << endl;
    return 0;
}

请注意,在竞赛中,我们通常开数组要比数组预定的大小多几个格。这样可以防止数组越界的问题(即在计算时数组的下标超过了数组的大小)。

4.3 查找一个数是否存在

让我们再练习一道题。

题目描述

给你一个长度为 $n$ 的序列 $a$,并给出 $x$,要求你找到 $x$ 是否在 $a$ 中存在。如果存在就输出 $x$ 第一次出现在 $a$ 中的下标,如果不存在就输出 -1

输入格式

输入共三行:

第一行一个正整数 $n$,其中保证 $2 \le n \le 1000$;

第二行为一个长度为 $n$ 的序列 $a$,对于 $a$ 中的每个元素,保证 $a_i$ 是 int 范围内的整数;

第三行为一个整数 $x$,保证 $x$ 在 int 范围内。

输出格式

一行,如果 $x$ 在序列 $a$ 中,输出 $x$ 第一次出现在 $a$ 中所在的下标;否则输出 -1

我们处理完输入后,做一次循环。对于每次运算,如果 $x$ 与 $a_i$ 相等,那就输出 $i$,然后立马结束程序;如果这次循环做完完整的运算后,说明 $x$ 没有在 $a$ 中被找到(因为如果 $x$ 被找到了程序就结束了),那就在循环后面加一句 cout << "-1" << endl;,表示 $x$ 不在序列 $a$ 中。

代码如下:

#include <iostream>

using namespace std;

int main() {
    int n;
    cin >> n;
    int a[1005];
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    int x;
    cin >> x;

    for (int i = 0; i < n; i++) {
        if (a[i] == x) {
            cout << i << endl;
            return 0;
        }
    }
    cout << "-1" << endl;
    return 0;
}