适用对象: 完成了第 5 课(嵌套循环)的同学 使用方式: 自学讲义。放在电脑旁边,边读边照着做 学完本课,你应该能:
遇到问题怎么办: 这节课最容易错的是下标从 0
开始数。int a[5] 一共 5 个盒子,编号是
0、1、2、3、4,没有 a[5]。这一条今天要念叨很多遍。
打开上节课的 t1.cpp(4 行 6
列星星),重新运行一遍,确认还能打出 4 行、每行 6 个
*。
嵌套循环还记得的话,今天的内容会很轻松。
假设要记录 5 个同学的成绩,用上节课学的办法只能这么写:
#include <bits/stdc++.h>
using namespace std;
int main() {
int s1 = 90, s2 = 85, s3 = 78, s4 = 92, s5 = 66;
cout << s1 << " " << s2 << " " << s3 << " " << s4 << " " << s5 << endl;
return 0;
}输出:90 85 78 92 66
能用,但很笨。要是有 100 个同学呢? 难道写
s1 一直写到 s100,输出的时候再写 100 遍
cout?
而且更要命的是:s1、s2……这些名字没法配合循环使用。循环变量
i 从 1 数到 5,可你没办法写出"第 i 个变量"这种东西。
数组就是来解决这件事的:一个名字,一串盒子,每个盒子有编号。
声明一个数组:
int a[5];这一行的意思是:造 5 个装整数的盒子,整排叫
a。它们长这样——
a[0] a[1] a[2] a[3] a[4]
+------+------+------+------+------+
| | | | | |
+------+------+------+------+------+
⚠️ 编号(叫"下标")从 0 开始,不是从 1 开始。
int a[5] 的 5 个盒子是
a[0]、a[1]、a[2]、a[3]、a[4]。a[5]
不存在,这是本课第一大坑。
存数和取数,就把 a[0]
整个当成一个普通变量用:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[5];
a[0] = 90;
a[1] = 85;
a[2] = 78;
cout << a[0] << endl;
cout << a[0] + a[1] << endl;
return 0;
}输出:
90
175
如果一开始就知道要装什么,可以直接写在大括号里:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[5] = {10, 20, 30, 40, 50};
cout << a[0] << " " << a[2] << " " << a[4] << endl;
return 0;
}输出:10 30 50
📝 数组的威力在于:下标可以是一个变量。
a[i] 里的 i
换成几,取的就是第几个盒子——这就是数组能配合循环的原因。
新建 check1.cpp:声明
int b[3] = {7, 8, 9};,然后把
b[0]、b[1]、b[2]
三个数加起来输出。(答案应该是 24。)
这才是数组真正好用的地方。把循环变量 i
直接当下标用。
读入 n 个数,再原样输出:
#include <bits/stdc++.h>
using namespace std;
int a[105]; // 盒子先多造一些,够用就行
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i]; // 一个一个读进盒子
for (int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}输入 5 回车,再输入
10 20 30 40 50,输出:10 20 30 40 50
⚠️ 注意循环写的是 i < n 不是
i <= n。 因为下标从 0 开始数,n 个数占的是 0 到
n-1 号盒子。"从 0 开始数 n 个"配的就是
i < n,记死这个搭配。
📝 数组要写在 main
外面(上面那样),并且开大一点。 int a[105];
表示最多能装 105 个数,题目说最多 100
个就够用了。写在外面还有个好处:里面自动全是 0。
倒着输出——只要让 i 倒着数:
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = n - 1; i >= 0; i--) cout << a[i] << " "; // 从最后一个数回来
cout << endl;
return 0;
}输入 5 和
10 20 30 40 50,输出:50 40 30 20 10
📝 最后一个盒子是 a[n-1],不是
a[n]。 又是那条规矩。
求总和——把第 4 课学的累加搬过来就行:
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int sum = 0; // 计数器清零
for (int i = 0; i < n; i++) sum = sum + a[i]; // 一个一个加进去
cout << sum << endl;
return 0;
}输入 5 和
10 20 30 40 50,输出:150
📝 求平均数要用到小数(150 除以 4 除不尽怎么办?),以后学。今天先只求总和。
一串数里最大的是哪个?办法叫打擂台:
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int maxv = a[0]; // 第一个数先上擂台
for (int i = 1; i < n; i++) { // 从第二个开始挑战(i 从 1 起)
if (a[i] > maxv) maxv = a[i]; // 挑战成功,换冠军
}
cout << maxv << endl;
return 0;
}输入 5 和
35 82 47 90 16,输出:90
⚠️ 擂台的初始值必须是 a[0],不要写成
int maxv = 0;。 如果这串数全是负数(比如
-5 -3 -9),从 0 开始打擂台的话谁也打不过
0,最后会错误地输出 0。
📝 找最小值一模一样,只要把变量名改成
minv、把 > 改成 <。
把上面的程序改成找最小值,用
35 82 47 90 16 测试,应该输出 16。
错误 1:下标越界(本课头号错误)
int a[5];
for (int i = 0; i <= 5; i++) { ← 写成了 i <= 5
cin >> a[i];
}
int a[5] 只有 a[0] 到 a[4] 这
5 个盒子,i 走到 5 的时候,a[5]
是一个根本不存在的盒子。
最坑的是:编译器不报错,程序也常常能跑完,只是往别人的地盘上乱写数据,结果要么算出莫名其妙的答案,要么过一会儿突然崩溃。
📝 口诀:int a[n] 配
for (int i = 0; i < n; i++)。
看见数组循环里出现 <=,先停下来想三秒。
错误 2:还没读入就拿来用
int a[105];
int sum = 0;
for (int i = 0; i < n; i++) sum = sum + a[i]; ← 忘了先 cin >> a[i]
cout << sum << endl;
盒子是空的(写在 main 外面的话全是 0),加出来的和就是
0;要是数组写在 main
里面,里面装的是上一个程序留下的垃圾数字,会输出一堆看不懂的数。
📝 数组用之前,先问自己一句:"里面的数是哪来的?"
要么是 = {…} 写死的,要么是 cin
读进来的,两样都没有就是空的。
⭐ 基础题 1:把一串数打印出来(文件名
t1.cpp)
用大括号写死 5 个数
5 10 15 20 25,然后用循环把它们全部输出在一行,中间用空格隔开。
输出样例:
5 10 15 20 25
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[5] = {5, 10, 15, 20, 25};
for (int i = 0; i < 5; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}注意 i < 5 不是 i <= 5。要是写成
<=,最后会多打一个不存在的 a[5]。
⭐⭐ 实战题 2:求一串数的总和(文件名
t2.cpp)
先输入一个整数 n,再输入 n 个整数,输出它们的总和。
输入样例:
5
3 1 4 1 5
输出样例:
14
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int sum = 0;
for (int i = 0; i < n; i++) sum = sum + a[i];
cout << sum << endl;
return 0;
}其实这题不用数组也能做(边读边加就行)。但先存进数组,后面想再拿这些数干别的事就方便了——练习 3 就必须先存起来。
⭐⭐⭐ 冲刺题 3:找最大值和它的位置(文件名
t3.cpp)
先输入一个整数 n,再输入 n 个整数,输出最大值是多少,以及它是第几个数(从 1 开始数,也就是第 1 个、第 2 个……)。题目保证最大值只有一个。
输入样例:
5
35 82 47 90 16
输出样例:
最大值是 90
它是第 4 个
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
int maxv = a[0];
int pos = 0; // 记住冠军住在几号盒子
for (int i = 1; i < n; i++) {
if (a[i] > maxv) {
maxv = a[i];
pos = i; // 换冠军的时候,位置也要跟着换
}
}
cout << "最大值是 " << maxv << endl;
cout << "它是第 " << pos + 1 << " 个" << endl;
return 0;
}⚠️ 这题的坑在最后一行:pos 是下标(从 0
数),题目要的是第几个(从 1 数),所以要
pos + 1。90 住在 a[3],但它是第 4 个数。
| 写法 | 意思 |
|---|---|
int a[5]; |
造 5 个装整数的盒子,下标 0~4 |
int a[5] = {10, 20, 30, 40, 50}; |
造 5 个盒子并直接装好数 |
a[2] = 99; |
往 2 号盒子里存 99 |
cout << a[2]; |
把 2 号盒子里的数拿出来 |
a[i] |
i 号盒子——下标可以是变量,这是数组的核心 |
三个必背套路:
读入 n 个数: for (int i = 0; i < n; i++) cin >> a[i];
求总和: sum = 0; 然后 for(...) sum = sum + a[i];
打擂台找最大: maxv = a[0]; 然后 for(i=1;...) if (a[i] > maxv) maxv = a[i];
易错点:
| 症状 | 原因 |
|---|---|
| 答案莫名其妙 / 程序突然崩溃 | 下标越界,循环写成了 i <= n |
| 全是负数时最大值输出 0 | 擂台初始值写成了 0,应该是 a[0] |
| 输出的位置比正确答案小 1 | 下标从 0 数,"第几个"从 1 数,忘了 +1 |
| 和永远是 0 | 忘了先 cin >> a[i] 把数读进来 |
以后学: 求平均数(要用小数)、把一串数从小到大排序、二维数组(表格)、字符串。
int a[5]
一共有几个盒子、编号分别是几i < n 而不是
i <= nint maxv = a[0]; 改成
int maxv = 0;,再输入 3 和
-5 -3 -9 跑一遍,亲眼看看错在哪