C语言数组(上)

# 数组的概念

        数组是一组相同类型元素的集合。数组中存放的是一个或多个数据,但是数组中的元素个数不能为零;数组中存放的所有元素(数据)的类型必须是相同的。

        数组分为一维数组和多维数组,多维数组一般比较多见的是二维数组。下面我将为大家详细讲解一维数组和二维数组的常用知识点。

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

        1  一维数组的创建

形式:type arr_name[常量值];

             |            |             |

          类型     数组名    常量

        存放在数组中的值被称为数组的元素,数组在创建的时候可以指定数组的大小和数组的元素类型。type 指定的是数组中存放的数据类型,可以是:char、short、int、float等,也可以自定义类型。arr_name 指的是数组名的名字,这个名字由你的意向决定,在这里我建议数组名尽量有意义,为自己和他人后期读代码更便利。[]中的常量值是用来指定数组大小的,这个数组的大小根据实际情况的需要来确定即可。

比如:我们现在想存储某个班级的20⼈的数学成绩,那我们就可以创建⼀个数组,形式为:

 int math[20];

当然我们也可以根据需要创建其他类型和⼤⼩的数组:

char ch[ 8 ];
double score[ 10 ];

 2 数组的初始化

        一般情况下,数组在创建的时候,我们需要给定数组一些初始值,这种就称为初始化的数组。数组的初始化⼀般使⽤⼤括号,将数据放在⼤括号中。

//完全初始化
int arr[5] = {1,2,3,4,5};
//不完全初始化
int arr2[6] = {1};//第⼀个元素初始化为1,剩余的元素默认初始化为0
//错误的初始化 - 初始化项太多
int arr3[3] = {1, 2, 3, 4};

 3 数组的类型

        数组的类型算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型。

int arr1[10];
//arr1的类型为 int[10]
int arr2[12];
//arr2的类型为 int[12]
char ch[5];
//ch的类型为 char[5]

#  一维数组的使用

        了解了一维数组的基本语法后,我们知道了一维数组可以存放数据,存放数据的目的是对数据进行操作,那下面我就要讲一下如何操作相应的数据。

1 数组下标

        C语言中规定了数组的下标,下标是从零开始的,假设数组有n个元素,那么最后一个元素的下标就是 n-1 ,下标本质上就是数组中元素的编号,如下:

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

数组:

下标:

       0             1             2            3             4            5             6            7             8             9                 [ ]是C语言中为了访问数组提供的⼀个操作符,称为下标引用操作符。有了下标访问操作符,我们就可以轻松的访问到数组的元素,⽐如我们访问下标为7的元素,我们就可以使⽤ arr[7] ,想要访问下标是3的元素,就可以使⽤ arr[3] ,如下代码:

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

2 数组元素的打印 

        了解了数组下标的使用后,我们就可以访问整个数组的内容了。如何操作呢?只要我们产生数组所有元素的下标就可以了,这里我们使用了for循环去产生0-9的下标,代码如下:

#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 ", arr[i]);
 }
 return 0;
}

 3 数组的输⼊

        明白了数组的访问后,我们就可以根据自己的需求,主动给数组中输入(存放)想要的数据了。例如:

#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++)
 {
     scanf("%d", &arr[i]);
 }
 for(i=0; i<10; i++)
 {
     printf("%d ", arr[i]);
 }
 return 0;
}

# 一维数组在内存中的储存 

        有了前⾯的知识,我们其实使⽤数组基本没有什么障碍了,如果我们要深⼊了解数组,我们最好能了解⼀下数组在内存中的存储。下面我们来依次打印数组元素的地址:
#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("&arr[%d] = %p\n ", i, &arr[i]);
 }
 return 0;
}

        从输出的结果我们分析,数组随着下标的增⻓,地址是由⼩到⼤变化的,并且我们发现每两个相邻的元素之间相差4(因为⼀个整型是4个字节)。所以我们得出结论:数组在内存中是连续存放的。这就为后期我们使⽤指针访问数组奠定了基础(在讲指针的时候我们在讲,这⾥暂且记住就⾏)。

 # sizeof计算数组元素个数

        我们已经学会了在数组中存放元素,那么有没有办法去得知数组中到底存放了多少元素呢?

我想通过本小段的标题你也已经想到了(使用sizeof操作符),但是有一个问题,sizeof是用于计算类型或者变量⼤⼩的,这样我们计算的是数组的大小,而不是数组中元素的个数。

        我们先来看一段代码:

#include <stido.h>
int main()
{
 int arr[10] = {0};
 printf("%d\n", sizeof(arr));
 return 0;
}

你能算出结果吗?int 是整型,一个整型数字的大小为4个字节。

        我们⼜知道数组中所有元素的类型都是相同的,那只要计算出⼀个元素所占字节的个数,数组的元素个数就能算出来,所以arr的大小就是40个字节。我想讲到这里你就有思路了,我们可以用数组中所有元素的大小去除数组中一个元素的大小,这样我们就求出了数组中元素的个数。

#include <stido.h>
int main()
{
 int arr[10] = {0};
 int sz = sizeof(arr)/sizeof(arr[0]);
 printf("%d\n", sz);
 return 0;
}
        这⾥的结果是:10,表⽰数组有10个元素。这样以后在代码中需要数组元素个数的地⽅就不⽤固定写死了,使⽤上⾯的计算,不管数组怎么变化,计算出的⼤⼩都是当前数组中元素的个数。

# 二维数组的创建

1 维数组的概念

        前⾯学习的数组被称为⼀维数组,数组的元素都是内置类型的,如果我们把⼀维数组做为数组的元素,这时候就是⼆维数组,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称为多维数组。下图就是一、二、三维数组的图示:

        因为除二维数组之外的多维数组并不常用,所以下面我只讲二维数组,其余多维数组,各位可以根据二维数组类推。

2 ⼆维数组的创建  

形式:

type arr_name[ 常量值 1 ][ 常量值 2 ]
例如:
int arr[3][5];
double data[2][8];
//• 3表⽰数组有3⾏
//• 5表⽰每⼀⾏有5个元素
//• int 表⽰数组的每个元素是整型类型
//• arr 是数组名,可以根据⾃⼰的需要指定名字
//data数组意思基本⼀致。

 # ⼆维数组的初始化

        二维数组的初始化与一维数组基本一致。

1 不完全初始化

int arr1[ 3 ][ 5 ] = { 1 , 2 };
int arr2[ 3 ][ 5 ] = { 0 };
        可以看出,不完全初始化的二维数组与一维数组具有共同点:未初始化的值默认为0。

2 完全初始化  

int arr3[ 3 ][ 5 ] = { 1 , 2 , 3 , 4 , 5 , 2 , 3 , 4 , 5 , 6 , 3 , 4 , 5 , 6 , 7 };

3 按照⾏初始化 

int arr4[ 3 ][ 5 ] = {{ 1 , 2 },{ 3 , 4 },{ 5 , 6 }};

4 初始化时省略⾏,但是不能省略列 

int arr5[][ 5 ] = { 1 , 2 , 3 };
int arr6[][ 5 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 };
int arr7[][ 5 ] = {{ 1 , 2 }, { 3 , 4 }, { 5 , 6 }};

# 二维数组的使用 

1 ⼆维数组的下标

        与一维数组相同,⼆维数组访问也是使⽤下标的形式的,⼆维数组是有⾏和列的,只要锁定了⾏和列就能唯⼀锁定数组中的⼀个元素。并且C语⾔规定,⼆维数组的⾏是从0开始的,列也是从0开始的,如下所⽰:

        int arr[4][3] = {0};

举个例子:

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

2 ⼆维数组的输⼊和输出  

        对于二维数组而言,我们只要能够按照⼀定的规律产⽣所有的⾏和列的数字就可以访问整个数组的元素。这里的输入输出就需要两层循环来使用:

#include <stdio.h>
int main()
{
 int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
 int i = 0;//遍历⾏
 //输⼊
 for(i=0; i<3; i++) //产⽣⾏号
 {
 int j = 0;
 for(j=0; j<5; j++) //产⽣列号
 {
 scanf("%d", &arr[i][j]); //输⼊数据
 }
 }
 //输出
 for(i=0; i<3; i++) //产⽣⾏号
 {
 int j = 0;
 for(j=0; j<5; j++) //产⽣列号
 {
 printf("%d ", arr[i][j]); //输出数据
 }
 printf("\n");
 }
 return 0;
}

#  ⼆维数组在内存中的存储

        像⼀维数组⼀样,我们如果想研究⼆维数组在内存中的存储⽅式,我们也是可以打印出数组所有元素的地址的。
#include <stdio.h>
int main()
{
 int arr[3][5] = { 0 };
 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;
}

        从输出的结果来看,每⼀⾏内部的每个元素都是相邻的,地址之间相差4个字节,跨⾏位置处的两个元素(如:arr[0][4]和arr[1][0])之间也是差4个字节,所以⼆维数组中的每个元素都是连续存放的。这也说明了为什么二维数组的列是不能省略的,如果列省略的话,下一行的第一个元素地址就不确定了。
        了解清楚⼆维数组在内存中的布局,有利于我们后期使⽤指针来访问数组的学习。

# C99中的变⻓数组

        在C99标准之前,C语⾔在创建数组的时候,数组⼤⼩的指定只能使⽤常量、常量表达式,或者如果我们初始化数据的话,可以省略数组⼤⼩。比如:
        int arr1[ 10 ];
        int arr2[ 3 + 5 ];
        int arr3[] = { 1 , 2 , 3 };
        这样的语法限制 让我们创建数组 就不够灵活,有时候数组⼤了浪费空间,有时候数组⼜⼩了不够⽤的。而在 C99中给⼀个变⻓数组(variable-length array,简称 VLA)的新特性,允许我们可以使⽤变量指定 数组⼤⼩。
int n = a+b;
int arr[n];

         上⾯⽰例中,数组 arr 就是变⻓数组,因为它的⻓度取决于变量 n 的值,编译器没法事先确定,只有运⾏时才能知道 n 是多少。

        变⻓数组的根本特征,就是数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定⼀个估计的⻓度,程序可以在运⾏时为数组分配精确的⻓度。有⼀个⽐较迷惑的点, 变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。数组的⼤⼩⼀旦确定就不能再变化了。  当然c99只存在于一部分编译器上,如 gcc 等
        下⾯是我在gcc编译器上测试,可以看⼀下:
#include <stdio.h>
int main()
{
 int n = 0;
 scanf("%d", &n);//根据输⼊数值确定数组的⼤⼩
 int arr[n];
 int i = 0;
 for (i = 0; i < n; i++)
 {
 scanf("%d", &arr[i]);
 }
 for (i = 0; i < n; i++)
 {
 printf("%d ", arr[i]);
 }
 return 0;
}
第⼀次测试,我给n中输⼊5,然后输⼊5个数字在数组中,并正常输出
第⼆次测试,我给n中输⼊10,然后输⼊10个数字在数组中,并正常输出

到此,数组的知识就讲完了。下期我会为大家演示两道练习题,用于巩固我们数组的学习。

练习1:多个字符从两端移动,向中间汇聚 

练习2:⼆分查找
如果大家感兴趣也可提前自行尝试,下期间。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LoadBalancer将服务暴露到外部实现负载均衡purelb-layer2模式配置介绍

目录 一.purelb简介 1.简介 2.purelb的layer2工作模式特点 二.layer2的配置演示 1.首先准备ipvs和arp配置环境 2.purelb部署开始 &#xff08;1&#xff09;下载purelb-complete.yaml文件并应用 &#xff08;2&#xff09;查看该有的资源是否创建完成并运行 &#xff…

安美数字酒店宽带运营系统 SQL注入漏洞复现

0x01 产品简介 HiBOS酒店宽带运营系统隶属于安美世纪(北京)科技有限公司开发的一套酒店宽带管理系统。 0x02 漏洞概述 安美数字酒店宽带运营系统 online_status.php、language.php等接口处存在SQL注入漏洞,未经身份认证的攻击者可以通过此漏洞获取数据库权限,进一步利用可…

Star 10.4k!推荐一款国产跨平台、轻量级的文本编辑器,内置代码对比功能

notepad 相信大家从学习这一行就开始用了&#xff0c;它是开发者/互联网行业的上班族使用率最高的一款轻量级文本编辑器。但是它只能在Windows上进行使用&#xff0c;而且正常来说是收费的&#xff08;虽然用的是pj的&#xff09;。 对于想在MacOS、Linux上想使用&#xff0c;…

java操作windows系统功能案例(二)

1、打印指定文件 可以使用Java提供的Runtime类和Process类来打印指定文件。以下是一个示例代码&#xff1a; import java.io.File; import java.io.IOException;public class PrintFile {public static void main(String[] args) {if (args.length ! 1) {System.out.println(…

GNU环境下伪操作伪指令的测试

目录 1.伪操作ldr转为指令的验证 测试目标&#xff1a; 测试代码&#xff1a; 测试结果&#xff1a; 结果分析: 2、伪操作ALIGN使用的例子 测试目标&#xff1a; 测试代码&#xff1a; 测试结果&#xff1a; (1)未使用align伪操作&#xff1a; (2)使用了align伪操作…

Leetcode1038. 从二叉搜索树到更大和树(每日一题)

目录 ⚽题目&#xff1a; &#x1f3d0;题目分析&#xff1a; &#x1f3c0;题目解答&#xff1a; &#x1f94e;代码如下&#xff1a; ⚽题目&#xff1a; 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值…

Python类型注解必备利器:typing模块解读指南

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python 3.5版本后引入的typing模块为Python的静态类型注解提供了支持。这个模块在增强代码可读性和维护性方面提供了帮助。本文将深入探讨typing模块&#xff0c;介绍其基本概念、常用类型注解以及使用示例&am…

Java并发模式和设计策略

引言 小伙伴们&#xff0c;今天小黑要和咱们聊聊Java并发编程的那些事儿。在现代软件开发中&#xff0c;高效地处理多任务是一个不可或缺的能力。特别是对于服务成千上万用户的应用&#xff0c;能够同时处理多个操作不仅是一个加分项&#xff0c;简直是必备技能了&#xff01;…

【踩坑】解决maven的编译报错Cannot connect to the Maven process. Try again later

背景 新公司新项目, 同事拷给我maven的setting配置文件, 跑项目编译发现maven报 Cannot connect to the Maven process. Try again later. If the problem persists, check the Maven Importing JDK settings and restart IntelliJ IDEA 虽然好像不影响, 项目最终还是能跑起来…

C++ 系列 第四篇 C++ 数据类型上篇—基本类型

系列文章 C 系列 前篇 为什么学习C 及学习计划-CSDN博客 C 系列 第一篇 开发环境搭建&#xff08;WSL 方向&#xff09;-CSDN博客 C 系列 第二篇 你真的了解C吗&#xff1f;本篇带你走进C的世界-CSDN博客 C 系列 第三篇 C程序的基本结构-CSDN博客 前言 面向对象编程(OOP)的…

Linux(14):进程管理

一个程序被加载到内存当中运作&#xff0c;那么在内存内的那个数据就被称为进程(process)。 进程是操作系统上非常重要的概念&#xff0c;所有系统上面跑的数据都会以进程的型态存在。 进程 在 Linux底下所有的指令与能够进行的动作都与权限有关&#xff0c;而系统如何判定权…

Android wifi连接和获取IP分析

wifi 连接&获取IP 流程图 代码流程分析 一、关联阶段 1. WifiSettings.submit – > WifiManager WifiSettings 干的事情比较简单&#xff0c;当在dialog完成ssid 以及密码填充后&#xff0c;直接call WifiManager save 即可WifiManager 收到Save 之后&#xff0c;就开…

JVM:双亲委派(未完结)

类加载 定义 一个java文件从编写代码到最终运行&#xff0c;必须要经历编译和类加载的过程&#xff0c;如下图&#xff08;图源自b站视频up主“跟着Mic学架构”&#xff09;。 编译就是把.java文件变成.class文件。类加载就是把.class文件加载到JVM内存中&#xff0c;得到一…

Shell数组函数:数组(一)

一、数组简介&#xff1a; 变量&#xff1a;用一个固定的字符串&#xff0c;代替一个不固定字符串。数组&#xff1a;用一个固定的字符串&#xff0c;代替多个不固定字符串。 二、类型 普通数组&#xff1a;只能使用整数作为数组索引关联数组&#xff1a;可以使用字符串作为…

【LeetCode热题100】【双指针】三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 …

具有五层协议的网络体系结构

目录 一、计算机的网络体系结构 二、五层协议的体系结构 1、物理层 2、数据链路层 3、网络层 4、传输层 5、应用层 三、数据在各层之间传输的过程 一、计算机的网络体系结构 二、五层协议的体系结构 1、物理层 利用传输介质为通信的网络结点之间建立、管理和释放物理连…

电压驻波比

电压驻波比 关于IF端口的电压驻波比 一个信号变频后&#xff0c;从中频端口输出&#xff0c;它的输出跟输入是互异的。这个电压柱波比反映了它输出的能量有多少可以真正的输送到后端连接的器件或者设备。

沐风老师3DMAX随机变换工具RandomTransform插件使用方法详解

3DMAX随机变换工具RandomTransform插件使用方法 3dMax随机变换工具RandomTransform&#xff0c;是一款用MAXScript脚本语言开发的3dsMax小工具&#xff0c;可以随机变换选中的单个或多个对象的位置、角度及大小。 在3dMax中“变换”工具是最常用的工具&#xff08;移动、旋转和…

【hacker送书第8期】Java从入门到精通(第7版)

第8期图书推荐 内容简介编辑推荐作者简介图书目录参与方式 内容简介 《Java从入门到精通&#xff08;第7版&#xff09;》从初学者角度出发&#xff0c;通过通俗易懂的语言、丰富多彩的实例&#xff0c;详细讲解了使用Java语言进行程序开发需要掌握的知识。全书分为4篇共24章&a…

Java生成word[doc格式转docx]

引入依赖 <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.32</version></dependency> doc…