#c

C++一维静态数组

数据的有序集合

#c
@鞠大龙
魅客科创中心

CONTENTS

目录

1. 数组的基本概念

1.1 什么是数组?

  • 数组是一组相同类型的数据的有序集合
  • 数组中的每个数据称为元素
  • 数组的大小在定义时确定,之后不能改变
  • 数组在内存中是连续存储的
  • 通过下标(索引)访问数组元素,从0开始计数
// 一个存储5个整数的数组示例
int numbers[5] = {1, 2, 3, 4, 5};

// 数组在内存中的示意图
// [1][2][3][4][5]
//  ↑
// 数组的第一个元素(下标为0)
返回目录 信息学 C++一维静态数组 魅客科创中心

1.2 数组的特点

优点

  • 访问元素快速(通过下标直接访问)
  • 内存使用连续,效率高
  • 适合存储固定数量的数据
  • 可以方便地遍历所有元素

使用场景

  • 存储学生成绩
  • 记录每月温度
  • 保存游戏分数
  • 处理固定长度的数据序列

注意事项

  • 大小固定,不能改变
  • 所有元素类型必须相同
  • 下标从0开始计数
  • 必须注意防止下标越界
int scores[3];  // 创建数组

// 正确的访问
scores[0] = 85;
scores[1] = 92;
scores[2] = 78;

// 错误的访问(越界)
scores[3] = 90;  // 危险!
返回目录 信息学 C++一维静态数组 魅客科创中心

1.3 为什么使用数组?

不使用数组的情况

int score1 = 85;
int score2 = 92;
int score3 = 78;
int score4 = 95;
int score5 = 88;
double average = (score1 + score2 + score3 + score4 + score5) / 5.0;// 计算平均分

使用数组的情况

int scores[5] = {85, 92, 78, 95, 88};// 使用数组存储5个学生的成绩
int sum = 0;
for(int i = 0; i < 5; i++) {
    sum += scores[i];
}
double average = sum / 5.0;
返回目录 信息学 C++一维静态数组 魅客科创中心

2. 数组的声明和初始化

2.1 数组的声明

基本语法

数据类型 数组名[数组大小];

示例

int numbers[10]; // 声明一个包含10个整数的数组
char letters[5]; // 声明一个包含5个字符的数组
double values[100]; // 声明一个包含100个浮点数的数组
// 数组大小必须是常量或常量表达式
const int SIZE = 20;
int data[SIZE];
// 错误的声明方式
int n = 10;
int wrong[n];  // 错误:数组大小必须是常量
返回目录 信息学 C++一维静态数组 魅客科创中心

2.2 数组的初始化

完整初始化

// 方法1:使用花括号
int numbers[5] = {1, 2, 3, 4, 5};

// 方法2:声明时不指定大小
int numbers[] = {1, 2, 3, 4, 5};
// 编译器会自动计算大小

// 方法3:全部初始化为0
int numbers[5] = {0};

部分初始化

// 只初始化部分元素
int numbers[5] = {1, 2};
// 其余元素自动设为0
// numbers = {1, 2, 0, 0, 0}

// 错误的初始化方式
int numbers[3] = {1, 2, 3, 4};
// 错误:初始值太多

int numbers[5];
numbers = {1, 2, 3, 4, 5};
// 错误:不能整体赋值
返回目录 信息学 C++一维静态数组 魅客科创中心

2.3 常见的初始化问题

// 1. 未初始化的数组
int numbers[5];  // 数组元素的值是随机的
// 2. 初始化值过多
int numbers[3] = {1, 2, 3, 4, 5};  // 错误
// 3. 使用变量作为数组大小
int size = 5;
int numbers[size];  // 错误:必须使用常量
// 4. 试图在声明后整体赋值
int numbers[5];
numbers = {1, 2, 3, 4, 5};  // 错误

// 正确的做法
const int SIZE = 5;  // 使用常量定义大小
int numbers[SIZE] = {0};  // 全部初始化为0
// 然后逐个赋值
for(int i = 0; i < SIZE; i++) {
    numbers[i] = i + 1;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

3. 访问和修改数组元素

3.1 数组元素的访问

  • 使用下标(索引)访问数组元素
  • 下标从0开始,到数组大小-1结束
  • 使用方括号[]访问元素
int numbers[5] = {10, 20, 30, 40, 50};

// 访问数组元素
cout << numbers[0] << endl;  // 输出:10
cout << numbers[4] << endl;  // 输出:50

// 使用变量作为下标
int index = 2;
cout << numbers[index] << endl;  // 输出:30

// 注意:访问越界会导致未定义行为
cout << numbers[5] << endl;  // 错误:下标越界
返回目录 信息学 C++一维静态数组 魅客科创中心

3.2 修改数组元素

直接赋值

int numbers[5] = {1, 2, 3, 4, 5};

// 修改单个元素
numbers[0] = 10;
numbers[4] = 50;

// 使用变量
int index = 2;
int value = 30;
numbers[index] = value;

// 使用表达式
numbers[1] = numbers[0] * 2;

常见错误

int numbers[5] = {1, 2, 3, 4, 5};

// 越界访问
numbers[5] = 60;  // 错误

// 使用负数下标
numbers[-1] = 0;  // 错误

// 使用过大的下标
int i = 10;
numbers[i] = 100;  // 错误

// 没有边界检查
// C++不会自动检查数组越界
// 需要程序员自己确保下标合法
返回目录 信息学 C++一维静态数组 魅客科创中心

3.3 数组边界检查

为了安全访问数组,我们应该:

  1. 始终检查数组下标是否在有效范围内
  2. 使用常量定义数组大小,便于维护
  3. 在访问数组之前验证下标
const int SIZE = 5;
int numbers[SIZE] = {1, 2, 3, 4, 5};

// 安全的数组访问
if(index >= 0 && index < SIZE) {
  value = numbers[index];
}
返回目录 信息学 C++一维静态数组 魅客科创中心

4. 数组的遍历

4.1 使用for循环遍历

遍历就是按照某种顺序访问数组中的元素

const int SIZE = 5;
int numbers[SIZE] = {1, 2, 3, 4, 5};
// 正向遍历
for(int i = 0; i < SIZE; i++) {
    cout << numbers[i] << " ";
}
// 输出:1 2 3 4 5
// 反向遍历
for(int i = SIZE - 1; i >= 0; i--) {
    cout << numbers[i] << " ";
}
// 输出:5 4 3 2 1
// 按步长遍历(每次跳过一个元素)
for(int i = 0; i < SIZE; i += 2) {
    cout << numbers[i] << " ";
}
// 输出:1 3 5
返回目录 信息学 C++一维静态数组 魅客科创中心

4.2 遍历中的常见操作

修改元素

for(int i = 0; i < SIZE; i++) {
    numbers[i] *= 2;// 将所有元素乘以2
}
for(int i = 0; i < SIZE; i++) {
    numbers[i] += i;// 将所有元素加上下标值
}

统计信息


int sum = 0;
for(int i = 0; i < SIZE; i++) {
    sum += numbers[i];// 计算元素和
}
double average = (double)sum / SIZE;// 计算平均值

条件处理

// 统计偶数的个数
int count = 0;
for(int i = 0; i < SIZE; i++) {
    if(numbers[i] % 2 == 0) {
        count++;
    }
}
// 查找特定值
int target = 3;
bool found = false;
for(int i = 0; i < SIZE; i++) {
    if(numbers[i] == target) {
        found = true;
        break;
    }
}
返回目录 信息学 C++一维静态数组 魅客科创中心

4.3 遍历的注意事项

  1. 循环边界
const int SIZE = 5;
int numbers[SIZE] = {1, 2, 3, 4, 5};
// 正确的循环边界
for(int i = 0; i < SIZE; i++)  // 使用 < 而不是 <=
// 错误的循环边界
for(int i = 1; i <= SIZE; i++)  // 从1开始会漏掉第一个元素
for(int i = 0; i <= SIZE; i++)  // 使用<=会导致越界
  1. 防止越界
for(int i = 0; i < SIZE; i++) {
    // 危险:在循环中修改i可能导致越界或无限循环
    if(numbers[i] < 0) {
        i--;  // 不要这样做!
    }
}
  1. 使用常量定义大小
const int SIZE = 5;  // 使用常量便于维护
int numbers[SIZE];   // 数组大小使用常量

// 避免使用魔法数字
for(int i = 0; i < 5; i++)  // 不好
for(int i = 0; i < SIZE; i++)  // 好
返回目录 信息学 C++一维静态数组 魅客科创中心

5. 数组的常见操作

5.1 查找操作

const int SIZE = 5;
int numbers[SIZE] = {1, 3, 5, 2, 4};

// 1. 查找特定值
int target = 3;
int findIndex = -1;  // 存储找到的位置,-1表示未找到

for(int i = 0; i < SIZE; i++) {
    if(numbers[i] == target) {
        findIndex = i;
        break;
    }
}

// 2. 查找最大值
int maxValue = numbers[0];  // 假设第一个元素是最大的
int maxIndex = 0;

for(int i = 1; i < SIZE; i++) {
    if(numbers[i] > maxValue) {
        maxValue = numbers[i];
        maxIndex = i;
    }
}

// 3. 查找最小值
int minValue = numbers[0];
int minIndex = 0;

for(int i = 1; i < SIZE; i++) {
    if(numbers[i] < minValue) {
        minValue = numbers[i];
        minIndex = i;
    }
}
返回目录 信息学 C++一维静态数组 魅客科创中心

5.2 统计操作

计算总和与平均值

int numbers[5] = {1, 2, 3, 4, 5};

// 计算总和
int sum = 0;
for(int i = 0; i < 5; i++) {
    sum += numbers[i];
}

// 计算平均值
double average = (double)sum / 5;

统计符合条件的元素

// 统计偶数个数
int evenCount = 0;
for(int i = 0; i < 5; i++) {
    if(numbers[i] % 2 == 0) {
        evenCount++;
    }
}

计算最大和最小值的差

// 找出最大和最小值
int max = numbers[0];
int min = numbers[0];

for(int i = 1; i < 5; i++) {
    if(numbers[i] > max) {
        max = numbers[i];
    }
    if(numbers[i] < min) {
        min = numbers[i];
    }
}

// 计算差值
int difference = max - min;
返回目录 信息学 C++一维静态数组 魅客科创中心

5.3 修改操作

const int SIZE = 5;
int numbers[SIZE] = {1, 2, 3, 4, 5};

// 1. 所有元素加上一个值
int addValue = 10;
for(int i = 0; i < SIZE; i++) {
    numbers[i] += addValue;
}

// 2. 所有元素乘以一个值
int multiplyValue = 2;
for(int i = 0; i < SIZE; i++) {
    numbers[i] *= multiplyValue;
}

// 3. 数组元素反转
for(int i = 0; i < SIZE/2; i++) {
    // 交换首尾对应的元素
    int temp = numbers[i];
    numbers[i] = numbers[SIZE-1-i];
    numbers[SIZE-1-i] = temp;
}

// 4. 将所有负数变成0
for(int i = 0; i < SIZE; i++) {
    if(numbers[i] < 0) {
        numbers[i] = 0;
    }
}
返回目录 信息学 C++一维静态数组 魅客科创中心

5.4 简单排序

const int SIZE = 5;
int numbers[SIZE] = {4, 2, 5, 1, 3};

// 冒泡排序(从小到大)
for(int i = 0; i < SIZE-1; i++) {
    for(int j = 0; j < SIZE-1-i; j++) {
        if(numbers[j] > numbers[j+1]) {
            // 交换相邻的两个元素
            int temp = numbers[j];
            numbers[j] = numbers[j+1];
            numbers[j+1] = temp;
        }
    }
}

// 选择排序(从小到大)
for(int i = 0; i < SIZE-1; i++) {
    // 找出第i个位置后面最小的元素
    int minIndex = i;
    for(int j = i+1; j < SIZE; j++) {
        if(numbers[j] < numbers[minIndex]) {
            minIndex = j;
        }
    }
    // 将找到的最小元素放到第i个位置
    if(minIndex != i) {
        int temp = numbers[i];
        numbers[i] = numbers[minIndex];
        numbers[minIndex] = temp;
    }
}
返回目录 信息学 C++一维静态数组 魅客科创中心

6. 数组作为函数参数

6.1 传递数组给函数

// 方法1:使用数组作为参数
void printArray(int arr[], int size) {
    for(int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// 方法2:使用指针作为参数(效果相同)
void printArray(int* arr, int size) {
    for(int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    const int SIZE = 5;
    int numbers[SIZE] = {1, 2, 3, 4, 5};
    
    // 调用函数
    printArray(numbers, SIZE);
    
    return 0;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

6.2 在函数中修改数组

修改数组元素

// 将数组所有元素加倍
void doubleElements(int arr[], int size) {
    for(int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    int numbers[5] = {1, 2, 3, 4, 5};
    doubleElements(numbers, 5);
    // numbers现在是{2,4,6,8,10}
    return 0;
}

注意事项

  • 数组作为参数传递时,实际传递的是数组的地址
  • 在函数中修改数组会影响原数组
  • 必须同时传递数组大小
  • 函数不能返回局部数组
// 错误示例:返回局部数组
int[] wrongFunction() {
    int arr[5] = {1,2,3,4,5};
    return arr;  // 错误!
}
返回目录 信息学 C++一维静态数组 魅客科创中心

6.3 常用的数组处理函数

// 1. 计算数组元素和
int getSum(const int arr[], int size) {
    int sum = 0;
    for(int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// 2. 查找最大值
int findMax(const int arr[], int size) {
    if(size == 0) return 0;  // 处理空数组
    int max = arr[0];
    for(int i = 1; i < size; i++) {
        if(arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

// 3. 复制数组
void copyArray(const int source[], int target[], int size) {
    for(int i = 0; i < size; i++) {
        target[i] = source[i];
    }
}

// 使用示例
int main() {
    const int SIZE = 5;
    int numbers[SIZE] = {1, 2, 3, 4, 5};
    int copy[SIZE];
    
    cout << "Sum: " << getSum(numbers, SIZE) << endl;
    cout << "Max: " << findMax(numbers, SIZE) << endl;
    copyArray(numbers, copy, SIZE);
    
    return 0;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

7. 应用实例

7.1 学生成绩统计

题目说明

  • 目标:统计一个班级的考试成绩
  • 要求:计算平均分、最高分、最低分,统计及格人数
  • 输入:10个学生的成绩
  • 输出:统计结果
int main() {
    const int SIZE = 10;
    int scores[SIZE];
    
    // 输入成绩
    cout << "请输入" << SIZE << "个学生的成绩:" << endl;
    for(int i = 0; i < SIZE; i++) {
        cin >> scores[i];
    }
    
    // 计算统计数据
    int sum = 0, max = scores[0], min = scores[0];
    int passCount = 0;  // 及格人数
    
    for(int i = 0; i < SIZE; i++) {
        sum += scores[i];
        if(scores[i] > max) max = scores[i];
        if(scores[i] < min) min = scores[i];
        if(scores[i] >= 60) passCount++;
    }
    
    // 输出结果
    cout << "平均分:" << (double)sum / SIZE << endl;
    cout << "最高分:" << max << endl;
    cout << "最低分:" << min << endl;
    cout << "及格人数:" << passCount << endl;
    cout << "及格率:" << (double)passCount / SIZE * 100 << "%" << endl;
    
    return 0;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

7.2 简单的数独检查

题目说明

  • 目标:检查一个9×9的数独中的一行是否合法
  • 要求:检查是否包含1-9的所有数字,且没有重复
  • 输入:一个包含9个数字的数组
  • 输出:是否合法
bool checkSudokuRow(int row[], int size) {
    // 创建一个数组记录数字是否出现
    bool used[10] = {false};  // 0号位置不使用
    
    // 检查每个数字
    for(int i = 0; i < size; i++) {
        // 检查数字是否在1-9范围内
        if(row[i] < 1 || row[i] > 9) {
            return false;
        }
        
        // 检查数字是否重复
        if(used[row[i]]) {
            return false;  // 数字已经出现过
        }
        
        used[row[i]] = true;  // 标记数字已使用
    }
    
    // 检查是否使用了所有数字1-9
    for(int i = 1; i <= 9; i++) {
        if(!used[i]) {
            return false;  // 缺少数字
        }
    }
    
    return true;  // 行合法
}

int main() {
    int sudokuRow[9] = {5, 3, 4, 6, 7, 8, 9, 1, 2};
    
    if(checkSudokuRow(sudokuRow, 9)) {
        cout << "数独行合法" << endl;
    } else {
        cout << "数独行不合法" << endl;
    }
    
    return 0;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

7.3 简单计分板

题目说明

  • 目标:实现一个简单的游戏计分板
  • 要求:记录最近5局游戏的分数,计算平均分
  • 功能:添加新分数时,最老的分数被删除
class Scoreboard {
private:
    const static int MAX_SCORES = 5;  // 保存最近5局分数
    int scores[MAX_SCORES];           // 分数数组
    int count;                        // 当前记录的分数数量
    
public:
    // 构造函数
    Scoreboard() {
        count = 0;
        for(int i = 0; i < MAX_SCORES; i++) {
            scores[i] = 0;
        }
    }
    
    // 添加新分数
    void addScore(int score) {
        // 移动所有分数
        for(int i = MAX_SCORES - 1; i > 0; i--) {
            scores[i] = scores[i-1];
        }
        // 在开头添加新分数
        scores[0] = score;
        // 更新计数
        if(count < MAX_SCORES) count++;
    }
    
    // 显示所有分数
    void displayScores() {
        cout << "最近" << count << "局游戏分数:" << endl;
        for(int i = 0; i < count; i++) {
            cout << "第" << i+1 << "局:" << scores[i] << endl;
        }
        
        // 计算并显示平均分
        if(count > 0) {
            int sum = 0;
            for(int i = 0; i < count; i++) {
                sum += scores[i];
            }
            cout << "平均分:" << (double)sum / count << endl;
        }
    }
};

int main() {
    Scoreboard board;
    
    // 添加一些测试分数
    board.addScore(100);
    board.addScore(85);
    board.addScore(95);
    board.displayScores();
    
    cout << "\n添加更多分数:\n" << endl;
    board.addScore(75);
    board.addScore(90);
    board.addScore(88);  // 这将删除最早的分数(100)
    board.displayScores();
    
    return 0;
}
返回目录 信息学 C++一维静态数组 魅客科创中心

8. 练习题

8.1 基础练习

  1. 创建一个整数数组,包含10个元素,将所有元素初始化为0
  2. 让用户输入5个数字,存入数组,然后按相反顺序打印出来
  3. 计算数组中所有元素的平均值
  4. 找出数组中的最大值和最小值
返回目录 信息学 C++一维静态数组 魅客科创中心

8.2 中级练习

  1. 统计数组中偶数和奇数的个数
  2. 将数组中的正数和负数分别统计出来
  3. 检查数组是否按升序排列
  4. 将两个有序数组合并成一个有序数组
返回目录 信息学 C++一维静态数组 魅客科创中心

8.3 实际题目练习

初级题目

  1. HDU 2000 - ASCII码排序 (★☆☆☆☆)

    • 输入三个字符,按ASCII码从小到大输出
    • 练习数组排序的基本操作
  2. HDU 2001 - 计算两点间的距离 (★☆☆☆☆)

    • 计算平面上两点间的距离
    • 使用数组存储坐标
  3. NOIP 2008 普及组 - 排座椅 (★★☆☆☆)

    • 使用数组记录学生身高
    • 按照特定规则排列座位

中级题目

  1. CSP-J 2019 - 数字游戏 (★★☆☆☆)

    • 统计二进制数中1的个数
    • 使用数组存储和处理数据
  2. USACO 2019 Bronze - Bucket Brigade (★★☆☆☆)

    • 使用数组表示农场地图
    • 计算从谷仓到湖的最短路径
  3. POJ 3094 - Quicksum (★★☆☆☆)

    • 计算字符串的加权和
    • 使用数组存储和处理字符
返回目录 信息学 C++一维静态数组 魅客科创中心

8.4 综合应用题

1. CSP-J 2022 - 解密 (★★★☆☆)

  • 使用数组处理密码
  • 实现简单的解密算法
  • 练习数组索引和操作

2. NOIP 2012 普及组 - 质因数分解 (★★★☆☆)

  • 将一个数分解为两个质数的乘积
  • 使用数组存储质数
  • 练习数组查找

3. CSES - Missing Number (★★☆☆☆)

  • 找出1到n中缺失的数字
  • 使用数组标记已出现的数字
  • 练习数组的基本操作

4. USACO 2017 Bronze - Why Did the Cow Cross the Road (★★★☆☆)

  • 使用数组记录奶牛位置
  • 计算奶牛穿过道路的次数
  • 练习数组排序和计数
返回目录 信息学 C++一维静态数组 魅客科创中心

8.5 扩展思考题

  1. 如何判断两个数组是否相等?
  2. 如何在不使用额外数组的情况下反转数组?
  3. 如何高效地在数组中删除重复元素?
  4. 数组和链表各有什么优缺点?
  5. 在什么情况下应该使用静态数组而不是动态数组(vector)?
返回目录 信息学 C++一维静态数组 魅客科创中心

9. 总结

9.1 重要概念回顾

  • 数组定义:相同类型数据的有序集合
  • 数组特点
    • 固定大小
    • 连续内存
    • 通过下标访问
    • 下标从0开始
  • 常见操作
    • 初始化
    • 访问和修改
    • 遍历
    • 查找和统计
    • 作为函数参数
返回目录 信息学 C++一维静态数组 魅客科创中心

9.2 使用建议

  1. 安全性

    • 始终检查数组边界
    • 使用常量定义数组大小
    • 初始化所有元素
  2. 可维护性

    • 使用有意义的变量名
    • 添加适当的注释
    • 使用函数封装常用操作
  3. 效率

    • 合理设计数组大小
    • 避免不必要的遍历
    • 选择合适的算法
  4. 进阶学习

    • 学习动态数组(vector)
    • 了解多维数组
    • 掌握常用算法

#c

返回目录 信息学 C++一维静态数组 魅客科创中心
C++一维静态数组

#c

感谢学习!
如有疑问,请联系:
judal@xmaker.org
魅客科创中心

内容针对初学者设计,使用简单易懂的语言和示例。 假设学生已经了解基本数据类型、循环和判断语句。