import{_ as s,c as i,o as a,a6 as n}from"./chunks/framework.CZKtKhAm.js";const l="/c/assets/1.CvTjP5jN.png",h="/c/assets/2.BR4TvWzU.png",p="/c/assets/3.hr3pCY5b.png",k="/c/assets/4.CgvWfxq4.png",t="/c/assets/5.DSekQATc.png",e="/c/assets/6.DjtEKfCa.png",r="/c/assets/7.BTWPdsCm.png",E="/c/assets/8.EoNXwZXz.png",d="/c/assets/9.iU-LaFqX.png",g="/c/assets/10.DYoXU9E6.jpg",y="/c/assets/11.DWDH3yqc.png",F="/c/assets/12.BvBjpbbE.png",c="/c/assets/13.CmPe90qp.png",b="/c/assets/14.MepLJvOt.jpg",u="/c/assets/15.CZUo3kuI.png",C="/c/assets/16.t7xuKRuB.png",o="/c/assets/17.Bkm40EoU.png",B="/c/assets/18.D0Mtsawg.png",m="/c/assets/19.C-mmUOKp.png",A="/c/assets/20.BvSSXPdI.png",D="/c/assets/21.uaya_nVR.png",N=JSON.parse('{"title":"第一章:数组的概念","description":"","frontmatter":{},"headers":[],"relativePath":"notes/01_c-basic/05_xdx/index.md","filePath":"notes/01_c-basic/05_xdx/index.md","lastUpdated":1721811495000}'),v={name:"notes/01_c-basic/05_xdx/index.md"},q=n(`
#include <stdio.h>
int main(){
double num1 = 0;
double num2 = 0;
double num3 = 0;
...
printf("请输入第 1 个员工的工资:");
scanf("%lf",&num1);
printf("请输入第 2 个员工的工资:");
scanf("%lf",&num2);
printf("请输入第 3 个员工的工资:");
scanf("%lf",&num3);
...
return 0;
}
数据
全部存储到一个容器(数组)
中进行统一管理,并进行其它的操作,如:求最值、求平均值等,如下所示:#include <stdio.h>
int main(){
// 声明数组
double nums[50];
// 数组的长度
int length = sizeof(nums) / sizeof(double);
// 使用 for 循环向数组中添加值
for(int i = 0;i < length;i++){
printf("请输入第 &d 个员工的工资:",i);
scanf("%lf",&num[i]);
}
// 其它操作,如:求最值,求平均值等
...
return 0;
}
商品信息
都存储到一个容器(数组)
中,进行统一管理;那么,之后的数据处理将会非常方便。生活中的容器
:水杯(装水、饮料的容器)、衣柜(装衣服等物品的容器)、集装箱(装货物等物品的容器)。程序中的容器
:将多个数据存储到一起,并且每个数据称为该容器中的元素。相同数据类型
的数据
按照一定的顺序排序的集合
,并使用一个标识符
命名,以及通过编号(索引,亦称为下标)
的方式对这些数据进行统一管理。数组名
:本质上是一个标识符常量,命名需要符合标识符规则和规范。元素
:同一个数组中的元素必须是相同的数据类型。索引(下标)
:从 0 开始的连续数字。数组的长度
:就是元素的个数。连续的空间
,占据空间的大小,取决于数组的长度和数组中元素的类型。数组的长度一旦确定,就不能更改
。数据类型 数组名[元素个数|长度];
NOTE
#include <stdio.h>
int main() {
// 先指定元素的个数和类型,再进行初始化
// 定义数组
int arr[3];
// 给数组元素赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
return 0;
}
数据类型 数组名[元素个数|长度] = {元素1,元素2,...}
NOTE
小于
数组声明的长度,那么就会从数组开始位置依次赋值,不够的就补 0 。等于
数组的长度。技巧:
聚合初始化
功能,即:示例:静态部分初识化
#include <stdio.h>
int main() {
// 定义数组和部分初始化:
// 会将给定的值从数组的开始位置一个个的赋值,没有赋值的地方,用 0 填充
int arr[5] = {1, 2};
return 0;
}
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[5] = {1, 2, 3, 4, 5};
return 0;
}
数据类型 数组名[] = {元素1,元素2,...}
NOTE
没有给出数组中元素的个数,将由系统根据初始化的元素,自动推断出数组中元素的个数。
#include <stdio.h>
int main() {
// 指定元素的类型,不指定元素个数,同时进行初始化
int arr[] = {1, 2, 3, 4, 5};
return 0;
}
数组名[索引|下标];
NOTE
假设数组 arr
有 n 个元素,如果使用的数组的下标 < 0
或 > n-1
,那么将会产生数组越界访问,即超出了数组合法空间的访问;那么,数组的索引范围是 [0,arr.length - 1]
。
#include <stdio.h>
int main() {
// 先指定元素的个数和类型,再进行初始化
// 定义数组
int arr[3];
// 给数组元素赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
// 访问数组元素
printf("arr[0] = %d\\n", arr[0]); // arr[0] = 10
printf("arr[1] = %d\\n", arr[1]); // arr[1] = 20
printf("arr[2] = %d\\n", arr[2]); // arr[2] = 30
return 0;
}
#include <stdio.h>
int main() {
// 定义数组和部分初始化:
// 会将给定的值从数组的开始位置一个个的赋值,没有赋值的地方,用 0 填充
int arr[5] = {1, 2};
// 访问数组元素
printf("arr[0] = %d\\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\\n", arr[2]); // arr[2] = 0
printf("arr[3] = %d\\n", arr[3]); // arr[3] = 0
printf("arr[4] = %d\\n", arr[4]); // arr[4] = 0
return 0;
}
#include <stdio.h>
int main() {
// 指定元素的类型,不指定元素个数,同时进行初始化
int arr[] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\\n", arr[4]); // arr[4] = 5
return 0;
}
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[5] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\\n", arr[4]); // arr[4] = 5
return 0;
}
NOTE
#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[] = {1, 2, 3, 4, 5};
// 访问数组元素
printf("arr[0] = %d\\n", arr[0]); // arr[0] = 1
printf("arr[1] = %d\\n", arr[1]); // arr[1] = 2
printf("arr[2] = %d\\n", arr[2]); // arr[2] = 3
printf("arr[3] = %d\\n", arr[3]); // arr[3] = 4
printf("arr[4] = %d\\n", arr[4]); // arr[4] = 5
printf("arr[-1] = %d\\n", arr[-1]); // 得到的是不确定的结果
printf("arr[5] = %d\\n", arr[5]); // 得到的是不确定的结果
return 0;
}
数组的长度 = 整个数组的字节长度 ÷ 单个元素的字节长度
。NOTE
声明
或定义
,其长度
就固定
了,不能动态变化
。#include <stdio.h>
int main() {
// 定义数组和全部初始化:数组初始化的元素个数等于数组的长度。
int arr[] = {1, 2, 3, 4, 5};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d \\n", arr[i]);
}
return 0;
}
遍历数组是指按顺序访问数组中的每个元素,以便读取或修改它们,编程中一般使用循环结构对数组进行遍历。
示例:声明一个存储有 12、2、31、24、15、36、67、108、29、51 的数组,并遍历数组所有元素
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, 36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d\\n", arr[i]);
}
return 0;
}
#include <stdio.h>
int main() {
// 定义数组
int arr[10];
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 给数组的每个元素赋值
for (int i = 0; i < length; i++) {
arr[i] = i;
}
// 遍历数组
for (int i = 0; i < length; i++) {
printf("%d\\n", arr[i]);
}
return 0;
}
int arr[] = {1,2,3,4,5};
NOTE
arr
就是记录该数组的首地址,即 arr[0]
的地址。arr[0]
的地址是 0xdea7bff880
,则 arr[1] 的地址 = arr[0] 的地址 + int 字节数(4) = 0xdea7bff880 + 4 = 0xdea7bff884
,依次类推...&arr
或 &arr[0]
等形式获取数组或数组元素的地址,即:#include <stdio.h>
int main() {
// 定义数组
int arr[10];
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 给数组的每个元素赋值
for (int i = 0; i < length; i++) {
arr[i] = i;
}
printf("数组的地址是 = %p\\n", arr);
// 遍历数组
for (int i = 0; i < length; i++) {
printf("数组元素 %d 的地址是 = %p\\n", arr[i], &arr[i]);
}
return 0;
}
C 语言规定,数组一旦声明,数组名指向的地址将不可更改
。因为在声明数组的时候,编译器会自动会数组分配内存地址,这个地址和数组名是绑定的,不可更改。WARNING
如果之后试图更改数组名对应的地址,编译器就会报错。
int num[5]; // 声明数组
// 使用大括号重新赋值是不允许的,必须在数组声明的时候赋值,否则编译将会报错
num = {1,2,3,4,5} ; // 报错
int num[] = {1,2,3,4,5};
// 使用大括号重新赋值是不允许的,必须在数组声明的时候赋值,否则编译将会报错
num = {2,3,4,5,6}; // 报错
int num[5];
num = NULL; // 报错,需要和 Java 区别一下,在 C 中不可以
int a[] = {1,2,3,4,5}
int b[5] = a ; // 报错,需要和 Java 区别一下,在 C 中不可以
需求:计算数组中所有元素的和以及平均数。
示例:
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, 36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 变量保存总和
int sum = 0;
// 遍历数组
for (int i = 0; i < length; i++) {
sum += arr[i];
}
double avg = (double)sum / length;
printf("数组的和为:%d\\n", sum); // 数组的和为:375
printf("数组的平均值为:%.2lf\\n", avg); //数组的平均值为:37.50
return 0;
}
NOTE
思路:
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 定义最大值
int max = arr[0];
// 定义最小值
int min = arr[0];
// 遍历数组
for (int i = 0; i < length; i++) {
if (arr[i] >= max) {
max = arr[i];
}
if (arr[i] <= min) {
min = arr[i];
}
}
printf("数组的最大值为:%d\\n", max); // 数组的最大值为:108
printf("数组的最小值为:%d\\n", min); // 数组的最小值为:-36
return 0;
}
需求:统计数组中某个元素出现的次数,要求:使用无限循环,如果输入的数字是 0 ,就退出。
示例:
#include <stdio.h>
int main() {
// 定义数组并初始化
int arr[] = {12, 2, 31, 24, 2, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(int);
// 遍历数组
printf("当前数组中的元素是:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
// 无限循环
while (true) {
// 统计的数字
int num;
// 统计数字出现的次数
int count = 0;
// 输入数字
printf("请输入要统计的数字:");
scanf("%d", &num);
// 0 作为结束条件
if (num == 0) {
break;
}
// 遍历数组,并计数
for (int i = 0; i < length; i++) {
if (arr[i] == num) {
count++;
}
}
printf("您输入的数字 %d 在数组中出现了 %d 次\\n", num, count);
}
return 0;
}
需求:将数组 a 中的全部元素复制到数组 b 中。
示例:
#include <stdio.h>
#define SIZE 10
int main() {
// 定义数组并初始化
int a[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
int b[SIZE];
// 复制数组
for (int i = 0; i < SIZE; i++) {
b[i] = a[i];
}
// 打印数组 b 中的全部元素
for (int i = 0; i < SIZE; i++) {
printf("%d ", b[i]);
}
return 0;
}
NOTE
思路:假设数组一共有 10 个元素,那么:
规律就是 a[i] <--互换--> arr[arr.length -1 -i]
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t SIZE = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
// 交换数组
for (int i = 0; i < SIZE / 2; i++) {
int temp = arr[i];
arr[i] = arr[SIZE - 1 - i];
arr[SIZE - 1 - i] = temp;
}
// 打印交换后的数组
printf("交换后数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
return 0;
}
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, 24, 15, -36, 67, 108, 29, 51};
// 计算数组的长度
size_t SIZE = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
// 交换数组
for (int i = 0, j = SIZE - 1 - i; i < SIZE / 2; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 打印交换后的数组
printf("交换后数组:");
for (int i = 0; i < SIZE; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
return 0;
}
NOTE
思路:从数组的下标 0
开始依次遍历到 length - 1
,如果 i
下标当前的值比 i+1
下标的值大,则交换;否则,就不交换。
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, -24, 15, -36, 67, 891, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
// 移动最大值到数组的最后一个位置
for (int i = 0; i < length - 1; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
// 打印移动之后的数组
printf("移动之后的数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
return 0;
}
NOTE
思路:一层循环,能实现最大值移动到数组的最后;那么,二层循环(控制内部循环数组的长度)就能实现将数组的元素从小到大排序。
#include <stdio.h>
int main() {
// 原始数组
int arr[] = {12, 2, 31, -24, 15, -36, 67, 891, 29, 51};
// 计算数组的长度
size_t length = sizeof(arr) / sizeof(arr[0]);
// 打印原始数组中的全部元素
printf("原始数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
for (int j = 0; j < length - 1; j++) {
for (int i = 0; i < length - 1 - j; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
// 打印移动之后的数组
printf("移动之后的数组:");
for (int i = 0; i < length; i++) {
printf("%d ", arr[i]);
}
printf("\\n");
return 0;
}
我们在数学、物理和计算机科学等学科中学习过一维坐标
、二维坐标
以及三维坐标
。
其中,一维坐标
通常用于描述在线段或直线上的点的位置,主要应用有:
其中,二维坐标
用于描述平面上的点的位置。主要应用包括:
其中,三维坐标用于描述空间中点的位置。主要应用包括:
总而言之,一维、二维和三维坐标系统在不同的领域中各有其重要的应用,从基础数学到高级科学和工程技术,它们帮助我们更好地理解和描述世界的结构和行为。
NOTE
下标
访问到数组中的某个元素,即:0、1、...NOTE
数据类型 数组名[几个⼀维数组元素][每个⼀维数组中有几个具体的数据元素];
NOTE
#include <stdio.h>
int main() {
// 定义二维数组并初始化
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \\n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d ", arr[1][1]);
printf("%d ", arr[1][2]);
printf("%d \\n", arr[1][3]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
数据类型 数组名[行数][列数] = {{元素1,元素2,...},{元素3,...},...}
NOTE
#include <stdio.h>
int main() {
// 定义二维数组并初始化
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \\n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d ", arr[1][1]);
printf("%d ", arr[1][2]);
printf("%d \\n", arr[1][3]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
数据类型 数组名[][列数] = {{元素1,元素2,...},{元素3,...},...}
NOTE
#include <stdio.h>
int main() {
// 定义二维数组
int arr[][4] = {{1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};
// 输出二维数组中的元素
printf("%d ", arr[0][0]);
printf("%d ", arr[0][1]);
printf("%d ", arr[0][2]);
printf("%d \\n", arr[0][3]);
printf("%d ", arr[1][0]);
printf("%d \\n", arr[1][1]);
printf("%d ", arr[2][0]);
printf("%d ", arr[2][1]);
printf("%d ", arr[2][2]);
printf("%d ", arr[2][3]);
return 0;
}
int arr[3][4];
arr
可以看做是 3
个一维数组组成,它们分别是 arr[0]
、arr[1]
、arr[2]
。这 3
个一维数组都各有 4 个元素,如:一维数组 arr[0]
中的元素是 arr[0][0]
、arr[0][1]
、arr[0][2]
、arr[0][3]
,即:NOTE
如果一个二维数组是这么定义的,即:int arr[3][4]
,那么:
行的长度 = sizeof(arr) / sizeof(arr[0])
,因为 arr
是二维数组的总
的内存空间;而 arr[0]
、arr[1]
、arr[2]
是二维数组中一维数组的内存空间 。列的长度 = sizeof(arr[0]) / sizeof(arr[0][0])
,因为arr[0]
、arr[1]
、arr[2]
是二维数组中一维数组的内存空间 ,而 arr[0][0]
、arr[0][1]
、... 是一维数组中元素的内存空间。#include <stdio.h>
int main() {
// 定义二维数组
int arr[][4] = {{1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};
// 获取行列数
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
// 打印二维数组元素
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%d ", arr[i][j]);
}
printf("\\n");
}
return 0;
}
用矩阵形式
(如:3 行 4 列形式)表示二维数组,是逻辑
上的概念,能形象地表示出行列关系。而在内存
中,各元素是连续存放的,不是二维的,是线性
的。
C 语言中,二维数组中元素排列的顺序是按行存放
的。即:先顺序存放第一行的元素,再存放第二行的元素。例如:数组a[3][4]
在内存中的存放,如下所示:
需求:现在有三个班,每个班五名同学,用二维数组保存他们的成绩,并求出每个班级平均分、以及所有班级平均分,数据要求从控制台输入。
示例:
#include <stdio.h>
int main() {
// 定义二维数组,用于保存成绩
double arr[3][5];
// 获取二维数组的行数和列数
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
// 从控制台输入成绩
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("请输入第%d个班级的第%d个学生的成绩:", i + 1, j + 1);
scanf("%lf", &arr[i][j]);
}
}
// 总分
double totalSum = 0;
// 遍历数组,求总分和各个班级的平均分
for (int i = 0; i < row; i++) {
double sum = 0;
for (int j = 0; j < col; j++) {
totalSum += arr[i][j];
sum += arr[i][j];
}
printf("第%d个班级的总分为:%.2lf\\n", i + 1, sum);
printf("第%d个班级的平均分为:%.2lf\\n", i + 1, sum / col);
}
printf("所有班级的总分为:%.2lf\\n", totalSum);
printf("所有班级的平均分为:%.2lf\\n", totalSum / (row * col));
return 0;
}