小白学习笔记(数组)

概念:

数组,是指多个相同类型的数据,按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。

数组中的概念:

数组名

下标(索引)【下标从零开始】

元素

数组的长度

数组的特点:

1.数组中的元素在内存中是依次紧密排列的,有序的。

2.创建数组对象会在内存中开辟一整块连续的空间,占据的空间的大小,取决于数组的长度和数组中元素的类型。

3.我们可以直接通过下标的方式调用指定位置的元素。

4.数组,一旦初始化完成,其长度就是确定的。数组的长度一旦确定,就不能再修改。

5.数组名中,引用的是这块连续空间的首地址。

数组的分类:

一维数组:存储一组数据

二维数组:存储多组数据,相当于二维表,一行代表一组数据,每一行长度可以不同

高维数组…………

按数据类型分类:

int类型数组

char类型数组

double类型数组

……………………

一维数组的定义方式:

int arr [10];(数组arr,里面包含10个元素,每个元素都是int类型)

或者:

#define NUM 10

int arr 【NUM】;

数组元素的调用:

格式:

数组名[下标](数组名的下标从0开始)

数组角标越界:

关于长度:

数组的字节长度:

sizeof运算符会返回整个数组的字节长度。

比如:

#include<stdio.h>
int main() {
    int arr [10];
    printf("%zd",sizeof(arr));
    return 0;
}

输出为40

数组的长度:

#include<stdio.h>
int main() {
    int arr[20];
    printf("数组的长度为%zd\n",sizeof(arr)/sizeof(int));
    return 0;
}

输出为:数组的长度为20(注意中括号中的数字)

一维数组的遍历:

举例:

//声明长度为10的int类型的数组,给数组中的元素依次赋值0到9,并遍历数组中的所有元素
#include<stdio.h>
int main() {
    int arr[10];
    size_t length = sizeof(arr)/sizeof(int);
    for (int i =1;i <length;i++) {
        arr[i] = i;
        printf("arr[%d] = %d;\n",i,i);
    }
    printf("遍历一维数组的数据:\n");
    for (int i =0;i < length;i++) {
        printf("%d",arr[i]);
    }
    return 0;
}

数组的其他定义方式:

定义方式2:

数组可以在声明时,使用大括号,同时对每一个元素赋值。比如:

int arr[5] = {22,37,90,48,95};

变形1:

int arr[ ] = {22,37,90,48,95};

(即省略中括号中的数字)

变形2:

对数组部分元素赋初值,如果大括号里面的值,少于数组的元素数量,那么未赋值的元素自动初始化为0

比如:

int arr[5] = {10,20,30,0,0};

变形3:

将每一个元素都赋值0,比如:

int a[100] = {0};

变形4:

给特定位置的元素赋值:

int arr[10] = {[1]=5,[9]=35}(给第二位数字和最后一位数字赋值,未指定的索引位置自动赋0)

错误方式:

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

使用大括号时,大括号里的值不能多于数组的长度,否则编译时会报错

一维数组的内存分析:

注意事项:

C语言规定,数组变量一旦声明,数组名指向的地址就不可更改。这是因为声明数组时,编译器会自动为数组分配内存地址,这个地址与数组名时绑定的,不可更改的。

当数组定义之后,再用大括号重新赋值是不允许的,会报错。

比如:

变长数组:

数组声明的时候,数组长度除了使用常量,也可以使用变量或者表达式来指定数组的大小,这叫做变长数组。

方式一:

例如:

int n = 10;

int arr[n];

这种方式只有在运行时才确定数组长度。

任何长度需要运行时才能确定的数组,都叫变长数组,例如:

int i = 10;

int ai[i];

int a2[i +5];

int a3[i +k];

注意:变长数组在c99标准中被引入,某些编译器可能不支持变长数组,或者有特定的限制

//在c99标准中,支持变长数组,例如:

int length = 10;

int arr[length];

int arr2[length + 5];

方式二:

使用malloc()函数来创建动态大小的数组

看不懂,等学了指针再看看

一维数组的练习:

数值型数组特征值统计:

举例1:

//声明长度为10的int类型的数组,包含十个元素,然后求出数组的最大值,最小值,总和,平均值,并输出
#include "stdio.h"
int main() {
    int i,max, min,total = 0;
    double average;
    int arr[10] = {132,12313,4124,31231,123123,12314,4123432,24523523,134231,254235};
    min = arr[0];
    max = arr[0];
    for (i = 0; i < sizeof(arr)/sizeof(int);i++) {
        if(arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }total +=arr[i];
    }
    average = total/10.0;
    printf("最大数是%d\n",max);
    printf("最小数是%d\n",min);
    printf("总和是%d\n",total);
    printf("平均数是%.2lf\n",average);
    return 0;
}

举例2:评委打分

#include<stdio.h>
int main() {
    int min,max,i,total =0;
    double average;
    int arr[] = {5,4,6,8,9,0,1,2,7,3};
    max = arr[0];
    min = arr[0];
    for (i = 0;i < sizeof(arr) / sizeof(int);i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
        if (arr[i] < min) {
            min = arr[i];
        }
        total += arr[i];
    } 
    average =(total - max - min + 0.0)/(sizeof(arr) / sizeof(int)-2);
    printf("平均数是%.2lf\n",average);

    return 0;
}

数组的复制:

由于数组名是指针,所以复制数组名不能简单得复制数组名

错误示范:

int a[3]={10,20,30}

int *b;

b = a;

上述写法结果不是将数组a赋值给数组b,而是让a和b指向同一个数组。

正确写法1,使用循环:

复制数组最简单的方法,将数组元素逐个进行复制,比如将数组a的成员逐个复制给数组b

举例:

//测试一维数组的复制
#include<stdio.h>
#define LENGTH 3
int main() {
    int arr1[LENGTH] ={10,20,30};
    int arr2[LENGTH];
    int i;
    for (i = 0; i < LENGTH; i++) {  //使用循环遍历arr1,同时给arr2中的元素赋值
        arr2[i] = arr1[i];
        printf("%d  ",arr2[i]);
    }

    return 0;
}

正确方式2,使用memcpy()函数:

memcpy()函数定义在头文件string.h中,直接把数组所在的那一段内存,再复制一遍。

3个参数依次为:目标函数,源数组,要复制的字节数

举例:(注意第三个参数是要复制的字节数,要乘sizeof(int))

//测试一维数组的复制
//memcpy函数3个参数依次为:目标函数,源数组,要复制的字节数
#include<stdio.h>
#include<string.h>
int main() {
    int arr1[3] = {10,20,30};
    int arr2[3];
    //使用memcpy函数复制数组1到数组2
    memcpy(arr2,arr1,3 * sizeof(int));
    //打印数组2的内存
    printf("复制后的数组2:");
    for (int i = 0;i < 3;i++) {
        printf("%d  ",arr2[i]);
    }
    return 0;
}

两种方式对比:

循环复制:

优点:简单直观,不需要引入头文件

缺点:需要遍历然后逐个赋值,不适合大型数组或复杂数据结构

memcpy函数复制:

优点:快速高效,适用于大型数组和复杂数据结构的复刻,不需要遍历

缺点:要引入头文件,对应简单的数组复制,可能过于繁琐

数组元素的反转:

数组对称位置的元素互换

反转方式1

举例:

//一维数组的反转,就是arr[i]和arr[arr.length-1-i]这两个位置互换
#include<stdio.h>
int main() {
    //定义一个数组
    int arr[10] = {1,2,3,4,5,6,7,8,9,0};
    int i;
    //获取数组的长度
    size_t length = sizeof(arr) / sizeof(int);
    //arr[i] 和 arr[arr.length-i-1]这两个位置的元素互换
    //反转位置
    for (i = 0;i < length / 2;i++) {
        //不管奇数还是偶数,判断的范围都是length / 2
        int temp = arr[i];
        arr[i] = arr[length - i -1];
        arr[length - i - 1] = temp;
    }
    //遍历反转后的数组
    for (i = 0;i < length;i++) {
        printf("%d  ",arr[i]);
    }

    return 0;
}

char型数组与字符串(难点):

数组元素的数据结构类型为char型的数组

一方面,可以看作普通数组,和上述一致,如:

char arr[]={'a','b','c','d'};

另一方面,字符型数组可以用来存储字符串。

字符串的使用:

由双引号括起来的一串字符称为字符串。

“”被称为空串,什么也没有;“ ”被称为空格串,是包含一个空格字符的字符串。两者不相等。

C语言没有专门用于存储字符串的变量类型,字符串都被存储在char类型的数组中。在字符串结尾,C语言会自动添加一个‘\0’的转义字符作为字符串结束的标志,所以字符数组也必须以‘\0’字符结尾

声明方式1(标准写法):

显示以‘\0'为最后一个字符元素结尾

char str[] = {'h','e','u','i','k','\0'};

如果一个字符数组的声明如下:

char str[10];

那么,由于必须留一个位置给\0,所以这个数组最多只能容纳9个字符的字符串

声明方式2(简化写法):

C语言中,双引号之中的字符,会被自动视为字符数组。

举例

//自动在末尾添加‘\0'字符。
char str1[12] = {"Hello World"};//注意使用双引号,不是单引号
//或者
char atr2[12] = "hello world";//可以省略一对{}来初始化数组元素

方式3(进一步简化):

char str3[] = {"Hello World"};

省略括号中的数字

字符串对应数组的长度:

上述数组的长度不是11,而是12.

字符串的长度:

字符串的长度不包括最后的\0,,所以上述的字符串长度为5.

数组nation前5个元素为C,h,i,n,a,第六个元素是\0,后四个元素也是\0

区分‘\0’,0,‘0’:

字符'\0'不同于字符'0',前者的ASCII码的是0,后者的ASCII码是48

练习1:

比较"x"和'x'

书写形式不同:字符串常量用的是双引号,字符常量用的是单引号

存储空间不同:字符串常量存储时自动加一个结束标志\0,“x”占用2个字节;字符常量只占用一个字节的存储空间,‘x'只占用1个字节

操作也不同:可以对字符常量进行加减运算,字符串常量则不能(假设存储手机号时,就可以存储到字符串中)

多维数组:

二维数组:

对于二维数组的理解,可以看做是由一维数组嵌套而成的,即一维数组array1又作为另一个一维数组array2的元素而存在。

定义方式:

int a[3][4];(可以理解为二维数组由三个一维数组构成,他们的数组名分别为a[0],a[1],a[2]。这三个一维数组各有4个元素。二维数组a共有3*4=12个元素)

如图:

二维数组,常称为矩阵,把二维数组写成行和列的排列形式,可以形象化地理解二维的数组的逻辑结构

三维数组:

int a[3][4][5];(是几维数组就带几个括号)

错误的声明方式

float a[3,4];

(一个中括号内不能写两个下标)

二维数组的内存分析:

在内存中,各元素是连续存放的,不是二维的,是线性的。

C语言中,二维数组中元素排列的顺序是按行存放的

举例:

关于长度:

printf("%zu\n",sizeof(a));//获取二维数组所占用的字节数,输出为48
printf("%d",sizeof(a)/ sizeof(int));//获取二维数组元素个数,输出为12

成员的调用:

格式:

数组名[下标][下标]

和一维数组一样,多维数组的第一个元素也是从0开始的

举例1:

给指定位置的元素赋值

举例2:

查看元素地址:

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

其他的定义方式:

定义方式2:

声明与初始化同时进行

举例:

#include<stdio.h>
int main() {
    int arr[3][4] = {{1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12}};
    return 0;
}

定义方式3:

多维数组也可以仅为指定的位置进行初始化赋值,其余未赋值的成员会自动设置为零

举例:

定义方式4:

多维数组也可以使用单层大括号赋值,不管数组有多少维度,在内存里都是线性存储,对于a[2][2]来说,a[0][0]后面是a[0][1],再后面是a[1][0],以此类推

定义方式5(在4的基础上简化):

如果对全部元素赋值,那么第一行的长度可以不给出

错误的定义方式:

行可以省略,列不能省略

举例:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值