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; }