数组(一)

各位小伙伴大家好,欢迎来到我的博文参观。今天学了数组,我就又来分享我今天所学的知识了,希望大家喜欢。下面时本文章的讲解思路。

一、一维数组

1.1一维数组的创建和初始化

数组是相同数据类型的有序数据的集合。其中的数据可以是int型、float型、char型、指针、结构体和共用体等类型。

数组的定义方式:

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

如以下代码:

注意:在vs编译器下不支持变长数组,变长数组的意思是方括号里面是一个变量。它的大小可以随变量的改变而改变,变长数组是c99标准所支持的概念,而在c99标准之前是没有这个概念的。

数组的初始化

完全初始化和不完全初始化

另外还需要注意,char类型数组的初始化,比如:把char arr[3] = {'a','b','c'},中的元素按字符串的形式打印出来,会发生什么。

我们可以看到,后面出现了乱码,那么为什么会出现这种情况呢,是因为,字符串打印碰到'\0'才会停止,而我们这里没有'\0',所以会一直越界访问,而编译器不知道后面存储的是什么,所以会出现乱码问题。

char类型的数组还可以这样来定义和初始化。

1.2一维数组的使用

我们在初识C语言中,介绍了[ ],下标引用操作符,该操作就是访问数组元素使用的。我们可以使用for循环来访问数组元素。代码如下:

注意:一维数组的下标识从0开始的,数组的大小可以通过计算得到:

十个整型类型的数据,每个整型占用内存大小为4个字节。所以,数组的大小为:4 * 10 = 40。

我们还可以通过以下方式去访问数组

这里的原来是,先把arr的地址赋给指针变量p,p就指向了一维数组的首元素地址,通过i自增1找到数组中第i个元素的地址,进行解引用打印。每次加1,会跳过4个字节的内存,这是由于此数组是整型。

1.3 一维数组在内存中的存储。

要研究这个问题,我们可以这样做,打印数组元素的地址。

这里会涉及到进制转换的问题,可以去看看这篇文章:

不同进制间转换

由以上图片可知,内存地址在有规律的递增,所以我们可以得出结论:数组在内存中是连续存放的。

数组内存图

二、二维数组

2.1二维数组的创建和初始化

数组创建格式如下:

类型名 数组名 [整型表达式][整型表达式]

二维数组的初始化

数组初始化见下图

画图解释arr3数组为什么只能省略行:

2.2二维数组的使用

二维数组的使用也是通过下标的方式。

由这张图我们可知,二维数组其实是一个有两个元素(只是举例)的一维数组,只不过它里面元素的类型是数组罢了。

这样我们就可以通过两层for循环来进行访问二维数组,第一层找到第一个一维数组的位置,第二层找到一维数组里的每一个元素

代码如下:

int main
{
    int arr1[2][3] = { 1,2,3,4,5,6 };
    int i = 0;
    int j = 0;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", arr1[i][j]);
        }
        printf("\n");
    }
    return 0;
}

运行结果:

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

我们还是可以使用打印地址的方式来讨论

我们把二维数组的每一行看作一个一维数组,那么每一行的一维数组也有数组名,如图所示:

三、数组的越界

数组的下标是由限制的,比如int arr[3]这个数组的下标范围是0~2,如果下标>2或者<0都会造成数组的越界。

C语言是不会检查数组下标越界的,这就需要程序员自己检查。

代码如下:

四、数组作为函数参数

这里我们先学习一个算法:冒泡排序算法。升序

4.1冒泡排序的错误设计

错误的代码如下:

void bubble_sort(int arr[])
{
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    int j = 0;
    //控制趟数
    for (i = 0; i < sz - 1; i++)
    {
        //控制每趟的比较次数
        for (j = 0; j < sz - i - 1; j++)
        {
            if (arr[j] > arr[j+1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
    bubble_sort(arr);
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

运行结果:

我们发现数组竟然原样输出了,那么这是怎么回事呢,我们通过调试来分析。

要理解这里的内容,我们需要了解下一节内容。

4.2数组名是什么?

请看如下代码:

所以我们可以得出数组名=数组首元素地址。

但是有两种情况除外

  • sizeof(数组名),计算的是整个数组的大小,现在的arr表示的是整个数组。

  • &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。

如下图所示:

我们再来看:

&arr取出整个数组的地址。

4.3冒泡排序函数的正确设计

当数组传参的时候,是把数组首元素地址传过去了,形参int arr[ ]表示的依然是一个指针:int* arr。

所以函数里面的sizeof就等于1或者2。需要改进冒泡排序,我们可以把sz放到主函数里求值,

然后作为函数参数传进去就可以了。

void bubble_sort(int arr[],int sz)
{
    int i = 0;
    int j = 0;
    //控制趟数
    for (i = 0; i < sz - 1; i++)
    {
        //控制每趟的比较次数
        for (j = 0; j < sz - i - 1; j++)
        {
            if (arr[j] > arr[j+1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr,sz);
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

运行结果:

可以看到排序完成。

第五部分内容会单独写一篇文章介绍,大家敬请期待!!!

各位小伙伴,今天就介绍到这里,我们下期见。请大家点点赞,谢谢大家了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值