第四节 数组

news2024/11/12 13:15:37

第四节 数组



目录

  • 一. 一维数组的创建和初始化
    • 1. 一维数组的创建
    • 2. 数组的初始化
    • 3. 一维数组的使用
    • 4. 一维数组在内存中的存储
  • 二. 二维数组的创建和初始化
    • 1. 二维数组的创建
    • 2. 二维数组的初始化
    • 3. 二维数组的使用
    • 4. 二维数组在内存中的存储
  • 三. 数组越界
  • 四. 数组作为函数参数
    • 1. 冒泡排序函数的错误设计
    • 2. 数组名是什么?
    • 3. 冒泡排序函数的正确设计
  • 五. 数据实例
    • 1. 三子棋
    • 2. 扫雷



本章重点:
一维数组的创建和初始化
一维数组的使用
一维数组在内存中的存储
二维数组的创建和初始化
二维数组的使用
二维数组在内存中的存储
数组越界
数组作为函数参数
数组的应用实例1:三子棋
数组的应用实例2:扫雷游戏


一. 一维数组的创建和初始化

1. 一维数组的创建

数组是一组相同类型元素的集合。

数组的创建方式:

//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小

数组创建的实例:

#include<stdio.h>

int main()
{
	int arr[5];
	int arr2[3 + 2];

	char arr3[8];

	int n = 0;
	scanf("%d", &n);
	int arr4[n];

	return 0;
}

注意:C99 之前数组只能是常量指定大小,C99 之后引用了变长数组的概念,数组的大小是可以使用变量指定的。但是VS2022、2019 不支持C99的边长数组的。变长数组是不能初始化的。


2. 数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。

数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。

代码如下:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3 };//不完全初始化,剩余的元素默认初始化为0
	int arr2[5] = { 1,2,3,4,5 };
	char arr4[3] = { 'a',98, 'c' };

	int arr3[] = { 1,2,3 };

	int arr5[10] = { 0 };
	int arr6[] = { 0 };

	char arr7[] = { 'a', 'b', 'c' };
	char arr8[] = "abc";

	return 0;
}


3. 一维数组的使用

对于数组的使用我们之前介绍了一个操作符: [] ,下标引用操作符。它其实就数组访问的操作符。

代码如下:

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	            //0 1 2 3 4 5 6 7 8 9
	//printf("%d\n", arr[6]);
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	
	for (i = 0; i < sz; i++)
	{
		arr[i] = 10 - i;
	}

	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

总结:
数组是使用下标来访问的,下标是从0开始。
数组的大小可以通过计算得到。


4. 一维数组在内存中的存储

接下来我们探讨数组在内存中的存储。

代码如下:

#include<stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	            //0 1 2 3 4 5 6 7 8 9
	//printf("%d\n", arr[6]);
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	
	for (i = 0; i < sz; i++)
	{
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}

	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。

由此可以得出结论:
数组在内存中是连续存放的。
随着下标的增长,地址是由低到高变化的。


二. 二维数组的创建和初始化

1. 二维数组的创建

#include <stdio.h>
int main()
{
	int arr[3][5];
	char arr1[3][5];
	return 0;
}


2. 二维数组的初始化

#include <stdio.h>
int main()
{
	int arr[3][5] = { 0 };//不完全初始化
	int arr1[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	int arr2[][10] = { {1,2},{2,3,4},{5,5,5} };
	return 0;
}

二维数组如果初始化了,行可以省略,列不能省略


3. 二维数组的使用

二维数组的使用也是通过下标

代码如下:

#include<stdio.h>
int main()
{
	int arr[3][5] = { {1,2},{4,5},{6,7,8} };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		
		for (j = 0; j < 5; j++)
		{
			arr[i][j] = i * 5 + j+1;
		}
	}
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述


4. 二维数组在内存中的存储

#include<stdio.h>
int main()
{
	int arr[3][5] = { {1,2},{4,5},{6,7,8} };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
		}
	}
	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

二维数组在内存中也是连续存放的

在这里插入图片描述

随着下标的增长,地址由低到高在变化。


三. 数组越界

数组的下标是有范围限制的。

数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。

所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查。

例子如下:

#include<stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    for (i = 0; i <= 10; i++)
    {
        printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
    }
    return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

二维数组的行和列也可能存在越界。


四. 数组作为函数参数

往往我们在写代码的时候,会将数组作为参数传个函数,比如:我要实现一个冒泡排序,将一个整形数组排序。

1. 冒泡排序函数的错误设计

代码如下:

#include <stdio.h>
void sort(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//降序
	//对arr进行排序,排序为升序
	sort(arr);
	//冒泡排序
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

代码虽运行成功,但并没有进行排序,对代码进行调试。

在这里插入图片描述

调试后发现传完数组后,sz的值是1。
由此可见,数组作为函数参数的时候,不是把整个数组传递过去。


2. 数组名是什么?

数组名就是地址,通常来说:数组名是数组首元素的地址

但是有2个例外:
1, sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2, &数组名,这里的数组名表示整个数组,取出的是整个数组的地址
除此之外,所有遇到的数组名都是数组首元素的地址

代码如下:

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0]+1);

	printf("%p\n", &arr);
	printf("%p\n", &arr+1);

	//printf("%d\n", sizeof(arr));//40

	return 0;
}

运行代码成功,结果如下:

在这里插入图片描述


3. 冒泡排序函数的正确设计

代码如下:

#include<stdio.h>
//void sort(int *arr, int sz)
void sort(int arr[], int sz)
{
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };//降序
	//对arr进行排序,排序为升序
	int sz = sizeof(arr) / sizeof(arr[0]);
	sort(arr, sz);//arr这里不是特殊的2种情况,就是数组首元素的地址
	//冒泡排序
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述


五. 数据实例

1. 三子棋

代码详见:https://github.com/danbaku/c-language-learning/tree/main/game_1/game_1


2. 扫雷

代码详见:https://github.com/danbaku/c-language-learning/tree/main/game_2/game_2



本篇博客为本人学习C语言时的详细笔记,如有错误之处,还望各位指正。
文章为原创,如要转载请注明出处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1285185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

梯度上升和随机梯度上升

目录 梯度上升算法&#xff1a; 代码&#xff1a; 随机梯度上升算法&#xff1a; 代码&#xff1a; 实验&#xff1a; 做图代码&#xff1a; 疑问&#xff1a; 1.梯度上升算法不适应大的数据集&#xff0c;改用随机梯度上升更合适。 2.改进过的随机梯度算法&#xff0…

1.nacos注册与发现及源码注册流程

目录 概述nacos工程案例nacos服务注册案例版本说明本地启动 nacos-server搭建 spring cloud alibaba 最佳实践服务注册案例服务订阅案例 nacos注册源码流程源码关键点技巧 结束 概述 通过本文&#xff0c;学会如何确定项目组件版本(减少可能出现的jar包冲突)&#xff0c;nacos…

【Python】创建简单的Python微服务Demo与FastAPI

创建简单的Python微服务Demo与FastAPI 在微服务架构中&#xff0c;通过FastAPI框架创建一个简单的Python微服务Demo涉及多个步骤&#xff0c;包括定义服务、使用框架、进行通信等。在这篇文章中&#xff0c;我们将使用FastAPI框架创建两个简单的微服务&#xff0c;它们通过RES…

12月5日星期二今日早报简报微语报早读

12月5日星期二&#xff0c;农历十月廿三&#xff0c;早报微语早读。 1、国家卫健委&#xff1a;各地基层医卫机构要全面向儿童开放&#xff0c;不得拒诊&#xff1b; 2、五月天演唱会被指假唱&#xff0c;上海文旅局执法总队&#xff1a;已要求五月天演唱会主办方配合调查&am…

The Sandbox 携手 Sandsoft,与 Nuqtah 合作推动沙特阿拉伯的 Web3 发展

新的合作伙伴关系将增强创作者的能力&#xff0c;促进区块链生态系统的包容性。 The Sandbox 及其合作伙伴 Sandsoft 是移动游戏开发商和发行商&#xff0c;也是 AAA 人才驱动的投资者&#xff0c;他们非常高兴地宣布与 Nuqtah 建立新的合作伙伴关系&#xff0c;Nuqtah 是中东和…

MybatisPlus中的使用Wrapper自定义SQL

一、条件构造器 条件构造器提供了一种更加简洁和直观的方式来构建复杂的查询条件。它提供了一组静态方法&#xff0c;用于构建各种类型的查询条件&#xff0c;包括等于、不等于、大于、小于、包含等。使用条件构造器可以避免手动拼接SQL语句的麻烦&#xff0c;提高代码的可读性…

树莓派Python程序开机自启动(Linux下Python程序开机自启动)

前一阵子用python编写了一个驱动I2C程序读写屏幕&#xff0c;输出IP的小程序&#xff0c;程序编好后需要树莓派使能程序开机自启动。其实这些方法对任何Linux系统都适用。 方法一&#xff1a;此方法的缺点是不进入默认pi的账号&#xff0c;甚至不开hdmi开启桌面的话&#xff0…

关于栈的简单理解

1. 栈(Stack) 1.1 文字讲解 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则&a…

IP5316 2.4A 充电、2.4 A 放电、集成 DCP 功能移动电源 SOC

IP5316 2.4A 充电、 2.4 A 放电、集成 DCP 功能移动电源 SOC 简介&#xff1a; IP5316 是一款集成升压转换器、锂电池充电管理、电池电量指示的多功能电源管理 SOC&#xff0c;为移动电源提供完整的电源解决方案。得益于 IP5316 的高集成度与丰富功能&#xff0c;使其在应用时…

零信任组件和实施

零信任是一种安全标准&#xff0c;其功能遵循“从不信任&#xff0c;始终验证”的原则&#xff0c;并确保没有用户或设备受信任&#xff0c;无论他们是在组织网络内部还是外部。简而言之&#xff0c;零信任模型消除了信任组织安全边界内任何内容的概念&#xff0c;而是倡导严格…

外包干了2个月,技术明显退步了...

先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近5年的功能测试&#xff0c;今年11月份&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

JS实现成才网注册系统(网页数据验证)

主代码 <!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"><head><meta http-equiv"Conten…

OpenGL ES 帧缓冲对象介绍和使用示例

一、介绍 1. 帧缓冲对象 默认情况下&#xff0c;OpenGL渲染的目标是屏幕&#xff0c;但如果你不想直接渲染到屏幕上&#xff0c;还需要对渲染结果做某些后期处理、渲染到纹理、阴影映射等操作&#xff0c;便可以使用帧缓冲对象&#xff0c;实现离屏渲染。 帧缓冲对象&#x…

DC电源模块的常见故障有哪些?

BOSHIDA DC电源模块的常见故障有哪些&#xff1f; DC电源模块是电子设备中常见的电源供应模块&#xff0c;它可以将交流电转化为直流电供给设备使用。然而&#xff0c;由于长期的使用和外界环境等因素的影响&#xff0c;DC电源模块也会出现各种故障。下面我们来介绍一下常见的…

【go语言开发】编写单元测试

本文主要介绍使用go语言编写单元测试用例&#xff0c;首先介绍如何编写单元测试&#xff0c;然后介绍基本命令的使用&#xff0c;最后给出demo示例 文章目录 前言命令示例 前言 在go语言中编写单元测试时&#xff0c;使用说明 测试文件命名&#xff1a;在 Go 语言中&#xff0…

蓝桥杯网络安全组竞赛

竞赛规则及说明 选拔赛时长&#xff1a;4h 决赛时长&#xff1a;4h 竞赛形式&#xff1a;线上比赛&#xff1a; 个人赛&#xff1a;一人一机&#xff0c;全程机考 大赛制定竞赛系统&#xff0c;在时间内提交答案到比赛系统&#xff0c;超时无法提交 机器环境&#xff1a; 电脑…

CSRF之pikachu靶场DW

1&#xff0c;登录皮卡丘靶场&#xff0c;get请求&#xff1b; 2&#xff0c;抓包并修改标记后的个人信息 最后放通一下&#xff0c;发现账号信息被修改 2&#xff0c;post请求 1提交post数据并使用bp抓包 2.利用工具改包&#xff0c;并生成url 3&#xff0c;点击提交后&#…

应用在触摸开关触控屏中的电容式触摸芯片

触摸开关是一种电子开关&#xff0c;使用时轻按开关按钮即可打开开关。松开手时&#xff0c;开关断开&#xff0c;内部结构由金属弹片受力弹动断开或者由电容值&#xff0c;电阻值等电气参数改变而控制。触摸开关一般是指应用触摸感应芯片原理设计的一种墙壁开关&#xff0c;是…

ArkUI组件--Button组件

1.声明Button组件 Button(label?:ResourceStr) #label是按钮上显示的文本 ①label是文字类型 所写文字会在按钮上显示 ②不输入label内容&#xff0c;需要额外定义一些描述。例如插入图片&#xff08;需要定义图片属性&#xff09; Button(){Image($r(app.media.xxx)).wi…

风靡万千软件开发者:揭秘华为研发代码大模型是如何实现的?

作者&#xff1a;陈泰红 秉持“自己的降落伞&#xff0c;自己先跳”的原则&#xff0c;由公司装备部门牵头&#xff0c;携手华为云PaaS作为基础能力提供方&#xff0c;与公司各产品线共同研发面向产业的代码大模型。在研发过程中&#xff0c;我们已取得初步成果&#xff0c;为…