少儿编程C++快速教程之——3. 数组和矩阵操作
1. 数组:计算机的"数据盒子"
1.1 什么是数组?
数组就像是一排整齐的盒子,每个盒子可以存储一个数据,所有盒子的数据类型都相同。每个盒子都有一个编号(索引),我们可以通过编号来访问特定的盒子。
1.2 一维数组:一排整齐的盒子
声明和初始化一维数组
#include <iostream>
using namespace std;int main() {// 声明一个可以存储5个整数的数组int numbers[5];// 初始化数组的每个元素numbers[0] = 10;numbers[1] = 20;numbers[2] = 30;numbers[3] = 40;numbers[4] = 50;// 声明并初始化数组int scores[] = {95, 87, 92, 78, 85}; // 编译器会自动计算数组大小// 声明时指定大小并初始化int ages[3] = {15, 16, 17};return 0;
}
访问和遍历一维数组
#include <iostream>
using namespace std;int main() {int numbers[] = {10, 20, 30, 40, 50};// 访问单个元素cout << "第一个元素: " << numbers[0] << endl;cout << "第三个元素: " << numbers[2] << endl;// 修改元素numbers[1] = 25;cout << "修改后的第二个元素: " << numbers[1] << endl;// 计算数组长度int length = sizeof(numbers) / sizeof(numbers[0]);cout << "数组长度: " << length << endl;// 遍历数组 - 使用for循环cout << "数组元素: ";for (int i = 0; i < length; i++) {cout << numbers[i] << " ";}cout << endl;// 遍历数组 - 使用范围for循环 (C++11)cout << "数组元素: ";for (int num : numbers) {cout << num << " ";}cout << endl;return 0;
}
一维数组的应用:计算平均值
#include <iostream>
using namespace std;int main() {int scores[] = {95, 87, 92, 78, 85};int length = sizeof(scores) / sizeof(scores[0]);int sum = 0;for (int i = 0; i < length; i++) {sum += scores[i];}double average = static_cast<double>(sum) / length;cout << "平均分: " << average << endl;return 0;
}
小练习: 编写一个程序,让用户输入5个数字,然后找出其中的最大值和最小值。
2. 二维数组:数据的表格
2.1 什么是二维数组?
二维数组就像是一个表格,有行和列。它可以用来表示棋盘、成绩表、图像像素等。
声明和初始化二维数组
#include <iostream>
using namespace std;int main() {// 声明一个3x3的二维数组(3行3列)int matrix[3][3];// 初始化二维数组matrix[0][0] = 1; matrix[0][1] = 2; matrix[0][2] = 3;matrix[1][0] = 4; matrix[1][1] = 5; matrix[1][2] = 6;matrix[2][0] = 7; matrix[2][1] = 8; matrix[2][2] = 9;// 声明并初始化二维数组int chessboard[8][8] = {{1, 0, 1, 0, 1, 0, 1, 0},{0, 1, 0, 1, 0, 1, 0, 1},{1, 0, 1, 0, 1, 0, 1, 0},{0, 1, 0, 1, 0, 1, 0, 1},{1, 0, 1, 0, 1, 0, 1, 0},{0, 1, 0, 1, 0, 1, 0, 1},{1, 0, 1, 0, 1, 0, 1, 0},{0, 1, 0, 1, 0, 1, 0, 1}};return 0;
}
访问和遍历二维数组
#include <iostream>
using namespace std;int main() {int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};// 访问单个元素cout << "第一行第二列: " << matrix[0][1] << endl;cout << "第二行第三列: " << matrix[1][2] << endl;// 修改元素matrix[2][0] = 70;cout << "修改后的第三行第一列: " << matrix[2][0] << endl;// 遍历二维数组 - 使用嵌套循环cout << "二维数组内容:" << endl;for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {cout << matrix[i][j] << " ";}cout << endl;}return 0;
}
二维数组的应用:成绩表
#include <iostream>
using namespace std;int main() {// 3个学生,4门科目int grades[3][4] = {{85, 92, 78, 90},{76, 88, 95, 82},{90, 85, 88, 92}};string students[] = {"小明", "小红", "小刚"};string subjects[] = {"语文", "数学", "英语", "科学"};// 计算每个学生的平均分cout << "学生平均分:" << endl;for (int i = 0; i < 3; i++) {int sum = 0;for (int j = 0; j < 4; j++) {sum += grades[i][j];}double average = static_cast<double>(sum) / 4;cout << students[i] << ": " << average << endl;}// 计算每门科目的平均分cout << "\n科目平均分:" << endl;for (int j = 0; j < 4; j++) {int sum = 0;for (int i = 0; i < 3; i++) {sum += grades[i][j];}double average = static_cast<double>(sum) / 3;cout << subjects[j] << ": " << average << endl;}return 0;
}
小练习: 创建一个5x5的二维数组,填充乘法表(1x1=1, 1x2=2, …, 5x5=25)。
3. 模拟算法:按照规则填充数组
3.1 什么是模拟算法?
模拟算法就是按照给定的规则,一步一步地完成任务。就像按照食谱做菜一样,按照步骤来就能得到想要的结果。
3.2 蛇形矩阵的模拟填充
蛇形矩阵是一种按照蛇形路径填充的矩阵。让我们一步步实现它:
#include <iostream>
#include <iomanip>
using namespace std;int main() {int n, m;cout << "请输入矩阵的行数和列数: ";cin >> n >> m;// 创建二维数组int matrix[n][m];int num = 1; // 从1开始填充for (int i = 0; i < n; i++) {if (i % 2 == 0) { // 偶数行:从左到右for (int j = 0; j < m; j++) {matrix[i][j] = num++;}} else { // 奇数行:从右到左for (int j = m - 1; j >= 0; j--) {matrix[i][j] = num++;}}}// 输出矩阵cout << "蛇形矩阵:" << endl;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cout << setw(4) << matrix[i][j] << " ";}cout << endl;}return 0;
}
3.3 螺旋矩阵的模拟填充
螺旋矩阵是另一种有趣的填充方式,数字按螺旋形状排列:
#include <iostream>
#include <iomanip>
using namespace std;int main() {int n;cout << "请输入矩阵的大小: ";cin >> n;int matrix[n][n];int num = 1;int top = 0, bottom = n - 1, left = 0, right = n - 1;while (top <= bottom && left <= right) {// 从左到右填充上边for (int j = left; j <= right; j++) {matrix[top][j] = num++;}top++;// 从上到下填充右边for (int i = top; i <= bottom; i++) {matrix[i][right] = num++;}right--;// 从右到左填充下边if (top <= bottom) {for (int j = right; j >= left; j--) {matrix[bottom][j] = num++;}bottom--;}// 从下到上填充左边if (left <= right) {for (int i = bottom; i >= top; i--) {matrix[i][left] = num++;}left++;}}// 输出矩阵cout << "螺旋矩阵:" << endl;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cout << setw(4) << matrix[i][j] << " ";}cout << endl;}return 0;
}
3.4 直接计算蛇形矩阵的值
对于蛇形矩阵,我们可以直接计算任意位置的值,而不需要填充整个矩阵:
#include <iostream>
using namespace std;int main() {int n, m, i, j;cout << "请输入矩阵的行数、列数和要查询的位置(行 列): ";cin >> n >> m >> i >> j;// 转换为0-based索引i--; j--;int value;if (i % 2 == 0) { // 偶数行value = i * m + j + 1;} else { // 奇数行value = (i + 1) * m - j;}cout << "第" << i+1 << "行第" << j+1 << "列的值是: " << value << endl;return 0;
}
小练习: 修改螺旋矩阵程序,使其能够处理非方阵(行数和列数不同)。
4. 边界处理:避免"越界"错误
4.1 什么是边界错误?
边界错误发生在尝试访问数组范围之外的元素时。这就像试图打开一个不存在的盒子,会导致程序崩溃或产生不可预测的结果。
4.2 常见的边界错误
#include <iostream>
using namespace std;int main() {int arr[5] = {1, 2, 3, 4, 5};// 这些访问会导致未定义行为(可能崩溃或输出错误值)cout << "访问越界元素: " << arr[5] << endl; // 索引5不存在(有效索引是0-4)cout << "访问负索引: " << arr[-1] << endl; // 负索引不存在return 0;
}
4.3 如何避免边界错误
方法1:检查索引是否有效
#include <iostream>
using namespace std;int main() {int arr[5] = {1, 2, 3, 4, 5};int index;cout << "请输入要访问的索引(0-4): ";cin >> index;if (index >= 0 && index < 5) {cout << "arr[" << index << "] = " << arr[index] << endl;} else {cout << "错误:索引越界!" << endl;}return 0;
}
方法2:在循环中正确处理边界
#include <iostream>
using namespace std;int main() {const int SIZE = 5;int arr[SIZE] = {1, 2, 3, 4, 5};// 正确的循环边界for (int i = 0; i < SIZE; i++) {cout << arr[i] << " ";}cout << endl;// 错误的循环边界(会导致越界)for (int i = 0; i <= SIZE; i++) { // i<=SIZE 是错误的cout << arr[i] << " ";}cout << endl;return 0;
}
方法3:使用安全的数据访问函数
#include <iostream>
using namespace std;// 安全访问数组元素的函数
int safeAccess(int arr[], int size, int index) {if (index < 0 || index >= size) {cout << "错误:索引 " << index << " 越界!" << endl;return -1; // 返回错误代码}return arr[index];
}int main() {int arr[5] = {1, 2, 3, 4, 5};cout << safeAccess(arr, 5, 2) << endl; // 正确访问cout << safeAccess(arr, 5, 5) << endl; // 越界访问return 0;
}
4.4 二维数组的边界处理
#include <iostream>
using namespace std;int main() {const int ROWS = 3;const int COLS = 4;int matrix[ROWS][COLS] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int row, col;cout << "请输入要访问的行(0-2)和列(0-3): ";cin >> row >> col;if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {cout << "matrix[" << row << "][" << col << "] = " << matrix[row][col] << endl;} else {cout << "错误:行或列索引越界!" << endl;}return 0;
}
小练习: 编写一个程序,创建一个10x10的矩阵,并实现一个函数来安全地访问矩阵中的元素,处理所有可能的边界错误。
5. 综合练习
5.1 井字棋游戏
#include <iostream>
using namespace std;const int SIZE = 3;void printBoard(char board[SIZE][SIZE]) {cout << " 0 1 2" << endl;for (int i = 0; i < SIZE; i++) {cout << i << " ";for (int j = 0; j < SIZE; j++) {cout << board[i][j] << " ";}cout << endl;}
}bool checkWin(char board[SIZE][SIZE], char player) {// 检查行for (int i = 0; i < SIZE; i++) {if (board[i][0] == player && board[i][1] == player && board[i][2] == player) {return true;}}// 检查列for (int j = 0; j < SIZE; j++) {if (board[0][j] == player && board[1][j] == player && board[2][j] == player) {return true;}}// 检查对角线if (board[0][0] == player && board[1][1] == player && board[2][2] == player) {return true;}if (board[0][2] == player && board[1][1] == player && board[2][0] == player) {return true;}return false;
}bool isBoardFull(char board[SIZE][SIZE]) {for (int i = 0; i < SIZE; i++) {for (int j = 0; j < SIZE; j++) {if (board[i][j] == ' ') {return false;}}}return true;
}int main() {char board[SIZE][SIZE] = {{' ', ' ', ' '},{' ', ' ', ' '},{' ', ' ', ' '}};char currentPlayer = 'X';int row, col;while (true) {printBoard(board);cout << "玩家 " << currentPlayer << ", 请输入行和列(0-2): ";cin >> row >> col;// 检查输入是否有效if (row < 0 || row >= SIZE || col < 0 || col >= SIZE) {cout << "无效的位置,请重新输入!" << endl;continue;}// 检查位置是否已被占用if (board[row][col] != ' ') {cout << "该位置已被占用,请重新选择!" << endl;continue;}// 放置棋子board[row][col] = currentPlayer;// 检查是否获胜if (checkWin(board, currentPlayer)) {printBoard(board);cout << "玩家 " << currentPlayer << " 获胜!" << endl;break;}// 检查是否平局if (isBoardFull(board)) {printBoard(board);cout << "平局!" << endl;break;}// 切换玩家currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';}return 0;
}
5.2 矩阵转置
#include <iostream>
using namespace std;int main() {const int ROWS = 3;const int COLS = 4;int matrix[ROWS][COLS] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};int transpose[COLS][ROWS];// 转置矩阵for (int i = 0; i < ROWS; i++) {for (int j = 0; j < COLS; j++) {transpose[j][i] = matrix[i][j];}}// 输出原矩阵cout << "原矩阵:" << endl;for (int i = 0; i < ROWS; i++) {for (int j = 0; j < COLS; j++) {cout << matrix[i][j] << "\t";}cout << endl;}// 输出转置矩阵cout << "\n转置矩阵:" << endl;for (int i = 0; i < COLS; i++) {for (int j = 0; j < ROWS; j++) {cout << transpose[i][j] << "\t";}cout << endl;}return 0;
}
6. 下一步学习建议
恭喜你完成了数组和矩阵操作的学习!这些是编程中非常重要的概念,几乎每个程序都会用到。接下来你可以:
- 多练习:尝试编写更多使用数组和矩阵的程序
- 学习动态数组:如C++的vector,可以动态调整大小
- 探索算法:如排序、搜索等基于数组的算法
- 尝试图形编程:使用矩阵表示和变换图形
- 参加编程竞赛:很多竞赛题目都涉及数组和矩阵操作
记住,数组和矩阵是编程的基础工具,熟练掌握它们对你未来的编程学习非常重要。不要害怕挑战,每个程序都是学习的机会!