C++ 数组知识点摘录

一维数组

声明一维数组的一般形式为:
<元素类型> <数组名>[<元素个数>];
<元素类型>指明了数组元素的类型,可以是整型、实型、布尔型和字符型等简单数据类型,也可以是用户定义的复合数据类型,包括数组类型;
<数组名>由标识符充当,是整个数组的名字;<数组名>后面的方括号是必须的,C 和 C++ 把[ ]作为运算符处理,其优先级与括号相同,左结合;
方括号中的<元素个数>是整常量表达式,可以省略,表示数组元素的个数,注意数组元素的下标是从零开始计数的。

例如:

int a[10];

上述声明了一个数组名为 a 的整型数组,它有10个整型元素,下标的变化范围是0~9。

数组元素的访问

给定一个数组,我们可以采用以下形式访问数组里的元素:

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

<下标表达式>是值为整型的表达式,它指明了拟访问的数组元素的下标。
例如,数组 a 的10个元素可以依次表示为:a[0] ,a[1] ,a[2] ,…… ,a[9]。
注意:如果访问数组元素时使用的下标超出了元素的数目,会导致访问越界错误。C 和 C++ 不检查访问越界,如果发生了访问越界,有可能导致程序在运行时发生错误。
数组的各元素按顺序存储在一片连续的内存单元中。数组int a[10]的内存分配见下图所示:

在这里插入图片描述

数组的初始化

数组初始化的方法是把初始值按顺序放在花括号中,数值之间用逗号分开。
例如:

int  a[10]={4};
float  r[20]={0.1, 5.1};
double  d[3]={10.0,5.0,1.0};

需要注意以下两点:
1.如果初始值的数目小于数组元素的数目,数组剩余的元素被自动初始化为 0。
例如:

int  n[5]={0};  //将数组 n 的所有数组元素都初始化为 0

注意:初始值的数目不能超过数组中元素的数目。
2.声明数组时可以省略数组元素的数目,这时系统会根据初始值的数目来确定数组元素的数目。
例如:

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

实际上声明了一个包含了5个整型元素的数组 x :x[0] …… x[4] ,其值分别被初始化为 1 ,…… ,5。
这里再强调一下:我们不能直接操作某个数组,只能对数组中的某一个元素进行操作。也就是说,数组需要“拆开来用”,每次只能操作一个数组元素,操作数组元素的方法和操作普通变量的方法相同,“拆开数组”的方法就是数组名加下标访问数组元素的方式。
例如:

a[7]= 4;     // 给数组元素 a[7] 赋值
x = 2 * a[i+2];     // 数组元素作表达式的运算量

数组的遍历

对于数组而言,最常见的用法是使用循环语句来操作数组,对数组元素进行遍历和处理。
例如下面的程序对数组 n 中的元素求和:

int n[10] = {12,34,55,71,1,65,423,19,540,10};     // 声明数组n并初始化
int i, sum = 0;     // 定义循环变量和累加和变量
// 循环遍历数组并求和
for (i = 0; i <= 10-1; i++)
{
    sum += n[i];
}
cout << "The summary is: " << sum << endl;     // 输出求和结果

数组作为函数的参数

由于数组的存储是内存中一块连续的单元,数组元素的个数也是不确定的(不同的数组可能包含不同个数的数组元素),因此函数传递数组需要传递两个信息,一个是数组的地址(数组名就是数组地址),告诉被调用函数该数组存放在内存什么地方,另一个是数组元素个数,告诉被调用函数访问该数组时允许的下标范围(防止访问越界)。
参数传入一个整型数组的函数的函数原型如下:

void  convertScores(int a[],  int len);

第一个参数 a 是一个数组类型的形式参数。该参数 a 接收传入数组的数组名,也就是数组的首地址,其后的方括号中的数组长度不需要,即使有,编译器也会将其忽略;
第二个参数 len 是整型参数。该参数 len 传入数组 a 的长度,即 a 有 len 个数组元素,访问 a 的元素的下标范围就是 0 到 len-1。
例如:下面的程序将一个整型数组中存放的10名同学的百分制成绩转换为5分制,并输出。

#include <iostream>
using namespace std;
// 分数转换函数的函数原型,其中:s-学生成绩数组名,len-学生成绩个数
void convertScores(int s[], int len);
int main()
{
    // 定义学生成绩数组并初始化
    int scores[10] = {85, 63, 72, 52, 95, 82, 77, 69, 88, 73};
    convertScores(scores, 10);     // 调用分数转换函数convertScores
    // 转换完成后输出分数数组中的分数
    for(int i = 0; i < 10; i++)
        cout << "scores["<<i<<"] = " << scores[i] << endl;
    return 0;
}
// 函数convertScores
void convertScores(int s[], int len)
{
    // 逐个访问数组中的每个元素,并做转换
    for (int i = 0; i < len; i++)
        s[i] = s[i]/20;     // 修改 s[i] 实际上就是修改 main 函数中的 scores[i],因为 s 和 scores 拥有相同的地址值
}

程序的输出为:

scores[0] = 4
scores[1] = 3
scores[2] = 3
scores[3] = 2
scores[4] = 4
scores[5] = 4
scores[6] = 3
scores[7] = 3
scores[8] = 4
scores[9] = 3

上述示例中函数调用convertScores(scores, 10);导致数组 scores 中的每个元素都被转换了。也就是说,在被调用函数体内对数组 s(形式参数)的元素进行的修改操作实际上作用在了数组 scores(实在参数)的元素上,这是否就是传引用呢?
实际上,C 和 C++ 在处理数组参数时是严格地采取了传值方式。
参数传递数组的方式有比较特殊的地方,要理解传递数组的机制,首先要明确下面两点:

  • 和一般变量一样,数组名也是有值的,数组名的值就是数组的第一个元素的地址(首地址);
  • 和一般变量一样,数组作为函数参数进行传递时,传递的也是数组变量的值,即数组第一个元素的地址。
    由于数组名的值就是数组的第一个元素的地址,而访问数组元素的方式是数组名加下标(也就是首地址加下标),才使得尽管采取的是传值方式,但在被调用函数 convertScores 中,通过 s 加下标的方式访问数组元素,实际上访问的就是 main 函数中定义的数组 scores 的数组元素,因为 s 和 scores 代表了同样的地址位置。
    (注意定义函数时二维数组和三维数组的传递:int f(a[ ][6] , int b[ ][2][3]),多维数组以此类推,其中a [ ][6] 表示数组 a 的二维大小为6,三维数组的类似)
    ——————————————————————————————————
    由于 C 和 C++ 中 int 类型的表示范围有限,为−2147483648~2147483647,所以超过10位的整数就会溢出。

例如下面的程序:

int a;
cin >> a;
cout << a << endl;

测试输入:77777777777

输出结果:-858993460

很显然整型变量 a 无法表示超出范围的数。

字符串数组

在 C 和 C++ 中,一个字符串就是用一对双引号括起来的一串字符。字符串的存储是利用一维字符数组来实现的,该字符数组的长度为待存字符串的长度加1。即如果一个字符串的长度为 n ,则用于存储该字符串的数组的长度应为 n+1。

当字符串存入数组时,是把每个字符依次存入到数组的对应元素中,即把第一个字符存入到下标为0的元素中,第二个字符存入到下标为1的元素中,依次类推,最后会把一个空字符 ′\0′ 存入到下标为 n 的元素中(这里假定字符串的长度为 n)。字符存储的是它的 ASCII 码或区位码。

例如用一维字符数组 a[12] 来存储字符串 ″Strings.\n″ 时,数组 a 中的内容参见下图:
在这里插入图片描述

接下来,我们可以利用字符串来初始化字符数组,如:

char a[10] = ″array″;
char b[20] = ″This is a pen.;
char c[8] = ″″;
  • 第一条语句定义了字符数组 a[10] 并被初始化为“array”,其中 a[0] ~ a[5] 元素的值依次为字符‘a’, ‘r’,‘r’,‘a’,‘y’和‘\0’;

  • 第二条语句定义了字符数组 b[20] ,其中 b[i] 元素( 0 ≤ i ≤ 13 )被初始化为所给字符串中的第 i+1 个字符,b[14] 被初始化为字符串结束标志符‘\0’;

  • 第三条语句定义了一个字符数组 c[8] 并初始化为一个空串,此时它的每个元素的值均为‘\0’。

我们可以看到对于字符串而言,它的存储总是以 ‘\0’ 结尾。

例如下面的程序可以计算并输出字符串的长度:

char s[1000];     // 定义一维字符数组
cin >> s;     // 输入一个字符串存入字符数组s中
int i = 0;
// 逐个判断字符数组的某一位是否是'\0',该字符意味着字符串的结束
while(s[i] != '\0')
    i++;
cout << i << endl;     // 输出字符串的长度

当然 cstring 头文件中还有 strlen( ) 函数直接计算字符串中字符个数(不含 ‘\0’ )

获取字符对应的整数

由于使用字符形式存储数字时,存储的是数字对应的 ASCII 码,由于在 ASCII 码表中字符‘0’到字符‘9’是连续存放的,所以下面的程序可以获得字符对应的数字:

char c = '2';     // c 中存储的是字符 '2' 的ASCII码
int k = c - '0';     // k 即为字符 '2' 对应的整数 2

从而实现了字符型’转换‘为整型

多维数组 / 二维数组

C 和 C++ 中有多个下标的数组称为多维数组。具有两个下标表示的数组称为二维数组。

例如:

int a[3][4];
char c[4][3][5];

其中 a 是一个整型二维数组,c 是一个字符型三维数组。

数学上的二维矩阵可以看成其元素是向量的向量,也可以看成元素是一维数组的一维数组,所以二维矩阵可以用二维数组表示出来。

上述示例中的二维数组 a 有 2 个下标:

  • 第1个下标可以称为行,变化范围是0~2;

  • 第2个下标可以称为列,变化范围是0~3。

因此,a 共有3行4列,12个元素。每个数组元素用数组名和两个下标表示。

例如:a[1][2]和a[2][1]分别表示第1行第2列的元素和第2行第1列的元素(从第0行0列开始)。

二维数组 a 的逻辑结构如下图所示:
在这里插入图片描述

多维数组在内存中“按行”存放,越靠后的下标先变化,越靠前面的下标后变化。二维数组 a 在内存中的物理存储形式如下图所示:
在这里插入图片描述

二维数组的初始化

二维数组可以在声明时初始化。

例如,下面是对2∗2的二维数组 matrix 的初始化:

int  matrix[2][2]{ {1, 2}, {3, 4} };

数组元素的值用花括号按行分组,上述示例中将整常数1和2赋给了matrix[0][0]和matrix[0][1],将整常数3和4赋给了matrix[1][0]和matrix[1][1]。

特别注意以下两点:

  • 如果指定行没有足够的初始值,与一维数组类似,则该行的剩余元素初始化为0,如果初始值只给出了部分行,则剩余的行中的所有元素都被初始化为0;

  • 如果初始值之间没有用花括号按行分组,那么编译器会自动用初始值顺序初始化第0行的元素、第1行的元素、…… 。如果初始值的数目少于数组元素的数目,剩余的元素自动初始化为0。

例如:

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

初始化完成后,数组 a 的各元素的值为:

matrix[0][0] = 1 
matrix[0][1] = 2 
matrix[0][2] = 3
matrix[0][3] = 4 
matrix[1][0] = 5 
matrix[1][1] = 6 

其余元素均为 0 。

二维数组的操作

二维数组的典型操作方法:使用两重循环对数组进行遍历,并逐个元素进行操作。两重循环分别遍历两个下标的范围。

例如:下面的程序可以遍历二维数组并输出每一个元素的值。

// 定义并初始化二维数组m
int m[4][4] = { {1, 1, 1, 1},
                {2, 2, 2, 2},
                {3, 3, 3, 3},
                {4, 4, 4, 4}};
// line遍历第一维
for (int line = 0; line < 4; line++)
{
    // col遍历第二维,输出某一行
    for (int col = 0; col < 4; col++)
        cout << "\t" << a[line][col];
    // 输出完一行后换行
    cout << endl;
}

输出:

	1	1	1	1
	2	2	2	2
	3	3	3	3
	4	4	4	4
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值