C++从入门到精通 第四章(数组)

 写在前面:

  1. 本系列专栏主要介绍C++的相关知识,思路以下面的参考链接教程为主,大部分笔记也出自该教程,笔者的原创部分主要在示例代码的注释部分。
  2. 除了参考下面的链接教程以外,笔者还参考了其它的一些C++教材(比如计算机二级教材和C语言教材),笔者认为重要的部分大多都会用粗体标注(未被标注出的部分可能全是重点,可根据相关部分的示例代码量和注释量判断,或者根据实际经验判断)。
  3. 由于C++基本继承了C语言的所有内容,建议读者先阅读C语言系列的专栏,有一些重点是仅在C语言系列专栏中有介绍的(比如二级指针、预处理等)。
  4. 如有错漏欢迎指出。

参考教程:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili

一、数组概述

(1)所谓数组,就是一个集合,里面按顺序存放了相同类型的数据元素。

(2)数组中的每个数据元素都是相同的数据类型

(3)数组是由连续的内存位置组成的。

二、一维数组

1、一维数组的定义

一维数组是由具有一个下标的数组元素组成的数组,其定义形式如下:

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

(1)数据类型是类型说明符,数组名是数组的名字,数组长度是任一值为正整数的int型常量表达式,用来指定数组中元素的个数,即数组的大小。

(2)数组元素的下标是从0到(数组长度-1)。

(3)数组名的命名规范与变量名命名规范一致,不要和变量重名。

2、一维数组的初始化

与所有的基本数据类型相同,数组也可以在定义时初始化,有两种形式:

(1)指定数组长度,花括号中各项数据之间以逗号分隔,若花括号内的元素个数小于(只能小于等于,如果大于将会报错)数组长度,则剩下的数组元素默认为零(或者说空)。

        <数据类型>  <数组名>[ <数组长度> ] = { <值1>, <值2> ...};

(2)不指定数组长度,花括号中各项数据之间以逗号分隔,数组长度即花括号内的元素个数。

        <数据类型>  <数组名>[ ] = { <值1>, <值2> ...};

3、访问数组元素的语法形式

        <数组名>[<表达式>]

(1)表达式是非负的int型表达式,称为下标,下标用于指定所要访问的数组中元素的位置,在C++中“[]”是一个运算符,称为下标运算符。

(2)数组下标从0开始,长度为n的数组,其下标的范围是0到n-1。(下标超出范围会造成越界访问,不管会不会报错,程序都是会存在问题的)

数组元素

数组a第1个元素

数组a第2个元素

数组a第3个元素

数组a第n个元素

访问方式

a[0]

a[1]

a[2]

a[n-1]

元素值

<值1>

<值2>

<值3>

<值n>

(3)在数组定义以后,给数组元素赋值时,必须一个元素一个元素地逐个访问。

(4)数组名是常量,不可以对其进行赋值,但可对其元素进行赋值。

#include<iostream>
using namespace std;

int main() {

	/*
	一维数组定义的三种方式:
	数据类型  数组名[ 数组长度 ];
	数据类型  数组名[ 数组长度 ] = { 值1,值2 ...};
	数据类型  数组名[ ] = { 值1,值2 ...};
	*/

	//1、数据类型  数组名[ 数组长度 ];
	int arr1[5];
	arr1[0] = 10;   //通过下标引用数组元素,一个数组有5个元素的话,那么每个元素的下标分别为0~4(给arr1数组的0号元素赋值为10)
	cout << arr1[0] << endl;    //访问数据元素
	//2、数据类型  数组名[ 数组长度 ] = { 值1,值2 ...};
	int arr2[5] = { 10,20,30,40,50 };  //如果在初始化数据时没有全部填写完,那么剩下的没赋值的元素会被赋为0
	cout << arr2[4] << endl;
	//3、数据类型  数组名[ ] = { 值1,值2 ...};
	int arr3[] = { 100,20,30,40,50,6 };   //填多少个数据,数组就有多少元素
	cout << arr3[3] << endl;
	//利用循环输出数组中的元素
	for (int i = 0; i < 6; i++)
	{
		cout << arr3[i] << " ";
	}
	cout << endl;

	system("pause");

	return 0;
}

4、一维数组名称的用途

(1)可以统计整个数组在内存中的长度。对数组名使用sizeof,可以获取整个数组占内存空间的大小。

(2)可以获取数组在内存中的首地址。直接打印数组名,可以查看数组所占内存的首地址。

#include<iostream>
using namespace std;

int main() {

	int arr[5] = { 1,2,3,4,5 };
	cout << sizeof(arr) << endl;          //统计整个数组在内存中的长度
	cout << sizeof(arr[0]) << endl;       //统计一个元素在内存中的长度
	cout << sizeof(arr) / sizeof(arr[0]) << endl;  //统计数组元素个数
	cout << arr << endl;        //获取数组在内存中的首地址,默认以十六进制展示
	cout << (int)arr << endl;   //获取数组在内存中的首地址,以十进制展示
	cout << (int)&arr[0] << endl;  //获取数组中第一个元素的地址,以十进制展示(要加取址符&)
	cout << (int)&arr[1] << endl;  //获取数组中第二个元素的地址,以十进制展示(要加取址符&)

	system("pause");

	return 0;
}

5、举例

(1)例1:

#include<iostream>
using namespace std;

int main() {

	/*在一个数组中记录了五只小猪的体重,如:int arr[5] = {300,350,200,400,250};
    找出并打印最重的小猪体重。*/
	int arr[5] = { 300,550,400,200,250 };
	int a = 0;
	int b = 0;
	for (int i = 0; i < 4; i++)
	{
		if (arr[i] > arr[i + 1])
		{
			a = arr[i + 1];
			arr[i + 1] = arr[i];      //把最大值往后排,使数组最后一个元素为最大值
			arr[i] = a;
		}
		else
		{
			b = i + 2;
		}
	}
	cout << arr[4] << endl;
	cout << "最重的是第" << b << "只猪";

	system("pause");

	return 0;
}

(2)例2:

#include<iostream>
using namespace std;

int main() {

	/*案例描述:请声明一个5个元素的数组,并且将元素逆置
    (如原数组元素为:1,3,2,5,4;逆置后输出结果为:4,5,2,3,1)*/
	int arr[5] = { 1,3,2,5,4 };
	int temp = 0;                              //用于做数据交换的变量
	int start = 0;                             //定义起始位置的下表
	int end = sizeof(arr) / sizeof(arr[0])-1;  //定义结束位置的下表
	for (; start<end;)                //当前标大于后标,证明互换完成,终止循环
	{
		temp= arr[start];
		arr[start] = arr[end];
		arr[end] = temp;
		end--;
		start++;
	}
	for (int j = 0; j < 5; j++)
	{
		cout << arr[j] << endl;
	}

	system("pause");

	return 0;
}

(3)例3(冒泡排序):

#include<iostream>
using namespace std;

/*
	冒泡排序是最常用的排序算法,可对数组内元素进行排序,步骤如下:
	①比较相邻的元素,如果第一个比第二个大,就交换他们两个。
	②对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值,第一轮比较结束。
	③重复以上的步骤,每轮的比较次数-1,直到不需要比较。
*/

int main() {

	//冒泡排序
	//排序总轮数=元素个数-1;每轮对比次数=元素个数-当前排序轮数
	int arr[9] = { 4,2,8,0,5,7,1,3,9 };
	cout << "排序前:";
	for (int i = 0; i < 9; i++)
	{
		cout << arr[i] << "  ";
	}
	cout << endl;
	int temp = 0;
	for (int i = 0; i < 9 - 1; i++)
	{
		for (int j = 0; j < 9 - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
	cout << "排序后:";
	for (int i = 0; i < 9; i++)
	{
		cout << arr[i]<< "  ";
	}
	cout << endl;

	system("pause");

	return 0;
}

三、二维数组

1、二维数组的定义

二维数组是以行和列(即二维)形式排列的固定数目元素的集合,并且组成数组的每个元素的类型都相同,即带有两个下标的数组。定义二维数组的语法是:

        <数据类型> <数组名>[<表达式1>][<表达式2>];

(1)数据类型是类型说明符,数组名是数组的名字,数组名的命名规范与变量名命名规范一致,不要和变量重名。

(2)两个表达式都是值为正整数的常量表达式,分别用来指定数组中行和列的数目。

2、二维数组的初始化

与一维数组相同,二维数组也可以在定义时初始化,有三种形式:

(1)指定数组的行数和列数,在同一行中的元素可以用花括号括起来,并用逗号分隔,这种方式最为直观,推荐使用。

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

(2)指定数组的行数和列数,初始化列表中的数据按顺序从二维数组的第一行第一列开始逐行赋值。

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

(3)仅指定数组的列数(无论如何列数都不能省略),程序会根据初始化列表的元素个数推断出二维数组的行数,然后从二维数组的第一行第一列开始逐行赋值。

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

3、访问数组元素的语法形式

        <数组名>[<表达式1>][<表达式2>]

(1)两个表达式是非负整数的表达式。

(2)表达式1指定行下标,表达式2指定列下标。

(3)二维数组可以看做一个元素类型为一维数组的一维数组,有r个元素(r为行数),其中每个一维数组的长度均为l(l为列数),一维数组下标从0开始,其下标的范围是0到l-1。(对于二维数组a[r][l],“a[x]”的语意是把二维数组的第x+1行元素当作一维数组,“a[x]”可视作该一维数组的名称

一维数组a[0]

a[0][0] = <数据1>

a[0][1] = <数据2>

a[0][l-1] = <数据l>

一维数组a[1]

a[1][0] = <数据l+1>

a[1][1] = <数据l+2>

a[1][l-1] = <数据2l>

一维数组a[2]

a[2][0] = <数据2l+1>

a[2][1] = <数据2l+2>

a[2][l-1] = <数据3l>

一维数组a[r-1]

a[r-1][0] = <数据(r-1)l+1>

a[r-1][1] = <数据(r-1)l+2>

a[r-1][l-1] = <数据rl>

#include<iostream>
using namespace std;

int main() {

	//二维数组定义方式
    //数组类型 数组名 [行数][列数]
	int arr[2][3];
	arr[0][0] = 1;
	arr[0][1] = 2;
	arr[0][2] = 2;
	arr[1][0] = 4;
	arr[1][1] = 5;
	arr[1][2] = 6;
	for (int i = 0; i < 2; i++)   //用嵌套循环实现一行一行地输出,外层循环打印行,内层循环打印列
	{
		for (int j = 0; j < 3; j++)
		{
			cout << arr[i][j] << " ";  
		}
		cout << endl;
	}
	//数据类型 数组名[行数][列数] = { {数据1,数据2 } ,{数据3,数据4 } };
	int arr2[2][3] =
	{
		{1,2,3},
		{4,5,6}
	};         //记得加分号
	//数据类型 数组名[行数][列数] = { 数据1,数据2 ,数据3,数据4  };
	int arr3[2][3] = { 1,2,3,4,5,6 };
	//数据类型 数组名[][列数] = { 数据1,数据2 ,数据3,数据4  };
	int arr4[][3] = { 1,2,3,4,5,6 };  //在定义二维数组时,如果初始化了数据,可以省略行数

	system("pause");

	return 0;
}

4、二维数组数组名的用途

(1)可以统计整个数组在内存中的长度。对数组名使用sizeof,可以获取整个数组占内存空间的大小。

(2)可以获取二维数组在内存中的首地址。直接打印数组名,可以查看数组所占内存的首地址。

#include<iostream>
using namespace std;

int main() {

	//二维数组数组名
	int arr[2][3] =
	{
		{1,2,3},
		{4,5,6}
	};

	cout << "二维数组大小: " << sizeof(arr) << endl;
	cout << "二维数组一行大小: " << sizeof(arr[0]) << endl;
	cout << "二维数组单个元素大小: " << sizeof(arr[0][0]) << endl;

	cout << "二维数组行数: " << sizeof(arr) / sizeof(arr[0]) << endl;
	cout << "二维数组列数: " << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;

	//地址
	cout << "二维数组首地址:" << arr << endl;
	cout << "二维数组第一行地址:" << arr[0] << endl;
	cout << "二维数组第二行地址:" << arr[1] << endl;

	cout << "二维数组第一个元素地址:" << &arr[0][0] << endl;
	cout << "二维数组第二个元素地址:" << &arr[0][1] << endl;

	system("pause");

	return 0;
}

5、举例

#include<iostream>
using namespace std;
#include<string>

int main() {

	//有三名同学(张三,李四,王五),在一次考试中的成绩分别如表,请分别输出三名同学的总成绩
	int arr[3][3]=
	{
		{100,100,100},
		{90,50,100},
		{60,70,80}
	};
	int sum[3] = { 0,0,0 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			sum[i] = sum[i] + arr[i][j];
		}
	}
	string name[3] = { "张三","李四","王五" };
	for (int i = 0; i < 3; i++)
	{
		cout << name[i] << "的总成绩为" << sum[i] << endl;
	}

	system("pause");

	return 0;
}

四、字符数组

1、string类型

(1)string类型又称字符串类型,用于表示一串字符。

(2)字符串常量的两侧需要添加双引号,默认添加转义字符’\0’(空字符)结尾。

(3)在使用string数据类型之前,需要在程序中包含头文件string并声明其所在的名字空间std。

2、char类型的一维数组

(1)char类型的一维数组的存储结构如下所示:

a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[n-1]

‘字符1’

‘字符2’

‘字符3’

‘字符4’

‘字符5’

‘字符6’

‘字符n-1’

(2)字符串以空字符结尾,而字符数组可以不含空字符。

(3)字符串可以存储在一维字符数组内,比如:

char word[10] = “Hello”;  //存储该字符串至少需要6个char存储空间,因为要算上’\0’

(4)由双引号括起来的字符串常量具有静态字符串数组类型,换句话说,字符串常量也可视作一个字符数组。

3、举例

#include<iostream>
using namespace std;
#include<string>    //在用C++风格字符串时要有这个头文件

int main() {

	//1、C风格字符串: char 变量名[] = "字符串值"
	char str[] = "Hello World";  //字符串名后面要加中括号[];等号后面要用双引号包含字符串
	cout << str << endl;

	//2、C++风格字符串: string  变量名 = "字符串值"
	string str2 = "Hello world"; //要包含头文件 #include<string>
	cout << str2 << endl;

	system("pause");

	return 0;
}

4、常用字符串函数

函数名称、类型和参数

函数功能

char * strcpy-s(char * s1, char * s2)

将字符串s2拷贝到字符串变量s1中,s1的长度应大于等于s2的长度,正常情况下返回0,否则返回非0。

char * strcat-s(char * s1, char * s2)

将s2的内容添加到s1的末端,不修改s2,s1的长度应足够大,正常情况下返回0,否则返回非0。

int * strcmp(char * s1, char * s2)

如果s1小于s2,返回一个负数;如果s1等于s2,返回0里如果s1大于s2,返回一个正数。

int * strlen(char * s)

返回字符串s的长度,以空字符为结束标志,末尾的空字符不计算在内

char * strstr(char * s1, char * s2)

在字符串s1中从左边开始查找字符串s2,若查找成功则返回s2在s1中首次出现的位置,否则返回NULL

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值