C++ 数组

目录

1. 概述

2. 一维数组

2.1 一维数组的三种定义方式

2.2 一维数组的 数组名 的作用

2.21.可以统计整个数组在内存中占用的空间大小

拓展:

2.2.2.可以获取数组在内存中的首地址

2.3 一维数组案例

2.3.1 找最大值

2.3.2 元素逆置

2.4 冒泡排序

3. 二维数组

3.1 二维数组的四种定义方式

3.2 二维数组的遍历顺序

3.3 二维数组的数组名

3.3.1 查看二维数组所占内存大小

3.3.2 获取二维数组的首地址

3.4 二维数组案例


1. 概述

数组,就是一个集合,用于存放相同类型的数据元素.

特性: 数组中的每个数据元素的数据类型都是同一个.

         数组的内存空间是由所有数据元素的内存空间 连续 组成的.

2. 一维数组

一维数组是指  数组中的每个元素都只有一个下标  的数组

2.1 一维数组的三种定义方式

语法:

数据类型 数组名 [数组长度] ;

给出数组长度,但是暂不赋值    如 int arr[3] ;  

此时数组arr中就包含3个元素,分别是 arr[0] , arr[1] 和 arr[2].   [0] / [1] / [2]就被称为它们的下标

注意下标是从0开始计数的,这意味着 数组长度为n的一维数组的 最大下标为[n-1]

但是我们并没有给这些元素赋值,这些值默认都为0.(但如果没有之前没有清空内存空间,也可能是其他值.)

数据类型 数组名 [ ] = {值1,值2,值3,……};

给出具体的值,但是数组长度由程序自己计数得出

数据类型 数组名 [数组长度] = {值1,值2,值3,……};

同时明确数组长度和赋值

这时,若明确赋值的元素数量小于标明的数组长度,则仍以数组长度为准分配内存,未赋值的元素将赋值为0 (bool 类型数组也是赋值为0,字符型和字符串型则为ASCII码0对应的字符)

总结起来就是,定义一维数组的时候,一定要明确数组的长度,要不就直接给出数组长度,要不就列出数组中包含的全部元素.这是因为程序在创建数组变量时需要分配好确定大小的内存空间

也就是说,创建数组变量的时候,这个数组未来可能会用到的所有内存空间就已经被占用了.

2.2 一维数组的 数组名 的作用

2.21.可以统计整个数组在内存中占用的空间大小

利用sizeof关键字可以得出整个数组占用的内存大小.

int arr[10] ;
cout << sizeof(arr) << endl;

输出结果为40,也就是10个整型变量所占的内存空间大小(每个4字节).

拓展:

int arr[10] ;
cout << sizeof(arr[5]) << endl;

在数组名后面加一个合法的下标,再sizeof,可以得到单个元素所占的内存空间大小.

此处显然为4个字节.

显然,它们之间满足这样的关系:

整个数组所占内存大小 / 单个元素所占内存大小 = 数组长度 = 元素个数

int arr[] = {1,2,5,3,4,7,9,8,6};
cout << sizeof(arr)/sizeof(arr[0]) << endl;

当你懒得数数组有多长的时候就可以这样得到数组长度.

2.2.2.可以获取数组在内存中的首地址

直接 cout << 数组名 << endl;

或者 cout << &数组名 << endl;    (&为取址符,也就是说这里取址符可以省略.)

就可以得到十六进制的数组首地址. 如果需要十进制的地址,可在数组名前加(int)

特别地,数组中第一个元素的地址就是整个数组的首地址.

可以通过 cout << &数组名[0] << endl;   来验证.

注意,此处的取址符就不可以省略了.

#include <iostream>
using namespace std;
int main()
{

	int arr[9] = { 1,2,5,3,4,7,9,8,6 };
	//整个数组占用的内存大小
	cout << sizeof(arr) << endl;
	
	//单个元素占用的内存大小
	cout << sizeof(arr[0]) << endl;

	//数组长度=总内存大小/单个元素内存大小
	cout << sizeof(arr) / sizeof(arr[0]) << endl;

	//获取数组首地址
	cout << arr << endl;

	//获取数组首地址(十进制)
	cout << (int)arr << endl;

	//数组中第一个元素的地址
	cout << &arr[0] << endl;
	cout << (int)&arr[0] << endl;
	return 0;
}

2.2.3 其他

注意数组名被视为一个常量,强行对数组名赋值会报错.

int arr[5];
arr = 100; //错误,数组名为常量,不能赋值

2.3 一维数组案例

2.3.1 找最大值

给定一个数组,求其中最大的元素的值,并求出该元素是数组中的第几个元素.

#include <iostream>
using namespace std;
int main()
{   //求数组中的最大值
	//创建一个数组
	int arr[10] = { 2,4,5,3,7,0,9,6,1,8 };

	//求数组长(直接用10也行,毕竟这里知道大小)
	int length = sizeof(arr) / sizeof(arr[0]);

	//定义最大值变量
	int max = 0;
	
	//找最大值是数组中的第几个元素:
	int ordinal = 0;
	
	//通过下标自增的方式,循环遍历数组中的每个元素,从下标0开始,到(长度-1)结束
	for (int num = 0; num < length; num++)
	{

		//当某个数组中的元素比当前最大值还要大时,用元素值覆盖最大值
		if( arr[num] > max )
		{
			max = arr[num];
			ordinal = num+1;  //第n个元素的下标为n-1,所以下标需要+1才能得到序数
		}
	}
	cout << "最大值为:" << max << endl;//输出最大值
	cout << "最大值位于数组中的第 " << ordinal << " 个元素" << endl;

    return 0 ;
}

当然, 也可以用三目运算符稍微简化一下.

如果你把这段代码直接衔接在上面那段代码中,记得要把max和ordinal 重新初始化为0.

//也可以用三目运算符进行简化
	for (int num1 = 0; num1 < length; num1++)
	{
		//如果最大值比数组元素大,就返回最大值,否则返回数组元素
		max = (max > arr[num1] ? max : arr[num1]);
		//第n个元素的下标为n-1,所以下标需要+1才能得到序数
		ordinal = (max > arr[num1] ? ordinal : num1+1);
	}
	cout << "最大值为:" << max << endl;//输出最大值
	cout << "最大值位于数组中的第 " << ordinal << " 个元素" << endl;

2.3.2 元素逆置

如果想要把整个数组序列倒过来输出要怎么写呢?

//把整个数组序列倒过来再输出
	//定义一个暂存空间方便交换数字
	int temp = 0;
	//定义未交换的数组部分的结尾,因为已经首位交换过的数字不用再参与交换了,数值为(数组长度-1)
	int end = length-1;
	
	//
	int arr1[10] = { 9,4,5,3,7,2,0,6,1,8 };
	//先遍历输出一次原序列
	for (int num = 0; num < length; num++)
	{
		cout << arr1[num] << "\t";
	}
	cout << endl;

	//当首下标小于尾下标时执行,若首尾下标相等说明是同一个元素,若大于则说明首下标已越过尾下标,不用再交换
	//循环结束之前首下标要自增,尾下标要自减,有两步操作,所以不能写末尾循环体了,要放到循环语句里面
	for (int start = 0;  start < end;   )
	{
		//暂存首下标元素
		temp = arr1[start];
		//尾下标覆盖首下标
		arr1[start] = arr1[end];
		//暂存的首下标覆盖尾下标
		arr1[end] = temp;
		start++;//移动始位
		end--;//移动末位
	}
	//检查交换结果
	for (int num = 0; num < length; num++)
	{
		cout << arr1[num] << "\t";
	}
	cout << endl;

2.4 冒泡排序

冒泡排序是最常用的排序算法,用于对数组内的元素按数值大小进行升序排序(逐渐增大)

规则: 从第一个元素(下标为0)开始,和下一个元素进行比较,若某个元素比下一个元素大,则互换它们的位置.互换完成后,从第二个元素继续开始比较.

直至最后一个元素的比较完成,此时最后一个元素一定是数组中的最大值.

然后再开始新一轮的排序,但是上一次已经确定了一个最大值,因此这一轮比较次数-1.

这样数组中的倒数第二个元素的值一定是数组中第二大的.

如此反复直到数组中的所有数字从左到右依次增大,完成排序.

#include <iostream>
using namespace std;
int main()
{
	//冒泡排序
	//从第一个元素开始,和下一个元素进行比较,若下一个元素较小,则将这两个元素位置互换

	//创建数组
	int arr[10] = { 8,5,7,1,4,2,3,0,9,6 };

	//求数组长度
	int n = sizeof(arr) / sizeof(arr[0]);
	
	//先遍历一遍数组把完整序列输出一下
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	//两层循环结构
	//大循环,每次都要完成一整轮排序,最右边浮出一个最大值(上一个最大值视为移出)
	//要对n个数全部排序,则至多需要浮出(n-1)次最大值,即进行(n-1)轮排序,有10个数,则0~8共9轮
	for (int i = 0; i < n-1 ; i++)
	{
		//小循环,每次比较两个数,则第i轮共有(n-i)个数需要排序,因为第一轮i=0
		//两个数才能比一次,所以需要比(n-i-1)次
		//第一次又是0,共n个数,第i轮需要排(n-i)个数,需要比(n-i-1)次,所以0~(n-i-2) 共(n-i-1)次
		for (int j = 0; j < n-i-1; j++)
		{
			//比较和下一个数的大小,若下一个数更小,则位置互换
			if(arr[j]>arr[j+1])
			{
				int temp = arr[j+1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}

		}
	}
	//再输出一次看看排序结果
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}

3. 二维数组

3.1 二维数组的四种定义方式

语法:

数据类型 数组名 [行数][列数] ;

数据类型 数组名 [行数][列数] = {{数据1,数据2},{数据3,数据4}};    (最为直观,建议使用)

数据类型 数组名 [行数][列数] = {数据1,数据2,数据3,数据4};

数据类型 数组名 [  ][列数] = {数据1,数据2,数据3,数据4};

3.2 二维数组的遍历顺序

0列1列2列
0行arr[0][0]   1arr[0][1]   2arr[0][2]   3
1行arr[1][0]   4arr[1][1]   5arr[1][2]   6

当使用第一种方法定义二维数组时,直接输出这些元素的值,发现并不为0.

这说明程序只给这些元素分配了内存空间,但是并没有重置其中的数据.

当使用第二种方法定义二维数组时,若列子集中的元素个数小于列数,则默认用0填充剩余的空位.

列子集的个数小于行数,则默认用0填充剩余的列子集中的所有空位.

#include <iostream>
using namespace std;
int main()
{
	int arr[3][6] = 
	{ 
		{1,2},
	    {3,4,5}
	};

	for (int a = 0; a < 3; a++)
	{
		for (int b = 0; b < 6; b++)
		{
			cout << arr[a][b] << " " ;
		}
		cout << endl;
	}
	return 0;
}

当你使用第三种方法定义二维数组时,若给出值的元素个数小于行数*列数,则优先用给出的值,从第0行第0列开始赋值,填满一行后再进行下一行,剩余的空位用0填充.

#include <iostream>
using namespace std;
int main()
{
	int arr[3][6] = { 1,2,3,4,5,6,7,8,9 };


	for (int a = 0; a < 3; a++)
	{
		for (int b = 0; b < 6; b++)
		{
			cout << arr[a][b] << " " ;
		}
		cout << endl;
	}
	return 0;
}

当你使用第四种方法定义二维数组时,与第三种类似,若给出值的元素个数小于行数*列数,则优先用给出的值,从第0行第0列开始赋值,填满一行后再进行下一行,剩余的空位用0填充.

但与第三种方法不同的是,若第三种方法中存在全空的行,程序仍然会为这些行分配内存并赋值0.

但第四种方法的行数是由程序计算得出的,当程序将提供的最后一个数值赋值给对应元素之后,就只会填满当前行中剩下的列,不会新起一行(即不会有全空的行).

需要注意的是, 用这种方式定义的数组在访问之前需要先求出行数!

否则,一旦循环条件/循环次数 与行数不匹配,就会访问到不属于该数组的内存空间.

#include <iostream>
using namespace std;
int main()
{
	int arr[][6] = { 1,2,3,4,5,6,7,8,9 };

	int row = sizeof(arr3)/sizeof(arr3[0]); //总内存大小除以第一行内存大小,得行数

	cout << row << endl;


	for (int e = 0; e < row; e++)
	{
		for (int f = 0; f < 6; f++)
		{
			cout << arr3[e][f] << " ";
		}
		cout << endl;
	}

	return 0;
}

3.3 二维数组的数组名

3.3.1 查看二维数组所占内存大小

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

cout << sizeof(arr) << endl;   //整个二维数组占用的内存
cout << sizeof(arr[0]) << endl;   //二维数组第一行占用的内存
cout << sizeof(arr[1][2]) << endl; //二维数组第二行第三个元素占用的内存

int row = sizeof(arr) / sizeof(arr[0]) ;   //总大小除以单行大小, 得到行数
int column = sizeof(arr[0]) / sizeof(arr[0][0]) ; //单行大小除以单个元素大小, 得到列数

3.3.2 获取二维数组的首地址

同理可以取得整个二维数组的首地址, 每行的首地址, 每个元素的首地址.

当取址对象为二维数组或者二维数组的行时,取址符可以省略.

但当取址对象为具体的某个元素时,取址符不可以省略,否则会输出的不是元素的地址,而是元素的值.

这一点与一维数组是相同的.

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

	cout << arr0 << endl;         //整个二维数组的首地址
	cout << &arr0 << endl;        //同上一行
	cout << arr0[0] << endl;      //二维数组第一行的首地址
	cout << &arr0[0] << endl;     //同上一行
	cout << &arr0[0][0] << endl;  //二维数组第一个元素的首地址
	

3.4 二维数组案例

有三名同学, 每人都参加了语文,数学,英语 三门考试, 请用二维数组打印他们的成绩,并打印出总分.

#include <iostream>
using namespace std;
int main()
{
	//三人考试成绩,用二维数组存放,行为某人的三科成绩,列为某科的三人成绩
	int score[3][3] =
	{
		{100,99,98},
		{90,80,70},
		{60,40,20}
	};

	//三人姓名,用一维数组存放
	string name[3] = { "张三","李四","王五" };
	
	//三个科目的名称,用一维数组存放
	string course[3] = { "语文","数学","英语" };

	//总分,用一维数组存放
	int sum[3] = { 0,0,0 };
	//大循环,每个循环输出一个人的全部成绩
	for (int a = 0; a < 3; a++)   
	{
		cout << name[a] << "的考试成绩为:\t"  ;
		//小循环,每个循环输出某个人的一科成绩
		for (int b = 0; b < 3; b++)
		{
			cout << course[b] << score[a][b] << "分\t";   //输出各科成绩
			sum[a] += score[a][b];
		}

		cout << "总分:" << sum[a] << endl;   //写完一个人的才换行
	}

	return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值