鹏哥C语言55-57---二维数组+数组越界+数组传参(冒泡排序)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//---------------------------------------------------------------------------------------2.   二维数组的创建和初始化

//-------------------------------------------------------------------------------------------------2.1 二维数组的创建
// 1 2 3 4 
// 2 3 4 5
// 3 4 5 6

int main()
{
    int arr1[3][4]; // (3行4列)
    char arr2[5][10]; // (5行10列)
    double arr3[6][6]; // (6行6列)

    return 0;
}

//-------------------------------------------------------------------------------------------------2.2 二维数组的初始化

int main()
{
    int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 }; 
      // 1 2 3 4
      //  2 3 4 5
     //   3 4 5 6  
    int arr2[3][4] = { 1,2,3,4,2,3,4,5,3,4 };  // 如果元素不够,用0补齐(不完全初始化)
     //  1 2 3 4
     //  2 3 4 5
     //  3 4 0 0   
    int arr3[3][4] = { {1},{2,3},{3,4,5} };  // 可以再分组(不完全初始化)
    //  1 0 0 0
    //  2 3 0 0
    //  3 4 5 0   
    
   //二维数组  可以省略 行 数,不能省略 列 数
    int arr3[][4] = { {1,2,3,4},{2,3} }; //行数输入了几行,就是几行
    //  1 2 3 4
    //     2 3 0 0  

    return 0;
}

//-------------------------------------------------------------------------------------------------2.3 二维数组的使用
// 二维数组的使用也是通过下标的方式
//不管是 行 还是 列 都是从0开始访问

int main()
{
    //int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
    //----------------------------------------------------自己 输入一个 二维数组
    int arr1[3][4] = { 0 }; 

    int i = 0;
    for (i = 0; i <3; i++)
    {
        int j = 0;
        for (j = 0; j <4; j++)
        {
            scanf("%d", &arr1[i][j]);
        }
    }

    //---------------------------------------------------- 打印 整个 二维数组
    for (i = 0; i <= 2; i++)
    {
        int j = 0;
        for (j = 0; j <= 3; j++)
        {
            printf("%d ", arr1[i][j]);
        }
        printf("\n");
    }

    //--------------------------------------------------------打印数组中的某个元素
    printf("%d\n", arr1[2][2]); // 打印 3行 3列 位置的元素
    printf("%d\n", arr1[2][0]); // 打印 3行 1列 位置的元素

    return 0;
}

//可以把二维数组理解为由一维数组组成的数组
访问第一行元素 arr[0][j]
访问第二行元素 arr[1][j]
访问第三行元素 arr[3][j]

//-----------------------------------------------------------------------------------------2.4 二维数组在内存中的存储
// 打印出 二维数组中的地址

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

//二维数组在内存中也是 连续存放的,各相差4个字节(一个字符四个字节)
&arr1[0][0]=00000027016FF598
&arr1[0][1]=00000027016FF59C
&arr1[0][2]=00000027016FF5A0
&arr1[0][3]=00000027016FF5A4
&arr1[1][0]=00000027016FF5A8
&arr1[1][1]=00000027016FF5AC
&arr1[1][2]=00000027016FF5B0
&arr1[1][3]=00000027016FF5B4
&arr1[2][0]=00000027016FF5B8
&arr1[2][1]=00000027016FF5BC
&arr1[2][2]=00000027016FF5C0
&arr1[2][3]=00000027016FF5C4


//二维数组  可以省略行数,不能省略 列 数
// int arr[][4]={1,2,3,4,5,6};


//---------------------------------------------------------------------------------------------------------------3.数组越界
数组的下标是有范围限制的。
数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查。

//------------------------------------------------一维

int main()
{
    int arr1[] = { 1,2,3,4,5,6 };
    int sz = sizeof(arr1) / sizeof(arr1[0]); //用公式计算得到数组大小
    int i = 0;
    for (i = 0; i < sz; i++) //写 sz 避免出现数组越界访问
//    for (i = 0; i < 9; i++) // 数组越界
    {
        printf("%d ", arr1[i]);
    }
    return 0;
}

//-----------------------------------------------二维

int main()
{
    int arr1[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };

    int i = 0;
    for (i = 0; i <3; i++)
    {
        int j = 0;
        for (j = 0; j <4; j++)
    // for (j = 0; j <= 4; j++) //数组越界

        {
            printf("%d ", arr1[i][j]);
        }
        printf("\n");
    }
    return 0;
}

//--------------------------------------------------------------------------------------------------4.数组作为函数参数
//写代码时,常常会将数组作为参数传给函数。比如实现一个冒泡程序
//冒泡排序的核心思想,两个相邻的元素进行比较
//一趟冒泡排序让一个数据来到他最终应该出现的位置

//----------------------------------------------------------------------------------------4.1 冒泡排序函数的错误设计
//数组传参,形参有两种写法: 1.数组  2.指针

//-------------------------------------失败原因------------------------------------
数组传参传的是数组内元素的首地址
地址应该使用指针来接收
所以 这里的 形参 int arr[],表面上是数组,本质上是个指针变量
因此  sizeof(arr) 计算出来的就不是数组大小了,是指针大小4(x86环境)
sizeof(arr[0]) 也是4 
所以 sz 求出来为 1,导致冒泡失败
修改方法,把 sz 放到函数外部求,传到函数内部

void bubble_sort(int arr[], int sz)  // 1. 形参是数组形式:便于理解。 []数值可写可不写
//void bubble_sort(int* arr, int sz)   // 2. 形参是指针形式

{
    //确定需要多少趟冒泡排序(也就是数组元素个数-1)
    //int sz = sizeof(arr) / sizeof(arr[0]); //失败原因,解决方法就是sz 在外部求,传到内部 -----------0 1 2 3 4 5 6 7 8 9 -----冒泡成功
    int i = 0;
    for (i = 0; i < sz - 1; i++) //sz-1趟冒泡排序
    {
        //一趟冒泡排序
        int j = 0;
        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;
            }
        }
    }
}

//void bubble_sort(int* arr)  // 2. 形参是指针形式:
//{
//
//}

int main()
{
    //把数组内容排成升序
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    //冒泡排序算法,对数组进行排序
    //bubble_sort(arr); // 数组名本质是数组首元素的地址---------------------------失败原因
    bubble_sort(arr,sz); //数组传参,给数组名就行,把数组元素个数也传过去

    // 打印出来
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);  // 8 9 7 6 5 4 3 2 1 0-------------------------冒泡失败
    }
    return 0;
}

//------------------------------------------------------------------------------------------------4.2 数组名是什么?
//数组名确实能表示首元素的地址
//但是有两个例外
// 1. sizeof(数组名),  这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
// 2. &数组名,           这里的数组名也表示整个数组,取出的是 整个数组的地址
//除了这两种情况之外,以后见到的所有的  数组名arr, 代表的都是首元素地址

int main()
{
    int arr[10];
    printf("%p\n", arr);    // 打印数组名    arr 首元素的地址
    printf("%p\n", arr+1);
    printf("---------------------------------------\n");
    printf("%p\n", &arr[0]); //打印首元素地址
    printf("%p\n", &arr[0]+1);
    printf("---------------------------------------\n");
    printf("%p\n", &arr);    //  打印数组的地址
    printf("%p\n", &arr+1);
    // 000000148B8FFB78  //跳了4个字节,1个元素
    // 000000148B8FFB7C
    // -------------------------------------- -
    // 000000148B8FFB78 //跳了4个字节,1个元素
    // 000000148B8FFB7C
    // -------------------------------------- -
    // 000000148B8FFB78   //跳了40个字节,整个数组的10个字节
    // 000000148B8FFBA0

    int n = sizeof(arr);
    printf("%d\n", n);    // 算出 40,数组的大小,40个字节
    return 0;
}

//------------------------------------二维数组数组名的理解

int main()
{
    int arr[3][4];
    int sz = sizeof(arr); //计算整个元素的大小     12个元素,每个元素4个字节
    printf("%d\n", sz);  // 输出 48 (3*4*4)

    arr; // 二维数组的数组名 表示的是 第一行(首行) 的地址,不是0*0元素的地址
    printf("%p\n", arr);
    printf("%p\n", arr + 1);
    // 000000A2C0AFFCC8  跳过16个字节,4个元素,也就是跳过一行
    //    000000A2C0AFFCD8

    printf("%d\n", sizeof(arr) / sizeof(arr[0]));             //计算数组的行数(数组所有字节 / 数组每行的字节数)
    printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));  //计算数组的行数(数组首行字节数 / 数组一个字节数)

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值