C语言:数组的概念


前言

这一小节呢,开始对C语言的数组进行讲解,从一维数组开始出发,接着讲解二维数组,对数组的概念进行一个简单的认识。


一、一维数组

1.1 数组的创建

  • 所谓数组,数组就是一组相同类型的元素的集合。
  • 数组的创建方式如下所示:
type_t  arr_name  [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小

数组创建的实际例子:

//代码1
int arr1[10];
//代码2
int count = 10;
int arr2[count];//数组时候可以正常创建?
//代码3
char arr3[10];
float arr4[1];
double arr5[20];

需要注意的一点:当我们创建数组的时候,[ ]里面必须要给一个常量值才可以表示,不可以使用变量。在C99之后才支持变长数组的概念,数组的大小可以使用变量指定,但是数组不可以初始化。


1.2 数组的初始化

  • 数组的初始化:就是在数组创建的同时给数组里面的内容设定一些合理的初始值。

举个例子就是:

int main()
{
    int arr1[10];  // 创建一个大小为10的int类型数组
    char arr2[20]; // 创建一个大小为20的char类型数组
    float arr3[1]; // 创建一个大小为1的float类型数组
    double arr4[] = {0}; // 创建一个不指定大小的double类型数组(需要初始化)
 
    return 0;
}

字符数组的初始化

int main()
{
    char ch1[5] = {'b', 'i', 't'};
    char ch2[] = {'b', 'i', 't'};
 
    char ch3[5] = "bit";  // 'b', 'i', 't', '\0', '0'
    char ch4[] = "bit";  // 'b', 'i', ''t, '\0'
 
    return 0;
}

字符数组初始化的两种写法:

如果字符数组带上双引号 " " 一般会自己带上 \0 。 花括号内部需要自己加上 \0 。

int main()
{
    char ch5[] = "bit"; // b, i, t, \0      【自带斜杠0】
    char ch6[] = {'b', 'i', 't'}; // b i t  【不自带斜杠0】
    printf("%s\n", ch5);
    printf("%s\n", ch6);
 
    return 0;
}

没有 \0的时候,strlen读取的字符的时候不会知道什么时候结束,strlen:遇到 \0的时候就会自动停止。

int main()
{
    char ch5[] = "bit"; // b, i, t, \0      【自带斜杠0】
    char ch6[] = {'b', 'i', 't'}; // b i t  【不自带斜杠0】
    printf("%d\n", strlen(ch5));
    printf("%d\n", strlen(ch6));
 
    return 0;
}

在这里插入图片描述
当然,如果我们手动加上一个 \0的话,这样子就不会是随机值了;

int main()
{
    char ch5[] = "bit"; // b, i, t, \0      【自带斜杠0】
    char ch6[] = {'b', 'i', 't', '\0'}; // b, i, t, + '\0' 【手动加上斜杠0】
    printf("%d\n", strlen(ch5));
    printf("%d\n", strlen(ch6));
 
    return 0;
}

这样的话,运行的结果就是3 3了。


1.3 数组的使用

  • 下标引用操作符:[ ] ,即数组访问操作符;

  • 来举一个简单的例子来看一看就知道了:

  • 打印一组数组

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int sz = sizeof(arr) / sizeof(arr[0]);
 
    int i = 0;
    for(i = 0; i < sz; i++)
        printf("%d ", arr[i]);
    
    return 0;
}

在这里插入图片描述
总结:
① 数组的访问是通过下标来访问的,下标是从0开始的。
② 可以通过计算来得到数组的大小。


1.4 数组的存储

接下来按地址的格式打印:%p 十六进制的打印。
在这里插入图片描述
一维数组的存储方式:

int main()
{
    int arr[10] = {0};
    
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);
    for(i = 0; i < sz; i++)
        printf("&arr[%d] = %p\n", i, &arr[i]);
 
    return 0;
}
 

运行的结果如下图所示:
在这里插入图片描述
仔细观察输出的结果可以知道:随着数组下标的增长,元素的地址也在有规律的变化。
结论:数组在内存当中是连续存放的
在这里插入图片描述


二、二维数组

2.1 二维数组的创建

二维数组的创建如图所示:

在这里插入图片描述
二维数组的创建:

int main()
{
    int arr[3][4];     // 创建一个3行4列的int型二维数组;
 
    /*
        0 0 0 0
        0 0 0 0
        0 0 0 0
    */
 
    char arr[3][5];    // 创建一个3行5列的char型二维数组;
    double arr[2][4];  // 创建一个2行4列的double型二维数组;
 
    return 0;
}

2.2 二维数组的初始化

初始化:在创建数组的同时要给数组的内容设置一个合理的初始值;

注意的事项:

  • 二维数组在初始化的时候,行可以省略,但是列绝对不可以省略;
  • 二维数组在内存当中也是连续存放的;

初始化演示:

int main()
{
    int arr[3][4] = {1,2,3,4,5};
    
    /*
        1 2 3 4
        5 0 0 0
        0 0 0 0
    */
 
    int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; // 完全初始化
    int arr2[3][4] = {1,2,3,4,5,6,7}; // 不完全初始化 - 后面补0;
 
    int arr3[3][4] = {{1,2}, {3,4}, {4,5}}; // 指定;
 
    /*
        1 2 0 0
        3 4 0 0
        4 5 0 0
    */
 
    return 0;
}

关于“行可以省略,但是列绝对不可以省略”

int main()
{
    int arr1[][] = {{2,3}, {4,5}};  // error
    int arr2[3][] = {{2,3}, {4,5}}; // error
    int arr2[][4] = {{2,3}, {4,5}}; // √
 
    return 0;
}

2.3 二维数组的使用

我们在打印二维数组的时候,同样是通过下标的方式,只不过相对于一维数组来说,在打印二维数组的时候一般利用两个for循环。

int main()
{
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 4; j++)
            printf("%d", arr4[i][j]); // 二维数组[行][列];
        printf("\n"); // 换行;
    }
}

二维数组在内存当中的存储

int main()
{
    int arr[3][4];
    int i = 0;
    int j = 0;
    for(i = 0; i < 3; i++) {
        for(j = 0; j < 4; j++)
            printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
    }
 
    return 0;
}

在这里插入图片描述

通过仔细观察输出的结果,我们可以发现二维数组在内存当中其实也是连续存放的;

因此我们可以得到这个结论:不论是一维数组还是二维数组,在内存当中都是连续存放的


三、数组作为函数传参

3.1 关于数组名

其实数组名就是数组首元素的地址(只有两个例外);

  • 例外1:sizeof(数组名),最后计算的是整个数组的大小
  • 例外2:&数组名,取出来的是整个数组的大小

验证:

int main()
{
    int arr[10] = {0};
    printf("%d\n", sizeof(arr));
 
    return 0;
}

最后输出的结果是 >> 40


3.2 冒泡排序

在这里插入图片描述
冒泡排序的核心思想:相邻的两两元素进行比较,如果满足条件则交换;

  1. 先确认总共需要的趟数;
  2. 写下来一趟冒泡排序的过程;
  3. 最后进行交换;

需要注意的一些点:

  1. int arr [ ] 本质是来讲依然是指针,int * arr;
  2. 数组在传递参数的时候,实际上传递的是数组的首元素地址;
  3. sz变量不能够在函数内部计算,需要在外部计算好了之后再传递进去;

例子:编写一个bubble_sort( ) 函数,升序排列,int arr [ ] = {9,8,7,6,5,4,3,2,1,0}

#include <stdio.h>
 
void bubble_sort (int arr[], int sz) // 形参arr本质上是指针 int* arr
{
    /* 确认趟数 */
    int i = 0;
    for(i = 0; i < sz; i++)
    {
        /* 一趟冒泡排序干的活 */
        int j = 0;
        for(j = 0; j <= (sz-1-i); j++) // -1:最后一趟不用排,-i:减去已经走过的趟
        {
            /* 如果前面数比后面数大,就交换 */
            if(arr[j] > arr[j + 1])
            {
                /* 创建临时变量交换法 */
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
 
int main(void)
{
    int arr[] = {9,8,7,6,5,4,3,2,1,0};
    int sz = sizeof(arr) / sizeof(arr[0]);
 
    /* 冒泡排序 */
    bubble_sort(arr, sz); // 数组传参的时候,传递的是首元素的地址
    
    /* 打印数组 */
    int i = 0;
    for(i=0; i<=sz; i++)
        printf("%d ", arr[i]);
 
    return (0);
}
 

最后输出的结果: 0 1 2 3 4 5 6 7 8 9

算法的优化:我们可以设置一个变量来判断数组是否有序,如果已经有序,则就不需要冒泡排序了。

#include <stdio.h>
 
void bubble_sort (int arr[], int sz)
{
    int i = 0;
    for(i = 0; i < sz; i++)
    {
        int j = 0;
        int falg = 1; // 标记1,假设这一趟冒泡排序已经有序
        for(j = 0; j <= (sz-1-i); j++)
        {
            if(arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                flag = 0; // 仍然不有序,标记为0
            }
        }
        if(flag == 1)
            break; // 已经有序了,就不需要再冒泡排序了
    }
}
 
int main(void)
{
    int arr[] = {9,8,7,6,5,4,3,2,1,0};
    int sz = sizeof(arr) / sizeof(arr[0]);
 
    /* 冒泡排序 */
    bubble_sort(arr, sz);
    
    /* 打印数组 */
    int i = 0;
    for(i=0; i<=sz; i++)
        printf("%d ", arr[i]);
 
    return (0);
}
 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值