L3 - 一维数组实战

🎯 教学目标

  1. 掌握数组的声明与初始化
  2. 熟练使用循环处理数组元素
  3. 实现基础统计算法

🔑 核心知识点

数组声明与初始化

1
2
3
4
// 标准声明方式
int scores[5]; // 声明包含5个整数的数组(未初始化)
float temps[7] = {}; // 全部初始化为0.0
char vowels[] = {'a','e','i','o','u'}; // 自动推导长度

关键要点:

  1. 内存分配原理

    • 连续内存块分配
    • 每个元素占数据类型对应字节数(int通常4字节)
    • 数组总大小 = 元素个数 × sizeof(元素类型)
  2. 初始化规则

    1
    2
    3
    int arr1[3];            // 值随机(危险!)
    int arr2[3] = {1,2}; // [1,2,0]
    int arr3[] = {9,8,7}; // 长度自动推导为3
  3. 访问机制

    • 索引从0开始计算
    • 通过首地址偏移访问元素
    • arr[i] 等效于 *(arr + i)

数组遍历标准模板

1
2
3
4
5
6
const int N = 5; // 最佳实践:用常量表示数组长度
int nums[N] = {3,1,4,1,5};

for(int i=0; i<N; i++){ // 严格使用 < 避免越界
cout << nums[i] << " ";
}

执行流程解析:

1
2
3
内存地址 | 0x1000 | 0x1004 | 0x1008 | 0x100C | 0x1010
元素值 | 3 | 1 | 4 | 1 | 5
索引 | [0] | [1] | [2] | [3] | [4]

📊 数据处理算法

求最大值算法

1
2
3
4
5
6
7
8
9
int findMax(int arr[], int size) {
int maxVal = arr[0]; // 假设第一个元素最大
for(int i=1; i<size; i++){ // 从第二个元素开始比较
if(arr[i] > maxVal){
maxVal = arr[i]; // 更新最大值
}
}
return maxVal;
}

算法优化技巧:

  • 初始值设为INT_MIN可处理全负数数组
  • 可同步记录最大值索引
  • 时间复杂度:O(n)

逆序存储算法

1
2
3
4
5
6
7
8
9
10
void reverseArray(int arr[], int size) {
int left = 0; // 首指针
int right = size - 1; // 尾指针

while(left < right) { // 双指针向中间移动
swap(arr[left], arr[right]);
left++;
right--;
}
}

内存变化演示:

1
2
3
4
原始数组:[1][2][3][4][5]
第1次交换:[5][2][3][4][1]
第2次交换:[5][4][3][2][1]
终止条件:left=2, right=2

💡 特别提示

数组越界陷阱

1
2
int arr[3] = {1,2,3};
cout << arr[3]; // 访问非法内存(索引0-2有效)
  • 可能后果:
    • 输出垃圾值
    • 程序崩溃(Segment Fault)
    • 覆盖其他变量内存

字符数组注意事项

1
2
3
char str1[5] = "hello";  // 错误!需要6个位置(含\0)
char str2[5] = {'h','e','l','l','o'}; // 合法但不安全
char str3[] = "world"; // 自动分配6字节

字符串处理要点:

  • 使用strlen()获取实际长度
  • cin.getline(str, size)安全输入
  • 末尾必须保留\0

💣 易错点详解

  1. 变量定义数组长度

    1
    2
    int n = 5;
    int arr[n]; // C99允许,但C++标准禁止!
  2. 越界访问导致数据污染

    1
    2
    3
    int a = 10;
    int arr[3] = {1,2,3};
    arr[3] = 4; // 实际修改了a的值!
  3. 数组整体赋值错误

    1
    2
    3
    int arr1[3] = {1,2,3};
    int arr2[3];
    arr2 = arr1; // 错误!数组不能直接赋值
  4. 误用sizeof计算元素个数

    1
    2
    3
    int arr[] = {1,2,3,4,5};
    int size = sizeof(arr); // 错误!返回总字节数
    // 正确写法:sizeof(arr)/sizeof(arr[0])

🛠️ 调试技巧

数组内容可视化调试

1
2
3
4
5
6
7
8
// 调试专用输出函数
void printArray(int arr[], int size) {
cout << "索引\t地址\t值\n";
for(int i=0; i<size; i++){
cout << i << "\t" << &arr[i]
<< "\t" << arr[i] << endl;
}
}

输出示例:

1
2
3
4
索引  地址        值
0 0x7ffeed0a 10
1 0x7ffeed0e 20
2 0x7ffeed12 30

边界值测试策略

  1. 空数组测试(size=0)
  2. 单元素数组测试
  3. 全相同元素数组
  4. 极值测试(INT_MAX/MIN)

🏋️ 配套练习

  1. 成绩分析系统

    • 输入:n个学生成绩(0-100)
    • 输出:
      • 平均分(保留2位小数)
      • 最高分及人数
      • 各分数段分布(0-59,60-69,…)
  2. 元素查找器

    • 输入:长度为10的数组,1个目标数
    • 输出:
      • 首次出现位置(从1开始)
      • 最后一次出现位置
      • 未找到时输出"Not Found"
  3. 数组洗牌器

    • 输入:数组长度n,数组元素
    • 输出:
      • 奇数在前偶数在后,相对顺序不变
      • 示例:
        输入:5 [2,5,8,3,6]
        输出:5 3 2 8 6
  4. 矩阵转置器

    • 输入:3x3矩阵
    • 输出:转置矩阵
      1
      2
      3
      4
      5
      6
      7
      8
      输入:
      1 2 3
      4 5 6
      7 8 9
      输出:
      1 4 7
      2 5 8
      3 6 9
  5. 凯撒密码加密机

    • 输入:字符串(仅字母),偏移量
    • 输出:加密结果(Z后回到A)
      1
      2
      输入:ATTACK 3
      输出:DWWDFN