在程序设计中,将同一数据类型的数据按照一定形式有序的组织起来,这些有序数据的集合就称为数组。
一个数组有一个统一的数组名,可以通过数组名和下标来确定数组中的元素。
一、一维数组
(1)数组的声明
int a[10];
int表示数组的元素的类型,a表示数组名,10表示数组的长度为10;
(2)数组的引用
数组引用的一般格式为:
数组名[下表]
比如:
a[0]
我们可以通过数组的引用输出数组某个位置的值:
int a[10];
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
cout << "a[2]=" << a[2] << endl;
cout << "a[3]=" << a[3] << endl;
输出结果是:
a[0]=-858993460
a[1]=-858993460
a[2]=-858993460
a[3]=-858993460
看到数组的值就可以知道,a[0]、a[1]、a[2]、a[3]是非法的,这个数组没有初始化,并没有主动给予这些数组的值。
(3)数组的初始化
一维数组的初始化有两种方式:单一数组元素赋值
和 聚合方法赋值
单一数组元素赋值:
a[0] = 0
a[0] = 0就是对单一数组元素进行赋值, 也可以用变量控制数组下标进行赋值:
a[i] = 0;
演示代码1如下:
int a[10];
a[0] = 0;
a[1] = 1;
a[2] = 2;
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
cout << "a[2]=" << a[2] << endl;
cout << "a[3]=" << a[3] << endl;
输出结果是:
a[0]=0
a[1]=1
a[2]=2
a[3]=-858993460
演示代码2如下:
int a[10];
for (int16_t i = 0; i < 3; i++)
{
a[i] = i;
}
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
cout << "a[2]=" << a[2] << endl;
cout << "a[3]=" << a[3] << endl;
输出结果是:
a[0]=0
a[1]=1
a[2]=2
a[3]=-858993460
如果对a[10]进行赋值,就会发生角标越界异常,因为在声明数组a时,它的长度是10,所以不存在第11个元素。
聚合方法赋值:
数组不仅可以逐一对元素赋值,还可以通过大括号进行多个元素的赋值。
演示代码如下:
int a[3] = {0, 1, 2};
int b[] = { 0, 1, 2, 3 };
cout << "输出数组a的值:" << endl;
for (int16_t i = 0; i < 3; i++)
{
a[i] = i;
cout << "a[" << i << "]=" << a[i] << " ";
}
cout << endl;
cout << "输出数组b的值:" << endl;
for (int16_t j = 0; j < 4; j++)
{
b[j] = j;
cout << "b[" << j << "]=" << b[j] << " ";
}
输出结果是:
输出数组a的值:
a[0]=0 a[1]=1 a[2]=2
输出数组b的值:
b[0]=0 b[1]=1 b[2]=2 b[3]=3
以上数组a明确指定了数组的长度为3,数组b的长度由元素的个数决定。
数组a的元素个数不能大于3。
二、二维数组
(1)数组的声明
int a[3][4];
int表示数组的元素的类型,a表示数组名,[3][4]表示3行4列,数组的长度是3x4 = 12;
(2)数组的引用
数组引用的一般格式为:
数组名[下表][下表]
比如:
a[2][3]
代码演示如下:
int a[3][4];
cout << "a[0][0]=" << a[0][0] << endl;
cout << "a[1][1]=" << a[1][1] << endl;
输出结果是:
a[0][0]=-858993460
a[1][1]=-858993460
(3)数组的初始化
二维数组的初始化和一维数组的初始化比较类似,直接看代码:
// 对元素逐一赋值
int a[3][4];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[0][3] = 4;
a[1][0] = 5;
a[1][1] = 6;
a[1][2] = 7;
a[1][3] = 8;
a[2][0] = 9;
a[2][1] = 10;
a[2][2] = 11;
a[2][3] = 12;
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 4; j++)
{
cout << "a[" << i << "][" << j << "] = " << a[i][j] << endl;
}
}
输出 结果是:
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[0][3] = 4
a[1][0] = 5
a[1][1] = 6
a[1][2] = 7
a[1][3] = 8
a[2][0] = 9
a[2][1] = 10
a[2][2] = 11
a[2][3] = 12
还有一种赋值方式是聚合赋值,代码如下:
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
数组a的长度为12,如果只赋值10个,那么输出结果是:
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[0][3] = 4
a[1][0] = 5
a[1][1] = 6
a[1][2] = 7
a[1][3] = 8
a[2][0] = 9
a[2][1] = 10
a[2][2] = 0
a[2][3] = 0
为了防止错误赋值,最好将赋值的数值写成3行4列:
int a[3][4] = {1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12};
还可以隐藏行数下标:
int a[][4] = {1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12};
三、字符数组
顾名思义,字符数组就是用来存放字符数据的数组。
字符数组的声明和初始化方法和一维数组一致,演示代码如下:
char a[3];
a[0] = 'A';
cout << "a[0]=" << a[0] << endl;
char b[3] = {'A','B','C'};
for (size_t i = 0; i < 3; i++)
{
cout << "b[" << i << "] = " << b[i] << endl;
}
char c[] = { 'A','B','C'};
for (size_t i = 0; i < 3; i++)
{
cout << "c[" << i << "] = " << c[i] << endl;
}
char d[] = "hello world";
cout << "d=" << d << endl;
char e[] = "hello world\0";
cout << "e=" << e << endl;
输出结果是:
a[0]=A
b[0] = A
b[1] = B
b[2] = C
c[0] = A
c[1] = B
c[2] = C
d=hello world
e=hello world
字符数组的 赋值可以去除大括号{},直接以字符串的方式赋值即可:
char d[] = "hello world";
“\0”是字符串的结束符,所以也可以写成
char e[] = "hello world\0";
结束符“\0”不能做为数组的值,也不能占位,它纯粹就是字符串的结束符。
四、字符串处理函数的使用
引入字符串库可以使用字符串的基本函数:
#include <string>
string库中常用的函数是:字符串连接函数(strcat)、字符串复制函数(strcpy)、字符串比较函数(strcmp)、获取字符串长度(strlen)。
(1)字符串长度
char str[] = "my name is zhangsan";
cout << "字符串的长度:" << strlen(str) << endl;
(2)字符串连接
先看下代码:
char str1[100] = "my name is ";
char str2[] = "zhangsan";
strcat_s(str1, strlen(str1) + strlen(str2) + 1, str2);
cout << "str1:" << str1 << endl;
输出结果是:
str1:my name is zhangsan
从代码中衍生出三个问题:
(1)str1为什么一定要指定长度,将100去掉行不行?
数组str1的长度必须指定,strcat_s的意思是,将str2拼接到str1中,所以必须让机器知道str1分配的内存够不够用。
(2)为什么使用strcat_s,而不使用strcat?
strcat已经不再安全,编译器会做SDL安全检查,解决方案是:(1)跳过SDL检查(2)使用strcat_s
(3)strcat_s的第二个参数是什么?
第二个参数是缓冲区的大小,缓冲区必须要装上:str1 + str2 +”\0“,拼接之后,str1和str2合并到str1中,”\0“虽然不会增加字符串的长度,但是字符串在内存中必然有一个”\0“结束符,”\0“会占用1字节的内存。
所以,应分配的缓冲区的合理大小为:
strlen(str1) + strlen(str2) + 1
(3)字符串比较
先看下代码:
char str1[] = "zhangsan";
char str2[] = "this is apple";
int cmpResult = strcmp(str1, str2);
if (cmpResult > 0)
{
cout << "str1 > str2" << endl;
}
else if (cmpResult < 0)
{
cout << "str1 < str2" << endl;
}
else
{
cout << "str1 = str2" << endl;
}
输出结果是:
str1 > str2
字符串的比较是先比较第一个字母,也就是说先比较 z 和 t 的大小,在26个英文字母中,a最小,z最大,字母的比较不区分大小写。
(3)字符串复制
为了安全考虑,使用strcpy_s来替代strcpy。
代码如下:
char str1[20] = "zhangsan";
char str2[] = "this is apple";
strcpy_s(str1, str2);
cout << "str1:" << str1 << endl;
strcpy_s的作用是将str2复制到str1中,所以需要保证str1能装的下str2,否则会报错。
str1的长度必须要明确,且能装的上str2。
strcpy_s可以传递3个参数,第二个参数可以指定缓存区的大小:
strcpy_s(str1, strlen(str2) + 1, str2);
缓冲区的大小必须要保证装得下str2,str2结尾存在结束符"\0",所以缓存区的大小必须考虑结束符。
[本章完...]
网友评论