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$ 时,我们可以这样做:
请注意,数组的索引是从 $0$ 开始的,所以数组第一个元素的索引是 $0$,第二个元素的索引是 $1$,以此类推。
当然,你也可以不使用数组的 $0$ 号位,这可以取决于你的个人习惯。而且在不同的算法中,要不要从 $0$ 号位开始使用数组是需要想清楚的,不然可能会很麻烦。
如何从 $1$ 号位开始使用数组呢?其实很简单,只需要把初始化表达式的循环变量设置为 $1$ 即可。
我们还可以像这样 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
样例输出 #1
这个问题我们这么解决:
先做输入,先输入 $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$ 中。
代码如下: