数组的定义

    /*
     变量如何定义?
     数据类型   变量名称
     数组如何定义?
     数据类型   数组名称[数据的个数]     这样
     元素类型   数组名称[元素个数]
     元素类型:就是数组中要存储的数据类型,一旦指定数组中就只能存储该类型的数据
     元素个数:就是数组中能够存储的数据个数
     */
    int scores[3]; // 定义了一个数据名称为 scores,数组中可以存储三个 int 类型的数据
    // 如何在内存中存储呢?
    // 先分配一个 12 个字节的空间给 scores,这个数组中n可以存放三个 int 类型的数据,那么就会等分成三个,四个字节的内存空间用来存储 int 类型的数据
    // 那么如何存值呢?
    // socres 中有三个小的空间,需要指定给哪个空间赋值
    // 只要 C语言定义了数组,那么系统就会给每个小的空间存储一个编号,这个编号称之为索引
    // 那么就只需要指定编号就可以赋值了
    scores[0] = 12;
    // 这个时候会将 12 的值赋值给 scores 存储空间中索引为 0 的空间中
    printf("scores[0]=%i\n",scores[0]);

数组的初始化

   // 数组的初始化
    int scores[5];
    scores[0] = 10;
    scores[1] = 20;
    scores[2] = 30;
    scores[3] = 40;
    scores[4] = 50;
    // 这样写很 low 哇,是不是很累啊
    // 完全初始化
    int scores1[5] = {1,2,3,4,5};
    // 部分初始化
    // 在部分初始化中对应的内存没有被初始化,那么值默认为 0
    int scores2[5] = {1,2}; // 默认从 0开始初始化
    printf("scores2[0]=%i\n",scores2[0]);
    printf("scores2[1]=%i\n",scores2[1]);
    printf("scores2[2]=%i\n",scores2[2]); // 0
    
    printf("-------\n");
    int scores3[3];
    printf("scores3[0]=%i\n",scores3[0]);
    printf("scores3[1]=%i\n",scores3[1]);
    printf("scores3[2]=%i\n",scores3[2]);
    // 此时整个数组都没有初始化,只是定义了话,有时打印的不是 0,注意只有部分初始化的时候,没有初始化的值才为 0.同时也不要随意使用没有初始化的值,可能是一段垃圾数据
    
    // 注意定义数组的时候,数组的个数不能使用变量,如果使用了变量,数组中的值会是一些垃圾的值
    /*
    int num = 10;
    int scores[num];// 报错,变量是一个动态的值,不清楚要分配多少内存空间
    */
    
    // 如果定义的同时进行初始化,那么元素的个数可以被省略
    // 省略之后,初始化了几个数据,那么数组的长度就是几,也就是数据可以存储几个数据
    int scores5[] = {1,3};
    printf("scores5[0]=%i\n",scores5[0]);
    printf("scores5[1]=%i\n",scores5[1]);
    
    // 如果定义的同时没有进行初始化,那么元素的个数不能省略会直接报错
    // int scores6[]; // 此时直接报错
    
    // 指定位置初始化
    int scores7[5] = {0,0,0,3,4};
    int scores8[101] = {[99]=1,[100]=2};
    printf("scores8[99] = %i\n",scores8[99]); // 1
    printf("scores8[100] = %i\n",scores8[100]); // 2


    // 大括号只能在定义的同时才可以使用,
    // 先定义在初始化
    int scores9[3];
    scores9[0] = 1;
    scores9[1] = 1;
    scores9[2] = 1;
    

数组的遍历

    // 数组的遍历
    int nums[6] = {99,88,77,55,66,44};
    for (int i = 0; i <= 6; i++) {
        printf("nums[%i] = %i\n",i,nums[i]);
    }
    // 这么写可以但是,如果以后数组的长度发生了变化呢?还是需要修改,能否动态修改这个长度呢?
    int leight = sizeof(nums) / sizeof(nums[0]);
    printf("leight = %i\n",leight);
    // 通过 sizeof 查出nums 这个数组的总内存空间的长度,再通过 sizeof 查出数组中第一个元素的长度(因为数组只能存储同一个类型的元素,所以每个元素所占的内存空间都是一样的),两个相除就是这个数组的长度
    
    for (int i = 0; i <= leight; i++) {
        printf("nums[%i] = %i\n",i,nums[i]);
    }

数组的内存存储

  • 变量存储数据是从高字节开始存储
  • 数组存储数据是从低字节开始存储
    // 数组的内存存储是从低字节开始存储,变量存储是从高字节开始存储
    char charValue[4] = {'a','v','c','d'};
    printf("charValue[0] = %p\n",&charValue[0] ); // 0x7ffeefbff20c
    printf("charValue[1] = %p\n",&charValue[1] ); // 0x7ffeefbff20d
    printf("charValue[2] = %p\n",&charValue[2] ); // 0x7ffeefbff20e
    printf("charValue[3] = %p\n",&charValue[3] ); // 0x7ffeefbff20f
    // 可以看出随着索引的变化,内存地址是变大的,所以数组的内存存储是从低字节开始存储的

  • 其实数组名就是数组地址
char charValue[4] = {'a','v','c','d'};
printf("charValue 数据名的内存地址:%p\n",&charValue);
printf("charValue[0] = %p\n",&charValue[0] );

/*
charValue 数据名的内存地址:0x7ffeefbff20c
charValue[0] = 0x7ffeefbff20c
*/

&charValue = charValue[0] = charValue
  • 数组的每一个元素是从低字节开始存储,但是每个元素中的值又是从高字节开始存储

数组注意点

  • 在使用数组的时候一定不要访问不是属于自己的存储空间,这样会导致数据混乱
    // 数组的注意点
    char num[2] = {1,2};
    char value[3] = {4,5,6};
    
    value[3] = 44;
    printf("num[0] = %i\n",num[0]);

// 控制台输出
// num[0] = 44

数组的练习

    // 练习
    // 从键盘输入三个数,计算总值和平均值
    // 不使用变量接收,使用数组接收
    int nums[3] = {-1};// 数组部分初始化
    int leight = sizeof(nums) / sizeof(nums[0]);
    
    for (int i = 0; i < leight; i++) {
        printf("nums[%i] = %i\n",i,nums[i]);
    }
    
    printf("----------\n");
    
    for (int i = 0; i < leight; i++) {
        printf("请您输入一个数,回车结束\n");
        scanf("%i",&nums[i]); // 赋值给每个索引的值
        // 1printf("nums[%i] = %i\n",i,nums[i]);
    }
    
    printf("----------\n");
    int sum = 0;
    for (int i = 0; i < leight; i++) {
        printf("nums[%i] = %i\n",i,nums[i]); // 打印每个索引的值
        // sum = sum + nums[i];
        sum += nums[i];
    }
    printf("求和的值:%i\n",sum);
    printf("求平均值的值:%i\n",sum/leight);

数组和函数

    // 数组和函数
    // 基本数据类型是值传递
    int num = 10;
    test(num);
    printf("num = %i\n",num); // 此时 num 的值还是 10,并不 50,因为基本数据类型是值传递
    printf("main函数中的 num 内存地址:%p\n",&num);
    
    // 此时看一看我们传递一个数组
    int array[] = {1,2,3};
    testArray(array);
    printf("array[0] = %i\n",array[0]); // 100,因为数组是地址传递,内存地址在哪里修改了都会受到影响
    printf("array[1] = %i\n",array[1]); // 2
    printf("array[2] = %i\n",array[2]); // 3
    printf("main函数中testArray[0]的内存地址:%p\n",&array[0]);
    printf("main函数中testArray[1]的内存地址:%p\n",&array[1]);
    printf("main函数中testArray[2]的内存地址:%p\n",&array[2]);
    // 通过打印内存地址可以看到,基本数据类型在方法中都是新开辟的内存地址,数组并不是
    
    return 0;
}

void test(int num){
    num = 50;
    printf("test 方法中的 num 内存地址:%p\n",&num);
}

void testArray(int array[]){
    array[0] = 100;
    printf("testArray方法中的 array[0]的内存地址:%p\n",&array[0]);
    printf("testArray方法中的 array[0]的内存地址:%p\n",&array[1]);
    printf("testArray方法中的 array[0]内存地址:%p\n",&array[2]);
}


// 注意只需要看函数的参数是传递的基本数据类型还是指针(地址)就可以
main(){
    // 要求实现一个函数,只要传递的是一个数组,就返回数组中所有的值
    int array1[5] ={1,2,3,4,5};
    int leight = sizeof(array1)/sizeof(array1[0]);
    getArrayNum(array1,leight);
    return 0;
}

int getArrayNum(int array1[],int leight){
    // int leight = sizeof(array1)/sizeof(array1[0]);
    // 这里不能将 leight在这里计算,因为传递的是一个数组的地址,地址永远是占 8 个字节
    for (int i = 0; i < leight; i++) {
        printf("array1[%i] = %i\n",i,array1[i]);
    }
    return 0;
}

练习 2

main(){
        // 设计一个函数 int arrayMax()找出数组元素的最大值
    int array[] = {0,-5,3,8};
    int leight = sizeof(array)/sizeof(array[0]);
    int maxNum = arrayMax(array,leight);
    printf("最大值是:%i\n",maxNum);
    return 0;
}

// 错误的写法,用第一个元素跟第二个元素比较,这种比较会超出数组的长度.返回一个垃圾值
int arrayMax(int array[],int leight){
    int temp = 0;
    for (int i = 0; i < leight; i++) {
        if(array[i] >= array[i+1]){ 
            temp = array[i];
        }
        else{
            temp = array[i+1];
        }
    }
    return temp;
}

// 方法一 (设置一个临时值,用这个临时值跟数组的没一个值作比较,如果临时值小于,那就替换)
int arrayMax(int array[],int leight){
    int temp = 0;
    for (int i = 0; i < leight; i++) {
        if(temp <= array[i]){
            temp = array[i];
        }
    }
    return temp;
}

// 但是方法一还存在问题,如果数组中的数都小于临时值的话那就出现了 bug
// 所以用数组中的一个数作为最大值
int arrayMax(int array[],int leight){
    int temp = array[0];
    for (int i = 0; i < leight; i++) {
        if(temp <= array[i]){
            temp = array[i];
        }
    }
    return temp;
}


//方法二 定义一个temp 值为索引值,
int arrayMax2(int array[],int leight){
    int temp = 0;
    for (int i = 1; i < leight; i++) { // 此处 i 可以从 1 开始
        if(array[temp] <= array[i]){
            temp = i;
        }
    }
    return array[temp];
}

练习 3

    // 从键盘输入3 个 0-9 之间的数,然后输出 0-9 之间那些数没有出现过
    int num1,num2,num3;
    printf("输入\n");
//    scanf("%i",&num1);
//    scanf("%i",&num2);
//    scanf("%i",&num3);
    scanf("%i,%i,%i",&num1,&num2,&num3);
    printf("输入结束\n");
    int array[3] = {num1,num2,num3};
    int leight = sizeof(array)/ sizeof(array[0]);
    for (int i = 0; i <= 9; i++) {
        if(array[0] != i &&
           array[1] != i &&
           array[2] != i){
            printf("%i没出现过\n",i);
        }
    }
    



    // 方法二,输入三个数,使这三个数作为下标,将次s复制为 1,那么值 为 0 的就是没有输入过的数
    int array[10] = {0}; // 部分初始化,没有被初始化的都为 0,并不是垃圾值
    int value = -1;
    int leigth = sizeof(array) / sizeof(array[0]);
    for (int i = 0; i < 3; i++) {
        printf("请输入第%i个数,回车结束\n",i+1);
        scanf("%i",&value);
        array[value] = 1;// 将每次的 value 值复制给
    }
    
    for (int i = 0; i <  leigth; i++) {
        printf("数组第%i 个的值:%i\n",i,array[i]);
    }
    
    for (int i = 0; i < leigth; i++) {
        if(array[i] != 1){//只要是 值为 0 的那么就是没有出现过的,巧妙的利用了 0-9 之间的数,先将输入的数当做下标,把数组的这个下标的值设置为 1,那么m不是1 的值,他的下标就是么有c输入过的
            printf("0-9 之间没有出现过:%i\n",i);
        }
    }

练习 4

    // 要求从键盘输入6 个 0-9 之间的数,排序后输出

	// 分析:部分初始化一个数组,依次输入 6 个数字,循环将输入的 6 个数作为下标,将数组中的数赋值为 1,那么此数组中值为 1 的下标就是输入的数,再次循环输出值为 1 的下标,既从小到大输出
    int array[10] = {0}; // 部分初始化
    int value = -1;
    int leight = sizeof(array) / sizeof(array[0]);
    for (int i = 0; i < 6; i++) {
        printf("请输入第%i个值:\n",i+1);
        scanf("%i",&value);
        array[value] = 1;
    }
    
    for (int i = 0; i <= 9; i++) {
        if(array[i] == 1){
            printf("从小到大排序:%i\n",i);
        }
        
    }



// 改进:
    // 但是输入了相同的值时,不会依次输出.而是将之前的值进行了覆盖
    int array[10] = {0}; // 部分初始化
    int value = -1;
    int leight = sizeof(array) / sizeof(array[0]);
    for (int i = 0; i < 6; i++) {
        printf("请输入第%i个值:\n",i+1);
        scanf("%i",&value);
        array[value] += 1; // 此处如果多次输入了d同一个下标,那么就进行加 1
    }
    
    for (int i = 0; i <= 9; i++) {
        if(array[i] != 0){ // 如果所在角标的值不是 0,那么久开始循环,条件表达式是 j<=这个下标所对的值
            for (int j = 1; j <= array[i]; j++) {
                printf("从小到大排序:%i\n",i);
            }
            
            
        }
        
posted on 2020-05-31 21:58  python我学的很菜  阅读(282)  评论(0编辑  收藏  举报