C语言 数组

C语言 数组

在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来——称为数组。

数组就是在内存中连续的相同类型的变量空间。

同一个数组所有的成员都是相同的数据类型,同时所有的成员在内存中的地址是连续的。

 

数组属于构造数据类型:

  • 一个数组可以分解为多个数组元素:这些数组元素可以是基本数据类型或构造类型。
 int a[10]; 
 struct Stu boy[10];
  • 按数组元素类型的不同,数组可分为:数值数组、字符数组、指针数组、结构数组等类别。
 int a[10];
 char s[10];
 char *p[10];

一维数组

数组名字符合标识符的书写规定(数字、英文字母、下划线)

数组名不能与其它变量名相同,同一作用域内是唯一的

方括号[]中常量表达式表示数组元素的个数

  • int a[3]表示数组a有3个元素
  • 其下标从0开始计算,因此3个元素分别为a[0],a[1],a[2]

定义数组时[]内最好是常量,使用数组时[]内即可是常量,也可以是变量

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 变量定义
    // 数据类型 变量 = 值
    // 数组定义
    // 数据类型 数组名[元素个数]={值1,值2,值3}
    int arr[10] = { 9,4,2,1,8,5,3,6,10,7 };

    // 数组下标 数组名[下标]
    // 数组下标是从0开始的到数组元素个数-1
    printf("%d\n", arr[0]);
    printf("%d\n", arr[1]);
    printf("%d\n", arr[2]);

    return 0;
}
数组 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 数组在内存中存储方式和大小
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    
    // 下标为0的元素地址、数组地址是连续的
    printf("%p\n", &arr[0]);
    printf("%p\n", &arr[1]);
    printf("%p\n", &arr[2]);
    
    // 数组名是一个地址常量、只想数组首地址的常量
    printf("%p\n", arr);

    // 数组在内存占用大小 = 数据类型 * 元素个数
    printf("%d\n", sizeof(arr));

    // 数组元素大小 = 赋值数据类型大小
    printf("%d\n", sizeof(arr[0]));

    // 数组元素个数 = 数组内存大小 / 单个数组元素大小
    printf("%d\n", sizeof(arr) / sizeof(arr[0]));
// 取出数组所有值 
    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}
数组 使用案例:存储大小
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 正常格式
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    // 值没有对应,默认被设置为被初始化值,为0
    int arr2[10] = { 1,2,3,4,5};
    // 元素个数会根据值得个数自动获取
    int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };
    // 错误格式:没有被赋值,输出会出现乱码
    int arr4[10];
    // 错误格式:数组元素必须是常量 常量表达式
    int i = 10;
    int arr[i];
    // 数组必须预先知道大小 动态数组->开辟堆空间
    int arr6[SIZE];
    int arr7[2 * 2];
    return 0;
}   
数组 使用案例:格式
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    for (int i = 0; i < 20; i++)
    {
        // 数组下标越界、打印乱码
        // 可能会报错
        printf("%d\n", arr[i]);
    }
}
数组 使用案例:下标越界
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 实现数组逆至
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    int j = sizeof(arr) / sizeof(arr[0]) - 1;
    while (i < j)
    {
        // 通过临时变量交换数据
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;

        i++;
        j--;
    }
    for (int i = 0; i < 10; i++)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}
数组 使用案例:数组逆至
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 冒泡排序
    // 从小到大排序
    int arr[] = { 2,5,6,8,9,0,6,4,4,7 };
    // 外层控制行
    // 外层执行元素个数-1
    for (int i = 0; i < 10 - 1; i++)
    {
        // 内层控制列
        // 内层执行元素个数-1-执行次数
        for (int j = 0; j < 10-1; j++)
        {
            // 比较两个元素 满足条件交换
            // 通过符号控制排序方式
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j+1] = temp;
            }
        }
    }
    for (int i = 0; i < 10; i++)
    {
        printf("%d\n", arr[i]);
    }

    return 0;
}
数组 使用案例:冒泡排序

二维数组

二维数组定义的一般形式是:

  • 类型说明符 数组名[常量表达式1][常量表达式2]

其中常量表达式1表示第一维下标的长度,常量表达式2 表示第二维下标的长度。

int a[3][4];

定义了一个三行四列的数组,数组名为a其元素类型为整型,该数组的元素个数为3×4个,即:

 

 

 

二维数组a是按行进行存放的,先存放a[0]行,再存放a[1]行、a[2]行,并且每行有四个元素,也是依次存放的。

  • 二维数组在概念上是二维的:其下标在两个方向上变化,对其访问一般需要两个下标。
  • 在内存中并并存在二维数组,二维数组实际的硬件存储器是连续编址的,也就是说内存中只有一维数组,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 数据类型 数组名[行][列]=
    // {
    // {值1, 值2},
    // {值3, 值4}
    // }
    int arr[2][3]=
    {
        {1,2,3},
        {4,5,6}
    };
    
    // 打印二维数组
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%d", arr[i][j]);
        }
        printf("\n");
    }

    // 二维数组大小 = 行 * 列 * sizeof(数据类型)
    printf("%d\n", sizeof(arr));
    // 二维数组一行大小 
    printf("%d\n", sizeof(arr[0]));
    // 二维数组元素大小
    printf("%d\n", sizeof(arr[0][0]));
    // 二维数组行数
    printf("%d\n", sizeof(arr) / sizeof(arr[0]));
    // 二维数组列数
    printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));


    return 0;
}
二维数组 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 二维数组初始化过程
    // 正确格式1:
    int arr1[2][3]=
    {
        {1,2,3},
        {4,5,6}
    };
    // 正确格式2:不推荐
    int arr2[2][3] = { 1,2,3,4,5,6, };
    // 正确格式3:列可以被省略、未被初始化的值,为0
    int arr3[][3] =
    {
        { 1,2,3 },
        { 4,}
    };
    
    // 二维数组首地址
    // 所使用的内存地址是连续的
    // 每个元素中间隔4个字符
    // 每个列之前间隔12个字符
    printf("%p\n", arr);
    printf("%p\n", arr[0]);
    printf("%p\n", &arr[0][0]);

    // 错误书写
    // arr[0] = 100; err

    return 0;
}
二维数组 使用案例:对应关系
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 定义一个数组 存储五名学生三门成绩 arr[5][3]
    // 求出每名学生的总成绩 平均成绩
    // 求出每门学科的总成绩 平均成绩
    int arr[5][3];

    // 获取学生成绩
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            scanf("%d",&arr[i][j]);
        }
    }

    // 获取学生成绩
    for (int i = 0; i < 5; i++)
    {
        int sum = 0;
        for (int j = 0; j < 3; j++)
        {
            sum += arr[i][j];
        }
        printf("第%d名学生的总成绩为:%d\t平均成绩为:%d\n", i + 1, sum, sum / 3);;
    }

    // 获取课程成绩
    for (int i = 0; i < 3; i++)
    {
        int sum = 0;
        for (int j = 0; j < 5; j++)
        {
            sum += arr[j][i];
        }
        printf("第%d门功课的总成绩为:%d\t平均成绩为:%d\n", i + 1, sum, sum / 5);;
    }

    return 0;
}
二维数组 使用案例:学生考试

多维数组

多维数组的定义与二维数组类似,其语法格式具体如下:

  • 数组类型修饰符 数组名 [n1][n2]…[nn];
int a[3][4][5];

定义了一个三维数组,数组的名字是a,数组的长度为3,每个数组的元素又是一个二维数组,这个二维数组的长度是4,并且这个二维数组中的每个元素又是一个一维数组,这个一维数组的长度是5,元素类型是int。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 三维数组
    // 数据类型 数组名[层][行][列]
    // 格式2:数据类型 arr[][3][4]
    // 未被初始化的值,为0
    int arr[2][3][4]=
    {
        {
            {1,2,3,4},
            {2,3,4,5},
            {3,4,5,6}
        },
        {
            {4,5,6,7},
            {2,3,4,5},
            {3,4,5,6}
        }
    };
    
    // 打印数组
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            for (int k = 0; k < 4; k++)
            {
                printf("%d\t", arr[i][j][k]);
            }
            printf("\n");
        }
    }

    // 三维数组大小 = 层 * 行 * 列 * sizeof(数据类型)
    printf("%d\n", sizeof(arr));
    // 三维数组中一层大小
    printf("%d\n", sizeof(arr[0]));
    // 三维数组中一行大小
    printf("%d\n", sizeof(arr[0][0]));
    // 三维数组中元素大小
    printf("%d\n", sizeof(arr[0][0][0]));
    
    // 求出数量
    printf("层:%d\n", sizeof(arr) / sizeof(arr[0]));
    printf("行:%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));
    printf("列:%d\n", sizeof(arr[0][0]) / sizeof(arr[0][0][0]));

    return 0;
}
多维数组 使用案例

字符数组

字符数组与字符串区别

  • C语言中没有字符串这种数据类型,可以通过char的数组来替代;
  • 字符串一定是一个char的数组,但char的数组未必是字符串;
  • 数字0(和字符‘\0’等价)结尾的char数组就是一个字符串,但如果char数组没有以数字0结尾,那么就不是一个字符串,只是普通字符数组,所以字符串是一种特殊的char的数组。

案例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 格式一:定义字符数组
    char arr1[5] = {'h','e','l','l','o'};

    // 字符串、字符串结束标志为\0
    // 数字0等同于\0,但是不等同于'0'
    // 格式二:数组的字符样式 
    char * arr2 = "hello";
    char arr3[6] = {'h','e','l','l','o'};
    char arr4[] = {'h','e','l','l','o' };
    char arr5[] = { 'h','e','l','l','o','\0' };
    char arr6[] = { "hello" };

    // 查看字符数组大小
    printf("%d\n",sizeof(arr1));

    // 格式一:打印字符数组、sizeof(arr)/sizeof(arr[0])可以写为sizeof(arr)
    for (int i = 0; i < sizeof(arr1)/sizeof(arr1[0]); i++)
    {
        printf("%c\n", arr1[i]);
    }

    // 格式二:打印字符数组
    printf("%s\n", arr3);

    return 0;
}
字符数组 使用案例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{

    char arr1[5] = {'h','e','l','l','o'};

    // 定义字符数组存储字符串
    char ch[10];

    // scanf不安全警告问题,需要先定义后使用
    // 字符数组键盘输入时不需要使用&
    // 输入9个字符串,需要保留1位给 \0使用
    scanf("%s", ch);
    printf("%s", ch);

    return 0;
}
字符数组 使用案例:输入键盘获取字符串
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int main(void)
{
    // 字符串拼接
    char ch1[] = "hello";
    char ch2[] = "world";
    char ch3[20];

    int i = 0;
    int j = 0;

    while (ch1[i] != '\0')
    {
        ch3[i] = ch1[i];
        i++;
    }

    while (ch2[j] != '\0')
    {
        ch3[i + j] = ch2[j];
        j++;
    }

    ch3[i + j] = '\0';
    printf("%s", ch3);

    return 0;
}
字符数组 使用案例:字符串拼接案例

 

posted @ 2020-02-27 17:47  kevin.Xiang  阅读(544)  评论(0编辑  收藏  举报