C语言基础之【数组和字符串】(上)
C语言基础之【数组和字符串】(上)
- 概述
- 一维数组
- 一维数组的定义
- 一维数组的初始化
- 一维数组的访问
- 一维数组的遍历
- 数组名
- 一维数组的常用数据
- 强化训练
- 一维数组的最值
- 一维数组的逆置
- 一维数组的排序(冒泡排序)
- 二维数组
- 二维数组的定义
- 二维数组的初始化
- 二维数组的访问
- 二维数组的遍历
- 数组名
- 二维数组的常用数据
- 强化训练
- 学生成绩统计与分析
- 多维数组
- 多维数组的定义
- 多维数组的初始化
- 多维数组的访问
- 多维数组的遍历
往期《C语言基础系列》回顾:
链接:
C语言基础之【C语言概述】
C语言基础之【数据类型】(上)
C语言基础之【数据类型】(下)
C语言基础之【运算符与表达式】
C语言基础之【程序流程结构】
概述
在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来——称为数组。
数组
:一组具有相同数据类型的元素
的有序集合
- 同一个数组中的所有成员都是相同的数据类型
- 同一个数组中的所有成员在内存中的地址是连续的
数组可以根据
维度
、存储方式
和使用场景
进行分类。
按维度分类:
数组的维度是指数组的层次结构,常见的有
一维数组
、二维数组
和多维数组
一维数组
一维数组是最简单的数组形式,元素按线性顺序排列。
int numbers[5] = {1, 2, 3, 4, 5};
二维数组
二维数组是一个矩阵,可以看作是一维数组的数组。
int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9} };
多维数组
多维数组是二维数组的扩展,可以有更多维度。
int cube[2][3][4]; // 三维数组
按存储方式分类:
数组的存储方式可以分为
静态数组
和动态数组
静态数组
静态数组的大小在编译时确定,内存分配在栈上。
int numbers[10]; // 静态数组
动态数组
动态数组的大小在运行时确定,内存分配在堆上。
- 需要使用动态内存分配函数(如:
malloc
、calloc
)int *numbers = (int *)malloc(10 * sizeof(int)); // 动态数组
按元素类型分类:
数组的元素类型决定了数组中存储的数据类型。
整型数组
存储整数类型的数据。
int numbers[5] = {1, 2, 3, 4, 5};
浮点型数组
存储浮点数类型的数据。
float scores[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
字符数组
存储字符类型的数据,常用于存储字符串。
char name[20] = "Hello";
指针数组
存储指针类型的数据。
char *names[3] = {"Alice", "Bob", "Charlie"};
结构体数组
存储结构体类型的数据。
struct Student {char name[20];int age; }; struct Student students[3] = {{"Alice", 20},{"Bob", 21},{"Charlie", 22} };
按使用场景分类:
数组可以根据其使用场景进行分类。
普通数组
用于存储和处理一组数据。
int numbers[5] = {1, 2, 3, 4, 5};
字符串数组
用于存储和处理字符串。
char names[3][20] = {"Alice", "Bob", "Charlie"};
一维数组
一维数组的定义
一维数组的定义语法:
数据类型 数组名[数组大小];
数据类型
:数组中每个元素的类型。(例如:int
、float
、char
等)数组名
:数组的标识符。(用于访问数组)数组大小
:数组中元素的数量。(必须是一个常量)int numbers[5]; // 定义一个包含5个整数的数组 float scores[10]; // 定义一个包含10个浮点数的数组 char name[20]; // 定义一个包含20个字符的数组
一维数组的注意事项:
数组大小必须是一个常量
- 数组大小必须是一个常量,不能是变量。
- 例如:
int n = 10; int numbers[n];
在标准C中是不合法的(C99 支持变长数组)
数组名是常量指针
- 数组名表示数组的首地址,是一个常量指针,不能修改。
- 例如:
int numbers[5];
中,numbers
是&numbers[0]
的简写。
一维数组的初始化
数组可以在
定义时初始化
,也可以在定义后逐个赋值
定义时初始化:
一维数组定义时初始化的语法:
数据类型 数组名[数组大小] = {初始值列表};
1.完全初始化
为数组的所有元素提供初始值。
int numbers[5] = {1, 2, 3, 4, 5};
- 数组
numbers
的元素为1, 2, 3, 4, 5
2.部分初始化
只为数组的部分元素提供初始值,剩余元素会自动初始化为
0
int numbers[5] = {1, 2};
- 数组
numbers
的元素为1, 2, 0, 0, 0
3.省略数组大小
如果提供了初始值列表,可以省略数组大小,编译器会根据初始值的数量自动确定数组大小。
int numbers[] = {1, 2, 3, 4, 5};
- 数组
numbers
的大小为5
,元素为1, 2, 3, 4, 5
注:
[]中不指定元素个数时,定义时必须初始化
定义后赋值:
int numbers[5]; numbers[0] = 1; numbers[1] = 2; numbers[2] = 3; numbers[3] = 4; numbers[4] = 5;
其他特殊的初始化:
在定义数组的同时进行赋值,称为
初始化
全局数组
若不初始化,编译器将其数组元素初始化为零
局部数组
若不初始化,数组元素为随机值
#include <stdio.h>int a[3];
int main()
{int b[3];//遍历数组,并输出每个成员的值for (int i = 0; i < 3; i++){printf("%d ", a[i]);}printf("\n");for (int i = 0; i < 3; i++){printf("%d ", b[i]);}printf("\n");return 0;
}
输出:
0 0 0
-858993460 -858993460 -858993460
一维数组的初始化总结:
#include <stdio.h>
#include <stdlib.h>int main()
{// 定义并初始化数组int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 完全初始化int arr2[10] = { 1, 2, 3, 4, 5 }; // 部分初始化,剩余元素为0int arr3[10] = { 0 }; // 全部初始化为0int arr4[] = { 1, 2, 3, 4, 5 }; // 自动推断大小为5int arr5[] = { 0 }; // 自动推断大小为1// 打印arr1printf("arr1= ");for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++){printf("%d ", arr1[i]);}printf("\n");// 打印arr2printf("arr2= ");for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++){printf("%d ", arr2[i]);}printf("\n");// 打印arr3printf("arr3= ");for (int i = 0; i < sizeof(arr3) / sizeof(arr3[0]); i++){printf("%d ", arr3[i]);}printf("\n");// 打印arr4printf("arr4= ");for (int i = 0; i < sizeof(arr4) / sizeof(arr4[0]); i++){printf("%d ", arr4[i]);}printf("\n");// 打印arr5printf("arr5= ");for (int i = 0; i < sizeof(arr5) / sizeof(arr5[0]); i++){printf("%d ", arr5[i]);}printf("\n");// 暂停程序(Windows特有)system("pause");// 返回成功状态return EXIT_SUCCESS;
}
输出:
arr1= 1 2 3 4 5 6 7 8 9 10 arr2= 1 2 3 4 5 0 0 0 0 0 arr3= 0 0 0 0 0 0 0 0 0 0 arr4= 1 2 3 4 5 arr5= 0
一维数组的访问
数组元素通过索引访问,索引从
0
开始,最大索引为数组大小 - 1
int numbers[5] = {10, 20, 30, 40, 50};printf("%d\n", numbers[0]); // 输出第一个元素:10 printf("%d\n", numbers[2]); // 输出第三个元素:30
一维数组的遍历
可以使用循环遍历数组中的所有元素。
int numbers[5] = {10, 20, 30, 40, 50};for (int i = 0; i < 5; i++) {printf("%d ", numbers[i]); }
输出:
10 20 30 40 50
数组名
数组名代表数组首元素的地址
#include <stdio.h>int main() {int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };printf("a = %p\n", a); //数组名printf("&a[0] = %p\n", &a[0]); //数组首元素for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){printf("%d ", a[i]);}printf("\n");return 0; }
输出:
a = 0000006C5C4FFAA8
&a[0] = 0000006C5C4FFAA8
1 2 3 4 5 6 7 8 9 10
数组名是一个指向数组首元素的指针
(可以通过指针访问数组元素)int numbers[5] = {10, 20, 30, 40, 50}; int *ptr = numbers; // ptr 指向数组的首元素printf("%d\n", *ptr); // 输出第一个元素:10 printf("%d\n", *(ptr + 2)); // 输出第三个元素:30
#include <stdio.h>
#include <stdlib.h>int main()
{int a = 5, b = 29, c = 10;int arr[10] = { 1, 2, 4, 6, 76, 8, 90, 4, 3, 6 }; printf("&a = %p\n", &a);printf("&b = %p\n", &b);printf("&c = %p\n", &c);printf("&arr[0] = %x\n", &arr[0]);printf("&arr[1] = %p\n", &arr[1]);printf("&arr[2] = %p\n", &arr[2]);printf("&arr[3] = %p\n", &arr[3]);printf("&arr[4] = %x\n", &arr[4]);system("pause");return EXIT_SUCCESS;
}
输出:
&a = 00000045704FF964
&b = 00000045704FF984
&c = 00000045704FF9A4
&arr[0] = 704ff9c8
&arr[1] = 00000045704FF9CC
&arr[2] = 00000045704FF9D0
&arr[3] = 00000045704FF9D4
&arr[4] = 704ff9d8分析:
- 变量a,b,c在内存中是非连续存储的。
- 数组arr中的10个整形变量在内存中是连续存储的。
%x
和%p
的区别:
%x
用于以十六进制格式打印无符号整数。%p
用于打印指针地址,通常以十六进制格式显示。
一维数组的常用数据
一维数组的大小 :
sizeof(arr));
一维数组一个元素的大小:
sizeof(arr[0]));
一维数组元素的个数:
sizeof(arr) / sizeof(arr[0]));
#include <stdio.h>
#include <stdlib.h>int main(void)
{int a = 5, b = 29, c = 10;int arr[12] = { 1, 2, 4, 6, 76, 8, 90, 4, 3, 6, 6, 8 }; printf("数组的大小: %u\n", sizeof(arr));printf("数组一个元素的大小: %u\n", sizeof(arr[0]));printf("数组元素的个数: %d\n", sizeof(arr) / sizeof(arr[0]));system("pause");return EXIT_SUCCESS;
}
输出:
数组的大小: 48
数组一个元素的大小: 4
数组元素的个数: 12
强化训练
一维数组的最值
#include <stdio.h>int main()
{int a[] = { 1, -2, 3,-4, 5, -6, 7, -8, 9, -10 };//定义一个数组,同时初始化所有成员变量int i = 0;int max = a[0];for (i = 1; i < sizeof(a) / sizeof(a[0]); i++){if (a[i] > max){max = a[i];}}printf("数组中最大值为:%d\n", max);return 0;
}
输出:
数组中最大值为:9
一维数组的逆置
#include <stdio.h>int main()
{int a[] = { 1, -2, 3,-4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量int i = 0;int j = sizeof(a) / sizeof(a[0]) - 1;int temp;while (i < j){temp = a[i];a[i] = a[j];a[j] = temp;i++;j--;}for (i = 0; i < sizeof(a) / sizeof(a[0]); i++){printf("%d ", a[i]);}printf("\n");return 0;
}
输出:
10 -9 -8 7 -6 5 -4 3 -2 1
一维数组的排序(冒泡排序)
#include <stdio.h>int main()
{int a[] = { 1, -2, 3,-4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量int i = 0;int j = 0;int n = sizeof(a) / sizeof(a[0]);int temp;for (i = 0; i < n - 1; i++){for (j = 0; j < n - i - 1; j++)//内循环的目的是比较相邻的元素,把大的放到后面{if (a[j] > a[j + 1]){temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}}for (i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");return 0;
}
输出:
-9 -8 -6 -4 -2 1 3 5 7 10
二维数组
二维数组的定义
二维数组的定义语法:
数据类型 数组名[行数][列数];
数据类型
:数组中每个元素的类型。(例如:int
、float
、char
等)数组名
:数组的标识符。行数
:数组的行数。列数
:数组的列数。int matrix[3][3]; // 定义一个3行3列的二维数组 float scores[5][10]; // 定义一个5行10列的二维数组
int a[3][4];
:定义了一个三行四列的数组。
- 数组名为a其元素类型为整型
- 该数组的元素个数为3×4个
二维数组在内存中是按行优先顺序存储的,先存放a[0]行,再存放a[1]行、a[2]行,并且每行有四个元素,也是依次存放的。
例如:
int matrix[3][4] = {{1, 2, 3},{4, 5, 6},{7, 8, 9} };
在内存中的存储顺序为:
1, 2, 3, 4, 5, 6, 7, 8, 9
二维数组在概念上是二维的
- 其下标在两个方向上变化,对其访问一般需要两个下标。
在内存中并不存在二维数组
- 也就是说内存中只有一维数组,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的。
所以:
二维数组它可以看作是一个“数组的数组”
二维数组的初始化
二维数组可以在
定义时初始化
,也可以在定义后逐个赋值
定义时初始化:
1.完全初始化
使用嵌套的大括号
{}
初始化二维数组。int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9} };
2.部分初始化
如果初始化时未指定所有元素的值,剩余元素会自动初始化为
0
int matrix[3][3] = {{1, 2},{4, 5},{7, 8} };
3.省略数组行数
在初始化三维数组时,可以省略第一维(层数)的大小,但必须指定第二维(行数)和第三维(列数)的大小。
编译器会根据初始化的数据自动推断第一维的大小。
#include <stdio.h>int main() {// 省略行数,指定列数为 3int arr[][3] = {1, 2, 3, 4, 5, 6, 7};// 计算行数int rows = sizeof(arr) / sizeof(arr[0]);int cols = sizeof(arr[0]) / sizeof(arr[0][0]);for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%d ", arr[i][j]);}printf("\n");}return 0; }
输出:
1 2 3 4 5 6 7 0 0
定义后赋值:
逐个为二维数组的元素赋值。
int matrix[3][3]; matrix[0][0] = 1; matrix[0][1] = 2; matrix[0][2] = 3; matrix[1][0] = 4; matrix[1][1] = 5; matrix[1][2] = 6; matrix[2][0] = 7; matrix[2][1] = 8; matrix[2][2] = 9;
二维数组的初始化总结:
#include <stdio.h>
#include <stdlib.h>int main()
{// 定义并初始化二维数组int arr1[3][3] ={{ 1, 2, 3 },{ 4, 5, 6 },{ 7, 8, 9 }};int arr2[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };int arr3[3][3] = {{1, 2},{4, 5},{7, 8}};int arr4[3][3] = { 1, 2, 3, 4 };int arr5[3][3] = { 0 };int arr6[][3] = {{1},{2, 3},{4, 5}};int arr7[][4] = { 1, 2, 3, 4, 5, 6 };int arr8[][4] = { 0 };// 打印arr1printf("arr1= \n");for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%d ", arr1[i][j]);}printf("\n");}printf("\n");// 打印arr2printf("arr2= \n");for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%d ", arr2[i][j]);}printf("\n");}printf("\n");// 打印arr3printf("arr3= \n");for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%d ", arr3[i][j]);}printf("\n");}printf("\n");// 打印arr4printf("arr4= \n");for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%d ", arr4[i][j]);}printf("\n");}printf("\n");// 打印arr5printf("arr5= \n");for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%d ", arr5[i][j]);}printf("\n");}printf("\n");// 打印arr6printf("arr6= \n");int rows6 = sizeof(arr6) / sizeof(arr6[0]);int cols6 = sizeof(arr6[0]) / sizeof(arr6[0][0]);for (int i = 0; i < rows6; i++){for (int j = 0; j < cols6; j++){printf("%d ", arr6[i][j]);}printf("\n");}printf("\n");// 打印arr7printf("arr7= \n");int rows7 = sizeof(arr7) / sizeof(arr7[0]);int cols7 = sizeof(arr7[0]) / sizeof(arr7[0][0]);for (int i = 0; i < rows7; i++){for (int j = 0; j < cols7; j++){printf("%d ", arr7[i][j]);}printf("\n");}printf("\n");// 打印arr8printf("arr8= \n");int rows8 = sizeof(arr8) / sizeof(arr8[0]);int cols8 = sizeof(arr8[0]) / sizeof(arr8[0][0]);for (int i = 0; i < rows8; i++){for (int j = 0; j < cols8; j++){printf("%d ", arr8[i][j]);}printf("\n");}printf("\n");// 暂停程序(Windows特有)system("pause");// 返回成功状态return EXIT_SUCCESS;
}
输出:
arr1= 1 2 3 4 5 6 7 8 9arr2= 1 2 3 4 5 6 7 8 9arr3= 1 2 0 4 5 0 7 8 0arr4= 1 2 3 4 0 0 0 0 0arr5= 0 0 0 0 0 0 0 0 0arr6= 1 0 0 2 3 0 4 5 0arr7= 1 2 3 4 5 6 0 0arr8= 0 0 0 0
二维数组的访问
二维数组的元素通过行索引和列索引访问,索引从
0
开始。int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9} };printf("%d\n", matrix[1][2]); // 输出第二行第三列的元素:6
二维数组的遍历
可以使用嵌套循环遍历二维数组中的所有元素。
int matrix[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9} }; for (int i = 0; i < 3; i++) // 遍历行 {for (int j = 0; j < 3; j++) // 遍历列{printf("%d ", matrix[i][j]);}printf("\n"); }
输出:
1 2 3
4 5 6
7 8 9
数组名
数组名 == 数组的首元素地址 == 数组的首行地址
printf(“%p\n",arr);== printf("%p\n",&arr[0][0]); == printf("%p\n",arr[0]):
注:
arr[0][0]
的前面一定要有&
符号。
#include <stdio.h>int main()
{int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 };printf("a = %p\n", a);printf("a[0] = %p\n", a[0]);printf("&a[0][0] = %p\n", &a[0][0]);printf("a[0][0] = %p\n", a[0][0]);return 0;
}
输出:
a = 00000072972FF648 a[0] = 00000072972FF648 &a[0][0] = 0000003750AFFB58 a[0][0] = 0000000000000001
二维数组的常用数据
二维数组数组的大小:
sizeof(arr)
二维数组一行的大小:sizeof(arr[0])
二维数组一个元素的大小:sizeof(arr[0][0])
二维数组的行数:sizeof(arr)/ sizeof(arr[0])
二维数组的列数:sizeof(arr[0])/ sizeof(arr[0][0])
二维数组元素的个数 :
sizeof(arr) / sizeof(arr[0][0])
#include <stdio.h>int main() {int arr[3][3] = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};for (size_t i = 0; i < 3; i++) // 行{for (size_t j = 0; j < 3; j++) // 列{printf("%d ", arr[i][j]);}printf("\n");}printf("二维数组数组的大小:%u\n", sizeof(arr));printf("二维数组一行的大小:%u\n", sizeof(arr[0]));printf("二维数组一个元素的大小:%u\n", sizeof(arr[0][0]));printf("二维数组的行数:%u\n", sizeof(arr) / sizeof(arr[0]));printf("二维数组的列数:%u\n", sizeof(arr[0]) / sizeof(arr[0][0]));printf("二维数组元素的个数:%u\n", sizeof(arr) / sizeof(arr[0][0]));return 0; }
输出:
1 2 3
4 5 6
7 8 9
二维数组数组的大小:36
二维数组一行的大小:12
二维数组一个元素的大小:4
二维数组的行数:3
二维数组的列数:3
二维数组元素的个数:9
强化训练
学生成绩统计与分析
#include <stdio.h>int main()
{//二维数组:五行、三列//行代表学生 列代表科目float a[5][3] = { { 80, 75, 56 }, { 59, 65, 71 }, { 59, 63, 70 }, { 85, 45, 90 }, { 76, 77, 45 } };int i, j, person_low[3] = { 0 };float s = 0, lesson_aver[3] = { 0 };for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){s = s + a[j][i];if (a[j][i] < 60){person_low[i]++;}}lesson_aver[i] = s / 5;s = 0;}printf("各科的平均成绩:\n");for (i = 0; i < 3; i++){printf("%.2f\n", lesson_aver[i]);}printf("各科不及格的人数:\n");for (i = 0; i < 3; i++){printf("%d\n", person_low[i]);}return 0;
}
输出:
各科的平均成绩:
71.80
65.00
66.40
各科不及格的人数:
2
1
2
多维数组
多维数组的定义
三维数组的定义语法:
数据类型 数组名[层数][行数][列数];
多维数组的定义语法:
数据类型 数组名[维度1大小][维度2大小]...[维度N大小];
数据类型
:数组中每个元素的类型。(例如:int
、float
、char
等)数组名
:数组的标识符。维度大小
:每个维度的大小。(必须是一个常量)int matrix[3][3]; // 定义一个3x3的二维数组 float cube[2][3][4]; // 定义一个2x3x4的三维数组
int a[3][4][5];
:定义了一个三维数组。
- 数组的名字是a,数组的长度为3
- 每个数组的元素又是一个二维数组,这个二维数组的长度是4
- 并且这个二维数组中的每个元素又是一个一维数组,这个一维数组的长度是5,元素类型是int
#include <stdio.h>int main()
{//int a[3][4][5] ;//定义了一个三维数组,有3个二维数组int[4][5]int a[3][4][5] = { { //第一层{ 1, 2, 3, 4, 5 },{ 6, 7, 8, 9, 10 }, { 0 }, { 0 }}, {//第二层{ 0 },{ 0 }, { 0 }, { 0 }},{//第三层{ 0 },{ 0 },{ 0 },{ 0 } } };int i, j, k;for (i = 0; i < 3; i++){for (j = 0; j < 4; j++){for (k = 0; k < 5; k++){//添加访问元素代码printf("%d ", a[i][j][k]);}printf("\n");}printf("\n");}return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
多维数组的初始化
多维数组可以在
定义时初始化
,也可以在定义后逐个赋值
定义时初始化
1.完全初始化
- 使用嵌套的大括号
{}
初始化多维数组。int cube[2][3][4] = {{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}},{{13, 14, 15, 16},{17, 18, 19, 20},{21, 22, 23, 24}} };
2.部分初始化
- 如果初始化时未指定所有元素的值,剩余元素会自动初始化为
0
int cube[2][3][4] = {{{1, 2},{5, 6},{9, 10}},{{13, 14},{17, 18},{21, 22}} };
- 未初始化的元素为
0
3.省略数组大小
- 可以省略第一个维度(行数)的大小,但必须指定第二个维度(列数)的大小。编译器会根据初始化的数据自动推断行数。
#include <stdio.h>int main() {// 定义并初始化三维数组,省略层数int arr[][3][4] = {{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}},{{13, 14, 15, 16},{17, 18, 19, 20},{21, 22, 23, 24}}};// 计算层数int layers = sizeof(arr) / sizeof(arr[0]);// 遍历三维数组并打印元素for (int i = 0; i < layers; i++) // 层{printf("第 %d 层:\n", i + 1);for (int j = 0; j < 3; j++) // 行{for (int k = 0; k < 4; k++) // 列{printf("%2d ", arr[i][j][k]);}printf("\n");}printf("\n");}return 0; }
输出:
第 1 层:1 2 3 45 6 7 89 10 11 12第 2 层: 13 14 15 16 17 18 19 20 21 22 23 24
定义后赋值
- 逐个为多维数组的元素赋值。
int cube[2][3][4]; cube[0][0][0] = 1; cube[0][0][1] = 2; cube[0][0][2] = 3; cube[0][0][3] = 4; cube[0][1][0] = 5; cube[0][1][1] = 6; cube[0][1][2] = 7; cube[0][1][3] = 8; cube[0][2][0] = 9; cube[0][2][1] = 10; cube[0][2][2] = 11; cube[0][2][3] = 12; cube[1][0][0] = 13; cube[1][0][1] = 14; cube[1][0][2] = 15; cube[1][0][3] = 16; cube[1][1][0] = 17; cube[1][1][1] = 18; cube[1][1][2] = 19; cube[1][1][3] = 20; cube[1][2][0] = 21; cube[1][2][1] = 22; cube[1][2][2] = 23; cube[1][2][3] = 24;
多维数组的访问
多维数组的元素通过多个索引访问,索引从
0
开始。int cube[2][3][4] = {{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}},{{13, 14, 15, 16},{17, 18, 19, 20},{21, 22, 23, 24}} };printf("%d\n", cube[1][2][3]); // 输出第二层第三行第四列的元素:24
多维数组的遍历
可以使用嵌套循环遍历多维数组中的所有元素。
int cube[2][3][4] = {{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}},{{13, 14, 15, 16},{17, 18, 19, 20},{21, 22, 23, 24}} }; for (int i = 0; i < 2; i++) // 遍历第一维 {for (int j = 0; j < 3; j++) // 遍历第二维{for (int k = 0; k < 4; k++) // 遍历第三维{printf("%d ", cube[i][j][k]);}printf("\n");}printf("\n"); }
输出:
1 2 3 4 5 6 7 8 9 10 11 1213 14 15 16 17 18 19 20 21 22 23 24
👨💻 博主正在持续更新C语言基础系列中。
❤️ 如果你觉得内容还不错,请多多点赞。⭐️ 如果你觉得对你有帮助,请多多收藏。(防止以后找不到了)
👨👩👧👦
C语言基础系列
持续更新中~,后续分享内容主要涉及C++全栈开发
的知识,如果你感兴趣请多多关注博主。
相关文章:
C语言基础之【数组和字符串】(上)
C语言基础之【数组和字符串】(上) 概述一维数组一维数组的定义一维数组的初始化一维数组的访问一维数组的遍历数组名一维数组的常用数据强化训练一维数组的最值一维数组的逆置一维数组的排序(冒泡排序) 二维数组二维数组的定义二维…...
Maven插件—flatten-maven-plugin:工程模块统一版本依赖
文章目录 前言一、认识flatten-maven-plugin插件二、如何使用flatten-maven-plugin插件?未使用flatten-maven-plugin插件之前的情况描述配置flatten-maven-plugin插件步骤1:最外层父模块安装插件&配置版本变量步骤2:各个自模块使用版本使…...
Linux系统 环境变量
环境变量 写在前面概念查看环境变量main函数的参数argc & argvenv bash环境变量 写在前面 对于环境变量,本篇主要介绍基本概念及三四个环境变量 —— PATH、HOME、PWD。其中 PATH 作为 “ 敲门砖 ”,我们会更详细讲解;理解环境变量的全局…...
TAPEX:通过神经SQL执行器学习的表格预训练
摘要 近年来,语言模型预训练的进展通过利用大规模非结构化文本数据取得了巨大成功。然而,由于缺乏大规模高质量的表格数据,在结构化表格数据上应用预训练仍然是一个挑战。本文提出了TAPEX,通过在一个合成语料库上学习神经SQL执行…...
Ruby:从宝石到编程语言的奇妙联系(中英双语)
Ruby:从宝石到编程语言的奇妙联系 在珠宝世界中,红宝石(Ruby)是一种象征热情、力量和高贵的珍贵宝石;而在编程世界中,Ruby则是一门灵活、优雅且富有创造力的编程语言。那么,这两者究竟有何联系…...
RLHF中的on-policy和off-policy的区别
在LLM(大语言模型)和RLHF(基于人类反馈的强化学习)中,on-policy和off-policy的主要区别在于数据的来源和策略更新的方式。以下是两者的详细对比以及各自的典型算法: On-policy 和 Off-policy 的区别 特性…...
计算机考研复试上机02
目录 3、排序 1)排序(华中科技大学复试上机题) 2)成绩排序(清华大学复试上机题) 3)特殊排序(华中科技大学复试上机题) 4)整数奇偶排序(北京大学复试上机题) 5)小白鼠排队(北京大学复试上机题) 4、查找 1)找 x(哈尔滨工业大学复试上机题) 2)查找(北…...
利用ETL工具进行数据挖掘
ETL的基本概念 数据抽取(Extraction):从不同源头系统中获取所需数据的步骤。比如从mysql中拿取数据就是一种简单的抽取动作,从API接口拿取数据也是。 数据转换(Transformation):清洗、整合和转…...
02DevOps基础环境准备
准备两台Linux的操作系统,最简单的方式就是在本机上使用虚拟机搭建两个操作系统(实际生产环境是两台服务器,虚拟机的方式用于学习使用) 我搭建的两台服务器的ip分别是192.168.1.10、192.168.1.11 192.168.1.10服务器用于安装doc…...
Kafka 入门与实战
一、Kafka 基础 1.1 创建topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test --create 1.2 查看消费者偏移量位置 kafka-consumer-groups.bat --bootstrap-server localhost:9092 --describe --group test 1.3 消息的生产与发送 #生产者 kafka-cons…...
VM虚拟机安装群晖系统
下载群晖系统 https://download.csdn.net/download/hmxm6/90351935 安装群晖连接软件 synology-assistant-6.2-24922(在上面的压缩包里面) 准备好VM虚拟机 创建群晖虚拟机 打开下载下来的虚拟机 添加硬盘 选择类型 创建新的磁盘 指定容量 指定存储文件 完成硬盘添加…...
关于ESP-IDF 5.4 中添加第三方组件esp32-camera找不到文件,编译错误解决办法(花了一天时间解决)
最近需要使用ESP32-S3-CAM 的OV2640摄像头采集图像,为了加速开发进度,于是选择了esp32-camera组件,该组件不是官方组件,需要自己git clone。但在为项目添加esp32-camera组件时,一直编译错误,找不到头文件&a…...
【C++】C++11
目录 C11简介 统一的列表初始化 {}初始化 std::initializer_list 声明 auto decltype nullptr 范围for循环 智能指针 STL中的一些变化 右值引用和移动语义 左值引用和右值引用 右值引用的意义 完美转发 lambda表达式 新的类功能 可变参数模版 包装器 func…...
Intellij IDEA如何查看当前文件的类
快捷键:CtrlF12,我个人感觉记快捷键很麻烦,知道具体的位置更简单,如果忘了快捷键(KeyMap)看一下就记起来了,不需要再Google or Baidu or GPT啥的,位置:Navigate > Fi…...
CF 278A.Circle Line
题目分析 输入n个数据作为路径,求从a到b的最短距离,需要将其相成一个圆圈,既可以从小往大走又可以从大往小走 思路分析 依然将数据存为数组,通过下标进行操作,既然说了有两种方式那就计算两种方式哪个更快就输出谁 代…...
Naive UI去掉n-select下拉框边框,去掉n-input输入框边框
1、第一种通过js去掉 <template><div><div style"margin-top:10px;width: 100%;"><dade-descriptions><tr><dade-descriptions-item label"代理名称"><dade-input placeholder"代理名称"></dade-…...
(文末提供数据集下载)ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练
文章目录 (文末提供数据集下载)ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练目标项目概述代码结构概述1. **主要类和文件**2. **命名空间和使用指令**3. **数据类 (TransactionObservation)**4. **主程序入口 (Main 方法)**5. **数据预处理 (DataPrepr…...
疯狂SQL转换系列- SQL for Milvs2.4
鉴于Milvus仍在不停的迭代新版本,推出新功能,其SDK目前并不稳定。目前其2.4版本的SDK接口已与之前的2.2版本有了较大的差别,功能上也有了一定的调整。为此,我们重新提供了针对[Milvus2.4](https://github.com/colorknight/moql-tr…...
C++的 I/O 流
本文把复杂的基类和派生类的作用和关系捋出来,具体的接口请参考相关文档 C的 I/O 流相关的类,继承关系如下图所示 https://zh.cppreference.com/w/cpp/io I / O 的概念:内存和外设进行数据交互称为 I / O ,例如:把数…...
基于ansible部署elk集群
ansible部署 ELK部署 ELK常见架构 (1)ElasticsearchLogstashKibana:这种架构是最常见的一种,也是最简单的一种架构,这种架构通过Logstash收集日志,运用Elasticsearch分析日志,最后通过Kibana中…...
4.Python字符串和列表:字符串输入、字符串输出、下标和切片、字符串常见函数、列表(list)、列表的循环遍历、列表的增删改查、列表的嵌套、列表的切片
1. Python 字符串 1.1 字符串输入 input() 函数用于从用户获取字符串输入。它总是返回一个字符串类型的值。 # 从用户输入字符串 name input("请输入你的名字:") print(f"你好, {name}")1.2 字符串输出 字符串的输出通常使用 print() 函数…...
51单片机之使用Keil uVision5创建工程以及使用stc-isp进行程序烧录步骤
一、Keil uVision5创建工程步骤 1.点击项目,新建 2.新建目录 3.选择目标机器,直接搜索at89c52选择,然后点击OK 4.是否添加起吊文件,一般选择否 5.再新建的项目工程中添加文件 6.选择C文件 7.在C文件中右键,添加…...
Redis - 全局ID生成器 RedisIdWorker
文章目录 Redis - 全局ID生成器 RedisIdWorker一、引言二、实现原理三、代码实现代码说明 四、使用示例示例说明 五、总结 Redis - 全局ID生成器 RedisIdWorker 一、引言 在分布式系统中,生成全局唯一ID是一个常见的需求。传统的自增ID生成方式在分布式环境下容易出…...
Linux ftrace 内核跟踪入门
文章目录 ftrace介绍开启ftraceftrace使用ftrace跟踪指定内核函数ftrace跟踪指定pid ftrace原理ftrace与stracetrace-cmd 工具KernelShark参考 ftrace介绍 Ftrace is an internal tracer designed to help out developers and designers of systems to find what is going on i…...
Visual Studio(VS)没有显示垂直滚轮or垂直滚轮异常显示
前言: 前段时间,我换上了新电脑。满心欢喜地安装好 VS,准备大干一场时,却发现了一个小麻烦 —— 垂直滚轮显示异常(如图 1)。这种显示方式实在让我难以适应,每一次操作都觉得别扭。 于是&#…...
大数据数仓实战项目(离线数仓+实时数仓)3
1.课程内容和课程目标 2.订单时间维度指标需求分析 根据时间数据,生成一个时间维度表,我们后面还可以去复用这个时间维度表 3.使用kettle生成日期维度数据 Hive创建日期维度表 使用Kettle构建以下组件结构图 使用kettle生成日期维度数据插入到我们的hi…...
通过acme生成与续签ssl证书,并部署到nginx
通过acme生成与续签ssl证书,并部署到nginx 介绍 官方介绍: acme.sh 实现了 acme 协议,可以从 ZeroSSL,Lets Encrypt 等 CA 生成免费的证书。 安装 acme.sh 1. curl方式 curl https://get.acme.sh | sh -s emailmyexample.com…...
c语言对应汇编写法(以中微单片机举例)
芯片手册资料 1. 赋值语句 C语言: a 5; b a; 汇编: ; 立即数赋值 LDIA 05H ; ACC 5 LD R01,A ; R01 ACC(a5); 寄存器间赋值 LD A,R01 ; ACC R01(读取a的值) LD R02,A ; R02 ACC&…...
React基础内容(面试一)
React大厂常见的面试题目涉及多个方面,包括React的基本概念、组件、状态管理、生命周期、性能优化等。以下是对这些面试题目的详细解析: 一、React基本概念 解释React是什么以及它的主要特点 React是一个用于构建用户界面的JavaScript库,由F…...
2025年软件测试五大趋势:AI、API安全、云测试等前沿实践
随着软件开发的不断进步,测试方法也在演变。企业需要紧跟新兴趋势,以提升软件质量、提高测试效率,并确保安全性,在竞争激烈的技术环境中保持领先地位。本文将深入探讨2025年最值得关注的五大软件测试趋势。 Parasoft下载https://…...
常用工具类——Collections集合框架
常用工具类——Collections集合框架 Collections 是 JDK 提供的一个工具类,提供了一系列静态方法,分类来复习! 1.排序操作 reverse(List list) :反转顺序shuffle(List list) : 洗牌,将顺序打乱sort(List list) &…...
【大数据技术】搭建完全分布式高可用大数据集群(ZooKeeper)
搭建完全分布式高可用大数据集群(ZooKeeper) apache-zookeeper-3.8.4-bin.tar.gz注:请在阅读本篇文章前,将以上资源下载下来。 写在前面 本文主要介绍搭建完全分布式高可用集群 ZooKeeper 的详细步骤。 注意: 统一约定将软件安装包存放于虚拟机的/software目录下,软件…...
Docker Desktop安装kubernetes时一直在Starting:Kubernetes failed to start
原因:由于墙的问题,导致拉取国外的K8s镜像失败 解决: 下载 k8s-for-docker-desktop 选中自己的kubernetes 版本 下载zip包 PowerShell运行load_images.ps1文件 重启docker kubernetes运行成功...
物流中的物联网:其含义、应用和优势
随着世界联系日益紧密,物流格局正经历重大变革。科技已成为供应链管理的支柱,推动物流公司迈入效率与连通性兼具的新时代。 物联网(IoT)是一股变革性力量,重塑着物流与运输行业的架构。物联网在物流领域并非昙花一现的…...
Axure设计教程:动态排名图(中继器实现)
一、开篇 在Axure原型设计中,动态图表是展示数据和交互效果的重要元素。今天,我们将学习如何使用中继器来创建一个动态的排名图,该图表不仅支持自动轮播,还可以手动切换,极大地增强了用户交互体验。此教程旨在提供一个…...
【人工智能】掌握图像风格迁移:使用Python实现艺术风格的自动化迁移
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 图像风格迁移(Image Style Transfer)是一种基于深度学习的计算机视觉技术,通过将一张图像的内容与另一张图像的艺术风格结合,生成一幅具…...
# C指针地址CUP寄存器访问IO内存映射
C指针地址&CUP寄存器访问&IO内存映射 在裸机编程中,C语言可以像汇编语言一样直接操作芯片寄存器地址进行读取和写入,主要是由于以下几个原因: 1. 裸机环境下没有操作系统的干预 裸机编程是指直接在硬件上运行程序,没有…...
UE5 蓝图学习计划 - Day 14:搭建基础游戏场景
在上一节中,我们 确定了游戏类型,并完成了 项目搭建、角色蓝图的基础设置(移动)。今天,我们将进一步完善 游戏场景,搭建 地形、墙壁、机关、触发器 等基础元素,并添加角色跳跃功能,为…...
浅尝yolo11全程记录1-准备环境+官网模型推理(个人备份)
准备工作(虚拟环境、导入项目) 安装Anaconda 主要是为了创建和管理虚拟环境,在pycharm里按照项目里的requirments.txt安装依赖的时候,使用虚拟环境会好很多(我记得不用Anaconda也可以直接在pycharm的terminal里头创建…...
用 Python 给 Excel 表格截图(20250207)
我搜索了网络上的方案,感觉把 Excel 表格转换为 HTML 再用 platwright 截图是比较顺畅的路径,因为有顺畅的工具链。如果使用的是 Windows 系统则不需要阅读此文,因为 win32com 库更方便。这篇文章中 Excel 转 HTML 的方案,主要弥补…...
Office/WPS接入DS等多个AI工具,开启办公新模式!
在现代职场中,Office办公套件已成为工作和学习的必备工具,其功能强大但复杂,熟练掌握需要系统的学习。为了简化操作,使每个人都能轻松使用各种功能,市场上涌现出各类办公插件。这些插件不仅提升了用户体验,…...
智能化转型2.0:从“工具应用”到“价值重构”
过去几年,“智能化”从一个模糊的概念逐渐成为企业发展的核心议题。2024年,随着生成式AI、大模型、智能体等技术的爆发式落地,中国企业正式迈入智能化转型的2.0时代。这一阶段的核心特征是从单一场景的“工具应用”转向全链条的“价值重构”&…...
深度整理总结MySQL——索引工作原理
B树索引数据结构 前言什么样的索引数据结构是好的搜索速度要求支持范围查找寻求适合查找的算法寻求合适的数据结构二叉查找树自平衡二叉树B树B树数据结构B与B树比较 总结 前言 相信你在面试时,通常会被问到“什么是索引?”而你一定要能脱口而出…...
基于asr的所见即可说方案
年前写的文章对所见即可说方案进一步调研-CSDN博客,针对rk3568定制版,进行了Accessibility实现所见即可说功能的验证与调研,结论是不可行。 最终解决方案是:结合科大讯飞的AI大模型智能助手,使用rk3588板(…...
【截图】selenium自动通过浏览器截取指定元素div的图片
【截图】selenium自动通过浏览器截取指定元素div的图片 思路 截取完整网页截图 通过元素的坐标 截图到指定位置的图片 前提是已经获取到 driver 了 # 定位目标divtarget_div driver.find_element(By.CLASS_NAME, headlines-right)# 获取div的位置和大小location target_div…...
CSS入门学习笔记(一)
学习视频:https://www.bilibili.com/video/BV1zN2UYoEEo/ 目录 基本介绍语法引入方式内联样式(行内样式)内部样式外部样式 选择器四种选择器全局选择器元素选择器类选择器id选择器 合并选择器选择器的优先级 字体属性colorfont-sizefont-weig…...
docker安装es及分词器ik
系统是macos,docker是docker-desktop 拉取镜像 docker pull bitnami/elasticsearch 启动docker镜像 docker create -e "discovery.typesingle-node" \ --name elasticsearch1 -p 9200:9200 -p 9300:9300 \ bitnami/elasticsearch:8.17.1 测试是否好…...
11. 9 构建生产级聊天对话记忆系统:从架构设计到性能优化的全链路指南
构建生产级聊天对话记忆系统:从架构设计到性能优化的全链路指南 关键词: 聊天对话记忆系统、多用户会话管理、LangChain生产部署、Redis记忆存储、高并发对话系统 一、服务级聊天记忆系统核心需求 多用户隔离:支持同时处理数千个独立对话持久化存储:对话历史不因服务重启丢…...
SpringBoot启动源码剖析:从入口到容器的诞生
文章目录 SpringBoot启动的核心入口SpringApplication的初始化SpringBoot的启动流程1. 准备环境(Environment)2. 创建应用上下文(ApplicationContext)3. 刷新应用上下文(Refresh Context)4. 调用Runner接口…...
Day38【AI思考】-彻底打通线性数据结构间的血脉联系
文章目录 **彻底打通线性数据结构间的血脉联系****数据结构家族谱系图****一、线性表(老祖宗的规矩)****核心特征** **二、嫡系血脉解析**1. **数组(规矩森严的长子)**2. **链表(灵活变通的次子)** **三、庶…...