C 班 第 6 课:数组——一个名字装一串数

适用对象: 完成了第 5 课(嵌套循环)的同学 使用方式: 自学讲义。放在电脑旁边,边读边照着做 学完本课,你应该能:

  1. 说清楚"数组"是什么,会声明数组、给数组里的盒子存数取数
  2. 用循环把一串数读进数组,再全部打印出来
  3. 求出一串数的总和,并找出其中最大的那个

遇到问题怎么办: 这节课最容易错的是下标从 0 开始数int a[5] 一共 5 个盒子,编号是 0、1、2、3、4,没有 a[5]。这一条今天要念叨很多遍。


1. 热身:把上节课的星星再打一遍(10 分钟)

打开上节课的 t1.cpp(4 行 6 列星星),重新运行一遍,确认还能打出 4 行、每行 6 个 *

嵌套循环还记得的话,今天的内容会很轻松。


2. 为什么需要数组(10 分钟)

假设要记录 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

而且更要命的是:s1s2……这些名字没法配合循环使用。循环变量 i 从 1 数到 5,可你没办法写出"第 i 个变量"这种东西。

数组就是来解决这件事的:一个名字,一串盒子,每个盒子有编号。


3. 数组:一排编号的盒子(20 分钟)

声明一个数组:

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 换成几,取的就是第几个盒子——这就是数组能配合循环的原因。

动手检查点 1(5 分钟)

新建 check1.cpp:声明 int b[3] = {7, 8, 9};,然后把 b[0]b[1]b[2] 三个数加起来输出。(答案应该是 24。)


4. 数组配合循环(20 分钟)

这才是数组真正好用的地方。把循环变量 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;
}

输入 510 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;
}

输入 510 20 30 40 50,输出:150

📝 求平均数要用到小数(150 除以 4 除不尽怎么办?),以后学。今天先只求总和。


5. 找最大值:打擂台(15 分钟)

一串数里最大的是哪个?办法叫打擂台

  1. 先让第一个数站上擂台,当"目前的冠军"
  2. 剩下的数一个一个上来挑战,谁比冠军大,谁就当新冠军
  3. 全部比完,站在台上的就是最大值
#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;
}

输入 535 82 47 90 16,输出:90

⚠️ 擂台的初始值必须是 a[0],不要写成 int maxv = 0; 如果这串数全是负数(比如 -5 -3 -9),从 0 开始打擂台的话谁也打不过 0,最后会错误地输出 0。

📝 找最小值一模一样,只要把变量名改成 minv、把 > 改成 <

动手检查点 2(5 分钟)

把上面的程序改成找最小值,用 35 82 47 90 16 测试,应该输出 16


6. 读错误:2 个典型坑(10 分钟)

错误 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 读进来的,两样都没有就是空的。


7. 本课练习(30 分钟起步)

⭐ 基础题 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] 把数读进来

以后学: 求平均数(要用小数)、把一串数从小到大排序、二维数组(表格)、字符串。


结束前的自我检查

  1. 不看讲义,说出 int a[5] 一共有几个盒子、编号分别是几
  2. 说清楚为什么数组循环写 i < n 而不是 i <= n
  3. 练习 1、2 都运行成功;⭐⭐⭐ 找最大值能做出来最好
  4. 把练习 3 里的 int maxv = a[0]; 改成 int maxv = 0;,再输入 3-5 -3 -9 跑一遍,亲眼看看错在哪
  5. 合上讲义,把"读入 n 个数"那两行一次性写对