欢迎光临
我们一直在努力

C语言从入门到进阶——第5讲:数组

文章目录

    • 1. 数组的概念
    • 2. 一维数组的创建和初始化
      • 2.1 数组创建
      • 2.2 数组的初始化
      • 2.3 数组的类型
    • 3. 一维数组的使用
      • 3.1 数组下标
      • 3.2 数组元素的打印
      • 3.3 数组的输入
    • 4. 一维数组在内存中的存储
    • 5. sizeof计算数组元素个数
    • 6. 二维数组的创建
      • 6.1 二维数组的概念
      • 6.2 二维数组的创建语法
    • 7. 二维数组的初始化
      • 7.1 不完全初始化
      • 7.2 完全初始化
      • 7.3 按照行初始化
      • 7.4 省略行的初始化
    • 8. 二维数组的使用
      • 8.1 二维数组的下标
      • 8.2 二维数组的输入和输出
    • 9. 二维数组在内存中的存储
    • 10. C99中的变长数组
      • 10.1 传统数组的限制
      • 10.2 变长数组的特性
    • 11. 数组练习
      • 11.1 练习1:多个字符从两端移动,向中间汇聚
      • 11.2 练习2:二分查找

1. 数组的概念

数组是一组相同类型元素的集合,从中可以提炼两个关键信息:

  • 数组中存放的元素个数不能为0,可存放一个或多个数据
  • 数组中所有元素的数据类型必须相同
  • 数组分为一维数组和多维数组,日常使用中以二维数组最为常见。

    2. 一维数组的创建和初始化

    2.1 数组创建

    一维数组创建的基本语法如下:

    type arr_name[常量值];

    • type:指定数组中元素的数据类型,如char、short、int、float等
    • arr_name:数组名,可根据需求自定义有意义的名称
    • []中的常量值:指定数组的元素个数

    示例:

    // 存储20人的数学成绩
    int math[20];
    // 存储8个字符
    char ch[8];
    // 存储10个浮点型分数
    double score[10];

    2.2 数组的初始化

    数组创建时给定初始值的操作称为初始化,通常使用 大括号{} 完成。

    完全初始化:所有元素都赋予初始值

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

    不完全初始化:只给部分元素赋值,未赋值的元素默认初始化为0

    int arr2[6] = {1};// 第一个元素为1,剩余5个元素为0

    错误初始化:初始化的元素个数超过数组的大小

    // 错误:数组大小为3,初始化项有4个
    int arr3[3] = {1, 2, 3, 4};

    省略大小初始化:数组初始化时可省略大小,编译器会根据初始化项的个数确定数组大小

    int arr4[] = {1,2,3};// 数组大小为3

    2.3 数组的类型

    数组属于自定义类型,去掉数组名后剩下的部分就是数组的类型。

    示例:

    int arr1[10];// 数组类型:int [10]
    int arr2[12];// 数组类型:int [12]
    char ch[5];// 数组类型:char [5]

    3. 一维数组的使用

    3.1 数组下标

    C语言规定数组的下标从0开始,假设数组有n个元素,最后一个元素的下标为n-1。例如:

    int arr[10] = {1,2,3,4,5,6,7,8,9,10};

    在这里插入图片描述

    数组提供了 下标引用操作符[] 来访问元素,语法为数组名[下标]。

    示例:

    #include <stdio.h>
    int main()
    {
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    // 访问下标为7的元素,值为8
    printf("%d\\n", arr[7]);
    // 访问下标为3的元素,值为4
    printf("%d\\n", arr[3]);
    return 0;
    }

    输出结果:

    8
    4

    3.2 数组元素的打印

    通过for循环生成所有元素的下标,即可遍历打印整个数组。

    示例:

    #include <stdio.h>
    int main()
    {
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    for(i = 0; i < 10; i++)
    {
    printf("%d ", arr[i]);
    }
    return 0;
    }

    输出结果:

    1 2 3 4 5 6 7 8 9 10

    3.3 数组的输入

    使用scanf配合下标引用操作符,可给数组元素输入数据。

    示例:

    #include <stdio.h>
    int main()
    {
    int arr[10] = {0};
    int i = 0;
    // 输入数据
    for(i = 0; i < 10; i++)
    {
    scanf("%d", &arr[i]);
    }
    // 输出数据
    for(i = 0; i < 10; i++)
    {
    printf("%d ", arr[i]);
    }
    return 0;
    }

    输入输出结果:

    0 2 4 6 8 1 3 5 7 9
    0 2 4 6 8 1 3 5 7 9

    4. 一维数组在内存中的存储

    通过打印数组每个元素的地址,可以观察数组在内存中的存储规律。

    示例代码:

    #include <stdio.h>
    int main()
    {
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    for(i = 0; i < 10; i++)
    {
    printf("&arr[%d] = %p\\n ", i, &arr[i]);
    }
    return 0;
    }

    输出结果: 在这里插入图片描述 根据上述结果,数组元素的地址随着下标的增长由小到大变化,且相邻元素的地址差值为4个字节(对应int类型的大小) 所以可以得出结论:一维数组在内存中是连续存放的

    5. sizeof计算数组元素个数

    sizeof是C语言的关键字,可计算类型或变量所占内存的大小(单位:字节),也能计算整个数组的总大小。

    计算原理:

    • 数组总大小 = sizeof(数组名)
    • 单个元素大小 = sizeof(数组名[0])
    • 元素个数 = 数组总大小 / 单个元素大小= sizeof(数组名)/sizeof(数组名[0])

    示例代码:

    #include <stdio.h>
    int main()
    {
    int arr[10] = {0};
    printf("%zd\\n", sizeof(arr)); // 计算数组总大小,结果为40
    printf("%zd\\n", sizeof(arr[0])); // 计算单个元素大小,结果为4
    printf("%zd\\n", sizeof(arr)/sizeof(arr[0])); // 计算元素个数,结果为10
    return 0;
    }

    注意:使用%zd作为sizeof计算结果的占位符,适配size_t类型

    6. 二维数组的创建

    6.1 二维数组的概念

    二维数组可以理解为数组的数组,即把一维数组作为元素,组成一个新的数组。 同理,二维数组为元素的数组被称为三维数组,二维及以上数组统称为多维数组。

    6.2 二维数组的创建语法

    type arr_name[常量值1][常量值2];

    • 常量值1:表示二维数组的行数
    • 常量值2:表示二维数组的列数
    • type:表示数组元素的数据类型

    示例:

    // 3行5列的整型二维数组
    int arr[3][5];
    // 2行8列的浮点型二维数组
    double data[2][8];

    7. 二维数组的初始化

    二维数组的初始化同样使用大括号{},支持多种初始化方式。

    7.1 不完全初始化

    只给部分元素赋值,未赋值的元素默认初始化为0

    // 第一行前两个元素为1、2,其余元素为0
    int arr1[3][5] = {1, 2};
    // 所有元素初始化为0
    int arr2[3][5] = {0};

    7.2 完全初始化

    按行顺序给所有元素赋值

    int arr3[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};

    7.3 按照行初始化

    使用嵌套大括号,明确每一行的初始值

    // 第一行:1、2;第二行:3、4;第三行:5、6;其余元素为0
    int arr4[3][5] = {{1,2},{3,4},{5,6}};

    7.4 省略行的初始化

    初始化时可以省略行数,但不能省略列数,编译器会根据初始化项自动计算行数

    int arr5[][5] = {1,2,3};
    int arr6[][5] = {1,2,3,4,5,6,7};
    int arr7[][5] = {{1,2}, {3,4}, {5,6}};

    8. 二维数组的使用

    8.1 二维数组的下标

    二维数组通过行下标和列下标来访问元素,行和列的下标都从0开始。

    语法格式:数组名[行下标][列下标]

    示例:

    #include <stdio.h>
    int main()
    {
    int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
    // 访问第2行第4列的元素,值为7
    printf("%d\\n", arr[2][4]);
    return 0;
    }

    输出结果:

    7

    8.2 二维数组的输入和输出

    使用双层for循环遍历二维数组:外层循环控制行,内层循环控制列。

    示例代码:

    #include <stdio.h>
    int main()
    {
    int arr[3][5] = {0};
    int i = 0;
    // 输入数据
    for(i = 0; i < 3; i++)
    {
    int j = 0;
    for(j = 0; j < 5; j++)
    {
    scanf("%d", &arr[i][j]);
    }
    }
    // 输出数据
    for(i = 0; i < 3; i++)
    {
    int j = 0;
    for(j = 0; j < 5; j++)
    {
    printf("%d ", arr[i][j]);
    }
    // 每行输出完换行
    printf("\\n");
    }
    return 0;
    }

    9. 二维数组在内存中的存储

    通过打印二维数组所有元素的地址,可观察其内存存储规律。

    示例代码:

    #include <stdio.h>
    int main()
    {
    int arr[3][5] = { 0 };
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++)
    {
    for (j = 0; j < 5; j++)
    {
    printf("&arr[%d][%d] = %p\\n", i, j, &arr[i][j]);
    }
    }
    return 0;
    }

    输出结果分析:

  • 同一行内相邻元素的地址差值为4个字节
  • 跨行元素(如arr[0][4]和arr[1][0])的地址也相差4个字节
  • 结论:二维数组在内存中也是连续存放的
  • 10. C99中的变长数组

    10.1 传统数组的限制

    C99标准之前,数组的大小必须用常量或常量表达式指定,无法使用变量,灵活性不足。

    // 合法
    int arr1[10];
    int arr2[3+5];
    // 合法(初始化时省略大小)
    int arr3[] = {1,2,3};

    10.2 变长数组的特性

    C99引入变长数组(VLA),允许使用变量指定数组大小,数组长度在运行时确定。

    int n = 5;
    // 变长数组,n的值决定数组大小
    int arr[n];

    注意事项:

  • 变长数组的大小一旦确定就不能修改
  • 变长数组不能进行初始化
  • VS2022不支持变长数组,GCC编译器支持
  • 示例代码(GCC下运行):

    #include <stdio.h>
    int main()
    {
    int n = 0;
    scanf("%d", &n);
    int arr[n];
    int i = 0;
    // 输入数据
    for (i = 0; i < n; i++)
    {
    scanf("%d", &arr[i]);
    }
    // 输出数据
    for (i = 0; i < n; i++)
    {
    printf("%d ", arr[i]);
    }
    return 0;
    }

    11. 数组练习

    11.1 练习1:多个字符从两端移动,向中间汇聚

    功能:演示字符串从两端向中间逐步显示的效果

    #include <stdio.h>
    #include <string.h>
    // Sleep函数需要的头文件,Windows系统下使用
    #include <windows.h>
    int main()
    {
    char arr1[] = "welcome to bit…";
    char arr2[] = "#################";
    int left = 0;
    int right = strlen(arr1)1;
    printf("%s\\n", arr2);
    while(left<=right)
    {
    // 休眠1秒
    Sleep(1000);
    arr2[left] = arr1[left];
    arr2[right] = arr1[right];
    left++;
    right;
    printf("%s\\n", arr2);
    }
    return 0;
    }

    11.2 练习2:二分查找

    功能:在升序整型数组中高效查找指定值,找到返回下标,否则提示找不到

    #include <stdio.h>
    int main()
    {
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    int left = 0;
    int right = sizeof(arr)/sizeof(arr[0])1;
    // 要查找的数字
    int key = 7;
    // 记录中间元素下标
    int mid = 0;
    // 标记是否找到
    int find = 0;
    while(left <= right)
    {
    // 计算中间下标,避免left+right溢出
    mid = left + (right left) / 2;
    if(arr[mid] > key)
    {
    // 目标值在左半区间
    right = mid1;
    }
    else if(arr[mid] < key)
    {
    // 目标值在右半区间
    left = mid+1;
    }
    else
    {
    // 找到目标值
    find = 1;
    break;
    }
    }
    if(1 == find)
    printf("找到了,下标是%d\\n", mid);
    else
    printf("找不到\\n");
    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » C语言从入门到进阶——第5讲:数组
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址