009-数组-C语言笔记

/ 0评 / 0

数组的声明

作用:

可以存储指定数据类型指定个数的数据,数组与我们之前学习的变量最大的不同就是我们之前的变量只能存储一个数据,而我们的数组可以存储多个数据。

特点:

1.可以存储多个数据

2.虽然数组可以存储多个数据,但是并不是什么类型的数据都可以存储的。要求存储在数组中的数据的类型要一致,在创建数组的时候指定可以存储的多个数据的类型。

3.虽然数组可以存储多个数据,但不是任意个都能直接往里面存储的,数组之中可以存储的数据的个数是固定的,也是在创建数组的时候指定的,一旦指定,不能改变。

4.存储在数组之中的数据非常方便管理,拿到数组就可以很方便的拿到数组之中的数据

术语:

1.元素:数组中的每一个小空间,就叫做数组的元素。

2.下标/索引:数组之中有很多元素,为了区分每一个元素,C语言就为每一个元素编了一个号,这个号就叫这个元素的下标/索引。下标/索引从0开始递增。

3.长度:元素的个数。

语法:数组元素的数据类型 数组名[数组长度];

int main() {
    int arr1[5];       //可以存储5个int类型的数据
    float arr2[8];     //可以存储8个float类型的数据
    double arr3[29];   //可以存储29个double类型的数据
    char arr4[3];      //可以存储3个char类型的数据
    return 0;
}

注意:

1.声明数组的时候必须要指定数组的长度!

2.数组的长度可以为0,表示一个数据都不能存储,数组长度也可以为1,表示只能存储一个数据,但长度不能给负数和小数。

3.数组长度可以是常量,变量,宏,表达式。但是长度一旦声明,长度就不能改了。

4.当数组长度为变量的时候,是不能在声明数组的同时为数组元素初始化值的。只能先声明数组,然后再为元素赋值。

数组元素的赋值和调用

数组真正用来存储数据的是数组中的元素,而不是数组本身,数组指的是整个数组,所以我们不能直接为数组赋值。所以我们应该将数据赋值给数组中的元素。数组之中有多个元素,元素的本质其实就是一个普通类型的变量。那我们如何确定是为哪个元素赋值呢?

赋值语法:数组名[元素的下标] = 数据;

int arr[3];     //声明一个int类型的数组
arr = 10;       //错误,不能直接为数组赋值
arr[0] = 10;    //正确,为数组第一个元素赋值1
arr[0] = 11;    //正确,元素本质就是普通变量,可以重复赋值
arr[3] = 10;    //错误,元素个数是3,但下标最大才2.数组下标不能越界

调用语法:数组名[元素下标];

int arr[3];         //声明一个int类型的数组
arr[0] = 10;        //为元素赋值
int num = arr[0];   //将第一个元素的值取出赋值给int类型的变量num
int num1 = arr[3];  //下标越界,取不到想要的值

数组的初始化

在声明数组的同时就初始化数组之中的每一个元素的值。

int arr[3] = {1,2,3};       //注意不要越界
int arr1[] = {1,2,3};       //如果没有指定元素个数,初始化的时候,后面有多少个数据,C语言就自动确定数组个数
int arr2[3] = {1};          //部分初始化.将第一个元素初始化为1,其他元素初始化为0
int arr3[3] = {1,2};        //部分初始化,依次从第一个元素初始化,不够的元素初始化为0
int arr4[3] = {[1] = 100};  //指定下标初始化,其他元素初始化为0

注意:

在声明数组的时候初始化元素,如果元素个数使用变量,就不能初始化。在编译的时候,编译器是不知道数组的长度的,所以没法初始化。

int main(){
    int length = 4;
    int arr[length];//不初始化就不会报错
    //int arr1[length] = {1,2,3};  这样就不行,会报错
}

数组的遍历

int main(){
    //声明数组并为每个元素赋值
    int arr[3];
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;

    //将每一个元素的下标遍历出来,当做数组的下标就能遍历数组了
    //下标 == 数组长度-1
    for(int i = 0;i < 3;i++){
        printf("%d\n",arr[i]);
    }
    return 0;
}

数组在内存中的存储

111111111111111

数组其实就是由指定个数的连续的变量组合成的,存储方式和普通变量存储方式相同,把每一个元素当做一个普通变量。分配内存空间的时候,只是分配多个连续空间分别存储每个元素,而且也是从高地址向低地址连续分配的。每个元素的地址,就是他占用字节的最低字节的地址。

int arr[3];
arr[0];//低地址,数组的地址就是第一个元素的地址
arr[1];
arr[2];//高地址

数组的地址:数组之中第1个元素的地址,就是数组的地址。也就是下标为0的元素的地址。

数组长度计算

sizeof(数组名)计算出这个数组在内存中占用的总字节数。

sizeof(数据类型)计算出每个元素在内存中占用的字节数。

元素个数 = sizeof(数组名)/sizeof(数据类型);

int main(){
    int scores[5] = {0};
    int length = sizeof(scores) / sizeof(int);//元素个数 = 数组总字节 / 每个元素字节;

    //讲用户输入数据存储到数组
    for (int i = 0; i < length; i++) {
        printf("请输入第%d个同学的年龄:",i+1);
        scanf("%d",&scores[i]);
    }

    //遍历打印出数组
    for (int i = 0; i < length; i++) {
        printf("scores[%d] = %d\n",i,scores[i]);
    }

    return 0;
}

数组的常见应用

1.求最大值

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //假设第一个元素为最大值
    int max = scores[0];

    for (int i = 1; i < length; i++) {
        //将max和每个元素相比,大的就赋值给max
        if (max < scores[i]) {
            max = scores[i];
        }
    }
    printf("max = %d\n",max);

    return 0;
}

2.求最小值

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //假设第一个元素为最小值
    int min = scores[0];

    for (int i = 1; i < length; i++) {
        //将max和每个元素相比,小的就赋值给max
        if (min < scores[i]) {
            min = scores[i];
        }
    }
    printf("min = %d\n",min);

    return 0;
}

3.求累加和

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //sum存储累加和
    int sum = 0;

    for (int i = 0; i < length; i++) {
        sum += scores[i];
    }
    printf("sum = %d\n",sum);

    return 0;
}

4.求平均值

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //sum存储累加和
    int sum = 0;

    //平均值
    float avg = 0;

    for (int i = 0; i < length; i++) {
        sum += scores[i];
    }
    avg = (float)sum / length;
    printf("avg = %.2f\n",avg);

    return 0;
}

5.查找数组是否包含指定元素

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //需要找的数
    int zhaoNum = 879;

    for (int i = 0; i < length; i++) {
        if (scores[i] == zhaoNum) {
            printf("找到了\n");
            break;
        }
        if (i == length - 1) {
            printf("没找到\n");
        }
    }

    return 0;
}

6.查找指定元素在数组中第一次出现的下标

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,4,657,684,5322,64765,8799,45453,34232,345};

    //计算数组长度
    int length = sizeof(scores)/sizeof(int);

    //需要找的数
    int zhaoNum = 325;

    for (int i = 0; i < length; i++) {
        if (scores[i] == zhaoNum) {
            printf("下标为:%d",i);
            break;
        }
        if (i == length - 1) {
            printf("没找到\n");
        }
    }

    return 0;
}

7.选择排序

void selectSort(int arr[],int length){

    //外层控制比较的轮数
    for (int i = 0; i < length - 1; i++) {

        //内层控制每轮比较的次数
        for (int j = i+1; j < length; j++) {

            //当每轮循环的第一个元素小于后面的元素时
            if (arr[i] < arr[j]) {

                //就交换他们的位置
                arr[i] = arr[i] ^ arr[j];
                arr[j] = arr[i] ^ arr[j];
                arr[i] = arr[i] ^ arr[j];
            }
        }
    }
}

int main(){
    int arr[] = {1,3423,54,646,4,2,3423,4,656,34,34,36,4,24,};
    //计算数组长度
    int length = sizeof(arr)/sizeof(int);

    //调用函数对数组进行排序
    selectSort(arr, length);

    //遍历打印出排序后的数组
    for (int i = 0; i < length; i++) {
        printf("%d ",arr[i]);
    }

    return 0;
}

双色球案例练习:

int cha(int arr[],int length,int zhaoNum){
    //遍历数组
    for (int i = 0; i < length; i++) {
        //判断数组中有没有要查找的数据
        if (arr[i] == zhaoNum) {
            //有则返回1
            return 1;
        }
        if (i == length - 1) {
            return 0;
        }
    }
    return 0;
}

int main(){
    int arr[6] = {0};
    int length = sizeof(arr)/sizeof(int);

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

        //随机生成1-33的整数
        int num = arc4random_uniform(33)+1;

        //调用函数判断数组中是否存在,返回0则不存在
        if (cha(arr,length,num) == 0) {
            //不存在就存进数组
            arr[i] = num;
        }else{
            //存在就重新生成
            i--;
        }
    }

    //打印出随机生成的6个红球
    for (int i = 0; i < length; i++) {
        printf("%d ",arr[i]);
    }
    return 0;
}

数组作为函数的参数

如果函数的形参是一个数组,在调用这个函数的时候,也必须要为这个函数传入一个相同类型的数组,并且是传入数组的地址。然后函数操作的就是我们传进去那个数组,改变数组中的元素,也就是改变传入的那个数组的元素。

void test(int num[]){
    num[0] = 10;
}

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,44232,345};

    //调用函数,传入数组名,数组名就是数组的地址
    test(scores);
    printf("%d\n",scores[0]);//打印 10

    return 0;
}

注意:当数组作为函数的参数的时候,传入的是数组的地址,一个地址占据8个字节。但一个数组如果占据的内存大于8字节,将不能在函数里通过sizeof计算数组的长度。而且函数里的形参是去内存中申请8个字节存储指针变量,并将传入的数组地址赋值给这个指针变量。

void test(int num[]){
    printf("%p\n",num);
}

int main(){
    //随便整一个int类型的数组
    int scores[] = {232,545,23,325,44232,345};

    //调用函数,传入数组
    test(scores);
    printf("%p\n",scores);

    return 0;
}

我们会发现函数中打印的数组地址和我们声明的数组的地址是一致的。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注