Blog Detail

  • 【C语言】数组你真的会用了吗?(关于数组的创建、初始化和使用)

    一、数组的概念

    数组:一组相同类型元素的集合

    数组的元素个数不能为0同一个数组内的元素类型是相同的

    数组分为一维数组和多维数组,多维数组中二维数组最为常见,所以本文主要介绍一维数组和二维数组的使用

    二、一维数组

    1. 一维数组的创建

    类型说明符 数组名 [常量表达式]

    类型说明符 指定数组的元素类型,可以为 int、double、char等,也可以为自定义的类型[常量表达式] 指定数组的大小,即数组中所包含的元素个数,一般根据实际需求设置,表达式可为常量或符号常量,但一定不能为变量( 如:int arr[x])数组名 可以为数组命名

    例如,我想创建一个放200个int类型的元素的数组,名字为arr,就可以这样写

    int arr[200];

    也可以创建其他类型的数组:

    char str[5];

    double maximum [10];

    2. 一维数组的初始化

    定义数组时给数组赋值,称为数组的初始化。

    初始化有下面几种情况:

    (1)全部初始化

    int arr[4] = {0,1,2,3,};//{}中的元素个数不可以超过[]中的常量值

    (2)部分元素赋初值

    int brr[10] = {0,1,2,3,4};//前五个元素依次赋值,其他未赋值元素默认为0

    (3)全部元素赋0

    int crr[3] = {0,0,0};

    也可以写成:

    int crr[3] = {0};

    (4)对所有数组元素赋初值时,可以不指定数组长度

    int arr[] = {0,1,2,3,4};//这个数组的长度为{}中元素的个数,即arr数组的大小为5

    3.一维数组的使用

    数组定义好后就可以使用它了,但不能一次性引用整个数组,只能引用单个数组元素。这个时候我们为了方便访问和操作数组中的元素,于是就有了数组的下标。

    3.1 数组的下标

    引用数组元素的形式为:

    数组名[下标]

    下标的意义:数组下标是一个整数,用于访问数组中的特定元素。通过下标,我们可以直接访问、读取或修改数组中的元素。下标的范围:数组下标的取值范围是从0到n-1,其中n是数组的长度。这意味着在C语言中,数组的最大下标是元素个数减1。下标的连续性:由于数组在内存中是连续存储的,所以数组下标也是连续的。这允许我们通过循环等方式遍历整个数组,并对每个元素进行处理。

    有了数组的下标,如果我有一个长度为N的数组,我想访问下标为2的元素,我就可以使用arr[1],只要想访问下标为a(a为任意小于N的常数),我就可以使用arr[a-1]。

    #include

    int main()

    {

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

    printf("%d\n", arr[0]);//输出1

    printf("%d\n", arr[6]);//输出7

    return 0;

    }

    运行结果

    3.2 打印数组的元素

    现在我们已经知道了如何访问数组中单个元素了,那我们如果想要访问整个数组的内容,那怎么办呢?

    其实,我们只需要把数组从第一个元素访问到最后一个,不就是访问整个数组了吗,那我们应该怎么访问呢?最常用的方法就是使用for循环(while循环也可以),产生从0到n-1的下标,如何使用下标进行访问就可以了。

    #include

    int main()

    {

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

    int i = 0;

    for (; i < 10; i++)

    {

    printf("%d ", arr[i]);

    }

    return 0;

    }

    运行结果:

    3.3 数组的输入

    如果我们定义了一个数组之后,我们该如何给数组输⼊想要的数据呢?

    在C语言中,给数组输入数据通常是通过循环结构来实现的,如for循环或while循环。

    #include

    int main() {

    int arr[5];

    printf("请输入5个数字:\n");

    for(int i = 0; i < 5; i++) {

    scanf("%d", &arr[i]);

    }

    return 0;

    }

    4. 一维数组的应用

    讲了太多的知识点,现在给出几个例子,来让我们更加深刻地体会一维数组如果使用吧。

    【例1】输入20个整数,然后逆序将这20个数打印出来

    对于这个例子,我们可以定义一个长度为20的数组arr来存放输入的20个数,然后再将数组arr中的内容逆序输出即可。

    #include

    int main()

    {

    int arr[20];

    int i = 0;

    for (; i < 20; i++)

    {

    scanf("%d", &arr[i]);

    }

    for (i = 19; i >= 0; i--)

    {

    printf("%d ", arr[i]);

    }

    return 0;

    }

    输出结果:

    【例2】输出n个数(n <= 1000),存放在数组arr[1] 到 arr[n] 中,输出最大数以及其所在的位置

    输入样例:

    5

    22 25 63 78 90

    输出样例:

    90 5

    #include

    int main()

    {

    int arr[1001] ;//n<=1000,所以数组最大长度为1001

    int i = 0, n;

    scanf("%d", &n);//输入数组的实际大小

    for (i = 1; i <= n; i++)

    {

    scanf("%d", &arr[i]);

    }

    int max = arr[1],m = 1;//为最大值和对应位置赋初始值

    for (i = 2; i <= n; i++)

    {

    if (max < arr[i])

    {

    max = arr[i];

    m = i;

    }

    }

    printf("%d %d", max, m);//输出

    return 0;

    }

    这个例子看完之后,可以再想想如何从一组数据找到最小值及其所在位置?我们可以试着写一写,由于思路写法与上面类似,这里我就不给出代码了。

    【例3】将输入的10个数自动从小到大排序然后输出

    这个例子我们可以使用冒泡排序(Bubble Sort)来解决

    冒泡排序的算法:

    比较相邻的两个元素如果第一个比第二个大,就交换他们两个对每一对相邻的元素作上述步骤,从开始到结尾,这个时候一组数中的最大值会被放到最后一位再除去最后一个数字,对剩下的数字继续进行1-3的步骤,然后再持续这个过程,大的数字就会被一个一个顶到后面去,直到只剩下最后一对数字也不需要交换时,这组数字就这样被排好了

    冒泡排序的名字来源于其工作方式,就像碳酸饮料中的气泡最终会上浮到顶端一样,较大的元素会慢慢“浮”到数列的后面,完成排序。

    冒泡排序是一种稳定排序算法,因为它在排序过程中保持相同元素的相对顺序不变。它的时间复杂度是O(n²),这意味着对于含有n个元素的序列,最多需要进行n(n-1)/2次比较操作。

    冒泡排序的一个关键特征是,它重复地遍历要排序的元素列表,比较每对相邻的元素,并交换它们(如果需要),直到没有更多的交换需要执行。这通常通过两个嵌套循环实现,外循环控制遍历次数,内循环负责执行实际的比较和交换操作。

    好了,弄清楚了冒泡排序,现在让我们来写这段代码吧

    #include

    int main()

    {

    int arr[10];

    int i = 0;

    for (; i < 10; i++)

    {

    scanf("%d", &arr[i]);

    }

    for (i = 0; i < 9; i++)

    {

    int j = 0;

    for (j = 0;j < (9 - i); j++)

    {

    int t = 0;

    if (arr[j] > arr[j + 1])

    {

    t = arr[j];

    arr[j] = arr[j + 1];

    arr[j + 1] = t;

    }

    }

    }

    for (i = 0; i < 10; i++)

    {

    printf("%d ", arr[i]);

    }

    return 0;

    }

    运行结果:

    好了,如果你看到了这里,上面三个例子是否让你知道一维数组怎么使用了呢?

    现在,我再给出一个例子,你可以试试着写一写,代码我会在本文的最后再给出,好了,来试试看吧!

    【例4】从键盘输入若干整数(数据个数应少于50),其值在0-4的范围,用-1作为输入结束的标志。统计每个整数的个数。

    三、二维数组

    1.二维数组的创建

    二维数组其实就是具有两个下标的数组,它是一种特殊的一维数组,其每个元素都是一个一维数组。二维数组也可以被看作是一个表,其有行和列。

    二维数组我们可以这样来定义:

    类型说明符 数组名[常量表达式1] [常量表达式2]

    常量表达式1 :行的长度 常量表达式2 :列的长度二维数组的大小 = 常量表达式1 * 常量表达式2 (元素总个数等于行数x列数)

    int arr[3][3];//定义一个3行3列的二维整型数组,元素个数为3*3=9

    char str[7][6];//定义一个7行6列的二维字符型数组,元素个数为7*6=42

    既然我说有两个下标的的数组就是二维数组,那么拥有多个下标的数组不就是多维数组了吗,又根据上面一维数组和二维数组定义的相似,我们不难想出三维数组、四维数组的建立。

    int [1][2][3];

    int [1][2][3][4];

    多维数组的引用赋值等操作与二维数组类似,但三维以上的数组很少用,因为这些数组需要占用大量的存储空间。

    2. 二维数组的初始化

    二维数组的初始化可以有下面几种操作:

    (1)分行初始化

    int arr[2][3] = { {0,1,2},{3,4,5} };//第一行为{0,1,2},第二行为{3,4,5}

    前面也说了,二维数组的元素就是一维数组,所以就可以像这样,以一维数组为元素用{ }括起来,这个几行也可以看成几个元素(即几个一维数组),几列可以看成表示的是这个一维数组的大小

    (2)按行顺序一次性初始化

    int arr[2][3] = { 0,1,2,3,4,5 };//这个数组与上面的数组是相等的

    (3)部分初始化(不完全初始化,即只给数组中的部分元素赋初始值)

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

    //相当于:

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

    因为之前一维数组的初始化我们知道:未赋值的元素系统默认为0,而一维数组赋值会从前开始依次赋值。

    (4)省略行下标的初始化

    对二维数组初始化时,行标可以省略,但列标一定不能省略!

    int arr[][3] = { 0,1,2,3,4,5 };//这是一个2行3列的数组

    //相当于:

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

    int brr[][3] = {{0},{1,2},{3,4,5}} ;//这是一个3行3列的数组

    //相当于:

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

    3. 二维数组的使用

    二维数组元素访问的一般形式:

    数组名[行下标][列下标]

    这个其实我感觉与一维数组的使用也是类似的,二维数组的行标和列标都是从0开始的,如果我们定义时行下标有N个,那么行下标取值范围就是1~N-1,列下标类似。

    二维数组中各个数组元素在内存中的存储顺序是“按行优先原则顺序存放”,就是先从第一行第一个开始存放,第一行存放完,再从第二行开始第一个开始,直到最后一个最后一行。而且⼆维数组中的每个元素都是连续存放的。

    数组元素可以与变量一样,能进行各种运算

    #include

    int main()

    {

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

    arr[0][2] = 9;

    arr[0][0] = 11;

    arr[1][2] = arr[1][0] + arr[0][1];

    int i, j;

    for (i = 0; i < 2; i++)//输出每一行

    {

    for (j = 0; j < 3; j++)//输出每行的每个元素

    {

    printf("%d ", arr[i][j]);

    }

    }

    return 0;

    }

    运行结果:

    4. 二维数组的应用

    【例5】矩阵的转置,在键盘上输入一个4*3的矩阵,将其转换成3*4的矩阵输出

    输入样例: 输出样例:

    1 2 3 1 4 7 0

    4 5 6 2 5 8 1

    7 8 9 3 6 9 2

    0 1 2

    #include

    int main()

    {

    int arr[4][3];

    int i, j;

    for (i = 0; i < 4; i++)//输入矩阵

    {

    for (j = 0; j < 3; j++)

    {

    scanf("%d", &arr[i][j]);

    }

    }

    printf("\n");

    for (i = 0; i < 3; i++)//输出矩阵

    {

    for (j = 0; j < 4; j++)

    {

    printf("%d ", arr[j][i]);

    }

    printf("\n");

    }

    return 0;

    }

    运行结果:

    【例6】求矩阵的对角线之和,键盘先输入N(其中N <= 100),再输入一个N*N矩阵,然后输出矩阵正对角线和负对角线之和。

    #include

    int main()

    {

    int arr[100][100];

    int N;

    scanf("%d", &N);

    int i, j;

    for (i = 0; i < N; i++)

    {

    for (j = 0; j < N; j++)

    {

    scanf("%d", &arr[i][j]);

    }

    }

    int a = 0, b = 0;

    for (i = 0; i < N; i++)

    {

    a += arr[i][i];//正对角线从第一行第一个开始,以后每个元素都在前一个基础是行列数+1

    b += arr[i][N - 1 - i];//负对角线从第一行最后一个开始,以后每个元素都在前一个

    } //基础上行+1,列-1

    printf("%d %d", a, b);

    return 0;

    }

    运行结果:

    【例4】

    #include

    int main()

    {

    int arr[50];

    int i,a=0,b=0,c=0,d=0;

    for (i = 0; i < 50; i++)

    {

    scanf("%d", &arr[i]);

    switch (arr[i])

    {

    case 1:a++; break;

    case 2:b++; break;

    case 3:c++; break;

    case 4:d++; break;

    }

    if (arr[i] == -1)

    break;

    }

    printf("1的个数:%d\n2的个数:%d\n3的个数:%d\n4的个数:%d\n", a, b, c, d);

    return 0;

    }

    运行结果:

    好了,到这里全文就结束啦~

    ps:博主水平有限,文中可能会存在错误和不足之处,望各位大佬批评指正。