【C语言_数组_复习篇】

目录

一、数组的概念

二、数组的类型

三、一维数组

        3.1 一维数组的创建

        3.2 一维数组的初始化

        3.3 一维数组的访问

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

四、二维数组

        4.1 二维数组的创建

        4.2 二维数组的初始化

        4.3 二维数组的访问

        4.4 二维数组在内存中的存储

五、字符串数组

        5.1 字符串数组的创建

        5.2 字符串数组的初始化

        5.2 字符串数组的输入

        5.3 字符串数组的输出

        5.4 字符串数组经典应用

六、变长数组

七、指针数组

        7.1 指针数组

        7.2 指针数组模拟实现二维数组

八、函数指针数组

        8.1 函数指针数组

        8.2 函数指针数组的应用:转移表 

九、sizeof计算数组的大小


一、数组的概念

1. 数组是一组相同类型元素的集合,存放在数组内的值被称为数组元素,数组分为一维数组和多维数组,多维数组中最常见的数组是二维数组。数组的type有很多,如int、char、float、结构体等。后面所讲到的字符串数组,指针数组和函数指针数组也都只不过是不同类型数组而已,它们均可创建出一维、二维、多维的形式。

2. 数组的元素个数不能为0数组内的每个元素必须是相同类型的

二、数组的类型

1. 数组的类型是除掉数组名剩余的部分,例如,int arr[10],数组arr的类型是int [10]。

三、一维数组

3.1 一维数组的创建

1. 一维数组的语法格式:type arr_name[常量值];

2. type表示一维数组中的每个元素是什么类型的,arr_name表示一维数组的名称,[常量值]表示一维数组的大小。

#include <stdio.h>
int main()
{
	int arr1[10];//定义存放10个整型的一维数组
	char arr2[4];//定义存放4个字符的一维数组
	float arr3[6];//定义存放6个单精度浮点型的一维数组
	//...
	return 0;
}

3.2 一维数组的初始化

1. 一维数组的初始化分为完全初始化和不完全初始化。

2. 完全初始化:一维数组有多大,就初始化几个元素。

3. 不完全初始化:初始化的元素个数小于一维数组的大小,剩余未初始化的元素会默认初始化为0。

4. 初始化一维数组时,[ ]中的常量值也可以省略不写此时初始化几个元素,一维数组就为多大

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

3.3 一维数组的访问

1. 数组元素的访问需要用到下标引用操作符[ ],数组元素的下标都是从0开始,最大为sz-1

2. 访问时的要点:①知道需要的变量在哪个数组中②知道变量在该数组中的下标编号是多少

③连续输入或使用数组元素时创建循环变量利用 for 循环解决

//一维数组的输入和输出
#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;//循环变量
	for (i = 0; i < sz; i++)
	{
		scanf("%d", &arr[i]);
		printf("%d ", arr[i]);
	}
	return 0;
}

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

1. 一维数组在内存中连续存储,并且随着下标的增长地址由小到大变化

//验证一维数组在内存中的存储方式
#include <stdio.h>
int main()
{
	char arr[5] = { '0', '1', '2', '3', '4'};//字符数组,每个元素占一个字节
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;//循环变量
	for (i = 0; i < sz; i++)
	{
		printf("arr[%d]=%p\n", i, &arr[i]);
	}
	return 0;
}

 

四、二维数组

4.1 二维数组的创建

1. 二维数组的语法格式:type arr_name[常量值1][常量值2];

2. type表示二维数组中的每个元素是什么类型的,arr_name表示二维数组的名称,[常量值1]表示二维数组中有几个一位数组(即几行)[常量值2]表示每个一维数组中有几个元素(即几列)

#include <stdio.h>
int main()
{
	int arr[3][5];//定义三行五列的整型二维数组
	char arr2[4][6];//定义4行6列的字符二维数组
	float arr3[2][4];//定义2行4列的浮点数二维数组
	//...
	return 0;
}

4.2 二维数组的初始化

1. 二维数组的初始化分为完全初始化和不完全初始化,一维数组的{}可打可不打不打时元素按照排满一行再换一行的顺序摆放

2. 完全初始化:二维数组有几列几行,就初始化几列几行的元素。

3. 不完全初始化:初始化的元素个数小于数组大小(行*列),剩余未初始化的元素默认初始化为0。

4. 初始化二维数组时,常量值1也可以省略不写但常量值2必须写, 编译器会根据初始化内容判断二维数组有几行

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

	int arr2[3][4] = { { 1 }, { 2, 3 }, { 4, 6, 8 } };//不完全初始化
	int arr3[3][4] = { 0, 1, 2 };//不完全初始化

	int arr4[][4] = { 1, 2 };//数组为1行4列
	int arr5[][4] = { { 1 }, { 3 }, { 2 , 5 } };//数组为3行4列
	return 0;
}

4.3 二维数组的访问

1. 二维数组的访问也要用到下标引用操作符[ ],二维数组的行标和列标都是0开始最大为sz-1

2. 访问时的要点:① 知道需要的变量在哪个数组中 ② 知道变量在该数组中的行标和列标是多少 ③ 连续输入或使用数组元素时创建循环变量利用嵌套 for 循环解决。

//二维数组的输入和输出
#include <stdio.h>
int main()
{
	int arr[3][4] = { 0 };
	int i = 0;//循环变量
	for (i = 0; i < 3; i++)
	{
		int j = 0;//循环变量
		for (j = 0; j < 4; j++)
		{
			scanf("%d", &arr[i][j]);
			printf("%d ", arr[i][j]);
		}
		//换行
		printf("\n");
	}
	return 0;
}

4.4 二维数组在内存中的存储

1. 二维数组和一维数组一样,在内存中连续存放随着下标的增长地址由小到大变化

//验证二维数组在内存中的存储方式
#include <stdio.h>
int main()
{
	char arr[2][3] = { { '1', '2', '3' }, { '2', '3', '4' }};//字符数组,每个元素占一个字节
	int i = 0;//循环变量
	for (i = 0; i < 2; i++)
	{
		int j = 0;//循环变量
		for (j = 0; j < 3; j++)
		{
			printf("arr[%d][%d]=%p\n", i, j, &arr[i][j]);
		}
	}
	return 0;
}

 

五、字符串数组

5.1 字符串数组的创建

1. C语言中没有专门的字符串类型,如果要存放字符串可以用字符串数组存放(字符串数组本质是字符数组)。

2.  字符串数组的语法格式(和一维字符数组、二维字符数组一样):

     一位字符串数组:char arr_name[常量值]

     二维字符串数组:char arr_name[常量值1][常量值2]

5.2 字符串数组的初始化

1. 字符串数组的初始化分为完全初始化和不完全初始化,且均有两种写法,一种是用单引号初始化,在字符串的末尾会自动存入\0,在定义字符串数组的大小时要考虑\0也是数组中的一个元素,第二种是用大括号的初始化,但不会自动存入\0,需要手动存入\0才能代表这是一个字符串数组,否则只能作为一个字符数组。(通常会用双引号的形式初始化)

2. 下面代码中仅展示一维字符串数组初始化形式,因为二维字符串数组很少用到。

#include <stdio.h>
int main()
{
    //一维字符串
	//方法一:用双引号初始化
	char arr1[4] = "abc";//完全初始化  a b c \0
    char arr2[4] = "ab";//不完全初始化 a b \0
    char arr3[] = "ab"//字符串数组大小为3

	//方法二:用大括号的初始化
	char arr4[4] = { 'a', 'b', 'c', '\0' };//完全初始化
	char arr5[4] = { 'a', 'b', '\0'};//不完全初始化
    char arr6[] = { 'a', 'b', '\0'};//字符串数组大小为3
 
    char arr7[4] = { 'a', 'b', 'c', 'd' };//不是字符串数组,因为数组中没有\0
	char arr8[4] = { 'a', 'b'};//不是字符串数组,因为数组中没有\0
    char arr9[] = { 'a', 'b'};//不是字符串数组,因为数组中没有\0                  
	return 0;
}

5.2 字符串数组的输入

1. 字符串数组的输入可以用scanf() 和 gets() 但两者是有区别的。 
2. scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。
3. gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以在字符串数组输入时,最好用 gets()

#include <stdio.h>
int main()
{
	char arr1[10] = { '0'};
	//输入方法一:
	scanf("%s", arr1);//"hello world",只会读取hello
	//输入方法二:
	gets(arr1);//"hello world",全部读取
	return 0;
}

5.3 字符串数组的输出

1. 字符串数组的输出可以用用scanf() 和 gets() 但是有区别的。

2. printf():通过格式控制符%s 输出字符串,不能自动换行

3. puts():输出字符串并自动换行,该函数只能输出字符串。

#include <stdio.h>
int main()
{
	char arr1[10] = "abcde";
	//输出方法一:
	printf("%s\n", arr1);//不会自动换行,打印时加\n
	//输出方法二:
	puts(arr1);//会自动换行
	return 0;
}

5.4 字符串数组经典应用

//【实现:多个字符从两端移动,向中间汇聚】
//##########################
//Y########################!
//Yo######################!!
//You####################!!!
//You ##################!!!!
// ...
//You are the best!!!!!!!!!!

#include <stdio.h>
#include <windows.h>
#include <stdlib.h>

int main()
{
	char arr1[] = "You are the best!!!!!!!!!!";
	char arr2[] = "##########################";
	//计算数组arr2的元素个数
	int sz = sizeof(arr2) / sizeof(arr2[0]);
	//再屏幕上先打印数组arr2的内容
	printf("%s\n", arr2);
	int left = 0;
	int right = sz - 2;//字符串的末尾隐藏着一个\0
	while (left <= right)
	{
		//睡眠1000毫秒
		Sleep(700);//sleep的第一个字母大写!

		arr2[left] = arr1[left];
		arr2[right] = arr1[right];

		//清屏
		system("cls");//system函数是库函数,执行系统命令,cls清理控制台屏幕

		//再次在屏幕上打印数组arr2
		printf("%s\n", arr2);

		//调整
		left++;
		right--;
	}
	return 0;
}

六、变长数组

1. 概念:C99之前,数组的大小只能是常量。C99之后,引入了变长数组的概念,可以使用变量来指定数组的大小。但VS默认不支持C99中的变长数组,使用gcc编译器的DevC++支持,oj刷题的网站一般也是支持的。

2. 变⻓数组的根本特征数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化

3. 好处:当在开发时,没有确定好数组的大小,可以利用变长数组,待程序运⾏时再为数组分配精确的⻓度。

4. 注意:变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。数组的⼤⼩⼀旦确定就不能再变化了。

七、指针数组

7.1 指针数组

1. 指针数组就是存放指针的数组,数组中的每个元素都是指针(地址)。

2. 指针数组的类型由数组中每个指针的类型决定,我们可以根据需要自行选择创建一维指针数组还是二维指针数组,指针数组的创建方式、初始化、访问、存储方式和一维数组、二维数组讲述中的内容没有差别。

#include <stdio.h>
int main()
{
	int arr1[] = { 1, 2, 3 };
	int arr2[] = { 2, 3, 4 };
	int arr3[] = { 3, 4, 5 };

	int* arr[3] = { arr1, arr2, arr3 };//一维指针数组
	//由于数组名是数组首元素的地址,每个数组首元素的地址是int*类型的
	//所以arr指针数组语法中的tpye部分要写成int*
	return 0;
}

7.2 指针数组模拟实现二维数组

1. 模拟的⼆维数组,并⾮完全是⼆维数组,因为每⼀⾏的数据在内存中是⾮是连续的。

2. 下图代码的解释:parr是数组首元素的地址,而parr首元素的地址是数组arr1的地址,我们可以通过对parr+-整数拿到parr中每个元素的地址,即内部每个数组的地址,再通过对这些地址解引用拿到,每个内部数组首元素地址,最后通过首元素的地址偏移和解引用,找到parr内部数组中的每个元素,即有了 *(*(arr+i) + j) == parr[i][j] 。

#include <stdio.h>
int main()
{
     int arr1[] = {1,2,3,4,5};
     int arr2[] = {2,3,4,5,6};
     int arr3[] = {3,4,5,6,7};
     
     int* parr[3] = {arr1, arr2, arr3};//一位指针数组
     int i = 0;
     int j = 0;
     for(i=0; i<3; i++)
     {
         for(j=0; j<5; j++)
         {
             printf("%d ", parr[i][j]);
         }
         printf("\n");
     }
     return 0;
}

八、函数指针数组

8.1 函数指针数组

1. 函数指针数组是存放函数指针的数组函数指针数组里的元素全都是函数指针

2. 函数指针数组的类型由数组中每个元素的类型决定,但函数指针数组的创建写法比较独特,具体见下方代码。

    即要把函数指针类型中写指针名称的地方写成函数指针数组名+数组大小

3. 和指针数组一样我们可以根据需要自行选择创建一维函数指针数组还是二维函数指针数组,函数指针数组除创建方式写法有些独特外,其初始化、访问、存储方式和一维数组、二维数组中讲述的内容没有差别。

#include <stdio.h>

int Add(int x, int y)
{
	//...
	return x + y;
}

int Sub(int x, int y)
{
	//...
	return x - y;
}

int Mul(int x, int y)
{
	//...
	return x * y;
}

int main()
{
	int (*arr[3])(int, int) = { Add, Sub, Mul };//函数指针数组
                                                //arr是数组名,[3]表示数组大小
    //int ret = (arr+1)(2, 3);//err
	//int ret = (*(arr + 1))(2, 3);
	int ret = arr[1](2, 3);//下标直接访问
	printf("%d\n", ret);
	return 0;
}

8.2 函数指针数组的应用:转移表 

#include <stdio.h>

int add(int a, int b)
{
	return a + b;
}

int sub(int a, int b)
{
	return a - b;
}

int mul(int a, int b)
{
	return a * b;
}

int div(int a, int b)
{
	return a / b;
}

int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if ((input <= 4 && input >= 1))
		{
			printf("输⼊操作数:");
			scanf("%d %d", &x, &y);
			ret = p[input](x, y);
			printf("ret = %d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("输⼊有误\n");
		}
	} while (input);
	return 0;
}

九、sizeof计算数组的大小

1. sizeof是专门计算变量或类型所占空间大小的一个关键字,计算结果的单位是字节,sizeof不会执行( )内的任何运算和函数调用。

2. sizeof(数组名)计算的是整个数组的大小,这里的数组名不再是数组首元素的地址。

3. 计算一维数组元素个数:int sz = sizeof(arr) / sizeof(arr[0]);利用整个数组的大小除以单个数组元素的大小,得到的就是数组大小,打印时占位符%d不行就用%zd。

4. 计算二维数组元素个数:int sz = sizeof(arr) / sizeof(arr[0][0]);

5. 使用的好处:方便修改和利用。

6. 好习惯:定义和初始化一维数组后,下面一行立即写上用sizeof计算出的一维数组元素个数。

 本篇已完结。。。。。。

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

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

相关文章

SAP前台处理:物料主数据创建<MM01>之采购视图

一、背景&#xff1a; 终于来到了物料主数据&#xff0c;我觉得物料账是SAP最重要的一项发明&#xff0c;也一直是SAP的一项重要优势&#xff0c;物料账记录了一个个物料的生生不息&#xff1b; 本章主要讲解物料主数据和财务相关的主要内容&#xff1a;这里特别提示由于作者…

“先干后看”式循环

题目&#xff1a;计算 &#xff0c;直到最后一项小于 。 注意题目要求&#xff1a;计算到最后一项小于 。也就是这一项是要参与到计算中的&#xff0c;计算完这一项才能触发循环停止条件。 这种先运算后判断的情况很对do-while循环的胃口。 do就是做嘛&#xff0c;while就是…

扇区架次数动态展示

打开前端Vue项目&#xff1a;kongguan_web&#xff0c;完成前端src/components/echart/SectorFlightChart.vue页面设计&#xff0c;使用ECharts插件实现柱状图和饼状图 在src/components目录下创建echart目录&#xff0c;完成src/components/echart/SectorFlightChart.vue 的页…

【SM3哈希算法】算法原理

【SM3哈希算法】算法原理 参考&#xff1a; 文章目录 【SM3哈希算法】算法原理一、算法简介二、基本原理三、具体流程1、填充2、分组3、迭代压缩 C语言实现 一、算法简介 SM3算法是一种密码散列函数标准&#xff0c;由国家密码管理局发布。它的安全性和SHA-256相当&#xff0…

【leetcode热题】 阶乘后的零

给定一个整数 n &#xff0c;返回 n! 结果中尾随零的数量。 提示 n! n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;0 解释&#xff1a;3! 6 &#xff0c;不含尾随 0示例 2&#xff1a; 输入&#xff1a;n 5 输出&a…

二叉树遍历(牛客网)

描述 编一个程序&#xff0c;读入用户输入的一串先序遍历字符串&#xff0c;根据此字符串建立一个二叉树&#xff08;以指针方式存储&#xff09;。 例如如下的先序遍历字符串&#xff1a; ABC##DE#G##F### 其中“#”表示的是空格&#xff0c;空格字符代表空树。建立起此二叉树…

Java毕业设计 基于springboot vue招聘网站 招聘系统

Java毕业设计 基于springboot vue招聘网站 招聘系统 springboot vue招聘网站 招聘系统 功能介绍 用户&#xff1a;登录 个人信息 简历信息 查看招聘信息 企业&#xff1a;登录 企业信息管理 发布招聘信息 职位招聘信息管理 简历信息管理 管理员&#xff1a;注册 登录 管理员…

const,static深度总结——c++穿透式分析

前言&#xff1b;c类和对象的知识点中除了几种默认函数&#xff0c; 比较重要的还有使用const和static修饰成员相关知识点。const在c中特性很简单。 但是在使用中&#xff0c; 比较容易疏忽大意出现问题。 static特性也很简单&#xff0c; 但是比起const来要直接的多。 在使用中…

2023 re:Invent 使用 PartyRock 和 Amazon Bedrock 安全高效构建 AI 应用程序

前言 “ Your Data , Your AI , Your Future .&#xff08;你的数据&#xff0c;你的 AI &#xff0c;你的未来。&#xff09; 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界…

javaAPI操作Elasticsearch

mapping属性 mapping是对索引库中文档的约束, 常见的mapping属性包括: type: 字段数据类型,常见的简单类型有: 字符串: text(可分词的文本), keyword(精确值, 例如: 品牌,国家)数值: long, integer, short, byte, double, float布尔: boolean日期: date对象: object index: 是否…

LLMs之Grok-1:Grok-1的简介、安装、使用方法之详细攻略

LLMs之Grok-1&#xff1a;Grok-1的简介、安装、使用方法之详细攻略 导读&#xff1a;马斯克旗下的xAI公司宣布开源名为Grok-1的混合专家模型&#xff0c;参数量达3140亿&#xff0c;为目前最大的开源大语言模型。xAI此举或将引领人工智能开源趋势&#xff0c;同时也将对不太Ope…

协议分类笔记

1.3 协议分类 通信的协议还是比较复杂的&#xff0c;java.net 包中包含的类和接口&#xff0c;它们提供低层次的通信细节。我们可以直接使用这些类和接口&#xff0c;来专注于网络程序开发&#xff0c;而不用考虑通信的细节。 java.net 包中提供了两种常见的网络协议的支持&a…

DevExpress WinForms crack,DevExpress WinForms组件套件和库

DevExpress WinForms crack,DevExpress WinForms组件套件和库 Reporting & Analytics - Reports, Pivot Tables, PDF Viewer. The DevExpress WinForms Subscription includes royalty-free user interface components for next-gen decision support systems. Whether you…

Java基础经典10道题

目录 for循环的嵌套 题目一: 求101到200之间的素数的个数,并打印 代码分析: 注意点: 题目二:开发验证码 代码分析: 题目三:数组元素的复制 代码分析: 题目四:评委打分 健壮版代码: 代码分析:看源码 注意点: 题目五:数字加密 优化版代码: 代码分析: 题目六:数字…

MeterSphere和Jmeter使用总结

一、MeterSphere 介绍 MeterSphere 是⼀站式开源持续测试平台&#xff0c;涵盖测试跟踪、接⼝测试、UI 测试和性能测试等&#xff0c;全 ⾯兼容 JMeter、Selenium 等主流开源标准&#xff0c;能够有效助⼒开发和测试团队在线共享协作&#xff0c;实现端到 端的测试管理跟踪…

2、RabbitMQ_安装

RabbitMQ安装文档 RabbitMQ官网下载地址&#xff1a;https://www.rabbitmq.com/download.html 1.安装依赖 在线安装依赖环境&#xff1a; yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel tk tc x…

Java语言: 多线程

1. 线程调度 1.1 线程状态 线程是cpu任务调度的最小执行单位&#xff0c;每个线程拥有自己独立的程序计数器、虚拟机栈、本地方法栈。 线程状态&#xff1a;创建、就绪、运行、阻塞、死亡 1.2 线程状态切换 1.3 阻塞唤醒过程 阻塞&#xff1a; 这三个方法的调用都会使当前…

视频私有云,HDMI/AV多硬件设备终端接入,SFU/MCU视频会议交互方案。

在视频业务深入的过程中越来越多的硬件设备接入视频交互的视频会议中远程交互&#xff0c;有的是视频采集&#xff0c;有的是医疗影像等资料&#xff0c;都需要在终端承显&#xff0c;这就需要我们的设备终端能多设备&#xff0c;多协议接入&#xff0c;设备接入如下。 1&#…

2024年敏捷产品负责人CSPO认证培训

课程名称&#xff1a;Scrum Product Owner CSPO产品负责人认证 课程类型&#xff1a;经理级 课程简介&#xff1a; Scrum Product Owner产品负责人在Scrum产品开发当中扮演“舵手”的角色&#xff0c;他决定产品的愿景、路线图以及投资回报&#xff0c;他需要回答为什么做&am…

数据收集与分析

数据收集与分析是任何组织决策过程中的核心环节&#xff0c;特别是在确定关键性能指标&#xff08;KPIs&#xff09;、使用先进的数据分析工具和方法方面。以下是一个概述&#xff0c;旨在解释如何进行数据收集与分析&#xff0c;并确定KPIs。 1. 确定关键性能指标&#xff08…