技术交流QQ群:1027579432,欢迎你的加入!
1.Cpp中的数组
- C++支持数组数据结构,它可以存储一个固定大小的相同类型的元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。数组的声明并不是声明一个个单独的变量,如a0,a1,a2,a3,a4...,a99,而是声明一个数组变量,比如as,然后使用as[0],as[1],as[2],...,as[99]来代表一个个单独的变量,数组的特定元素可以通过索引来访问。所数组都是由连续的内存位置组成,最低的地址对应第一个元素,最高的地址对应最后一个元素。
2.声明数组
- 在C++在声明一个数组,需要指定元素的类型和元素的数量,如下所示:
数据类型 数组名[元素数量];
- 上面声明的格式是一维数组的声明,其中元素个数必须是一个大于0的整型常量,数据类型可以是任意有效的C++数据类型。如声明一个类型为double的包含10个元素的数组balance,声明语句是: double balance[10];
3.初始化数组
- 在C++中,可以逐个初始化数组,也可以使用一个初始化语句,如下所示:
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
- 大括号{ }之间的值的数目不能大于在数组声明时在方括号[ ]中指定的元素数目。
-
如果省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,如果是下面的格式,将创建一个数组,它与前一个实例中所创建的数组是完全相同的
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
- 为数组中某个元素赋值的实例,下面的语句把数组中第五个元素的值赋为666.6。所有的数组都是以0作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去1。
balance[4] = 666.6;
4.访问数组元素
-
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:
double salary = balance[3];
- 声明数组、初始化数组、访问数组元素实例如下:
#include "iostream" #include "iomanip" using namespace std; using std::setw; // setw() 函数来格式化输出 int main(){ int a[10]; // 声明一个包含10个元素的整型数组 // 初始化数组 for (int i = 0; i < 10; i++) a[i] = i + 100; cout << "元素索引" << setw(13) << "元素值" << endl; // 输出数组中的每个元素 for (int j = 0; j < 10; j++) cout << setw(7) << j << setw(13) << a[j] << endl; return 0; }
5.与数组有关的概念
- 5.1 多维数组
- C++支持多维数组。多维数组声明的一般形式如下:
数据类型名 数组名[size1][size2]...[sizeN];
- 例如,下面的声明创建了一个三维整型数组:
int tridim[5][10][4];
- 二维数组
- 多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个x行y列的二维整型数组,形式如下:
数据类型 数组名[x][y];
-
一个二维数组可以被认为是一个带有x行和y列的表格。下面是一个二维数组,包含3行和4列:
- 因此,数组中的每个元素是使用形式为a[i][j]的元素名称来标识的,其中a是数组名称,i和j 是唯一标识a中每个元素的下标。
- 初始化二维数组
- 多维数组可以通过在括号内为每行指定值来进行初始化,下面是一个带有3行4列的数组。
int a[3][4] = { {0, 1, 2, 3}, /* 初始化索引号为 0 的行 */ {4, 5, 6, 7}, /* 初始化索引号为 1 的行 */ {8, 9, 10, 11}, /* 初始化索引号为 2 的行 */ };
-
内部嵌套的括号是可选的,下面的初始化与上面是等同的:
int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
- 多维数组可以通过在括号内为每行指定值来进行初始化,下面是一个带有3行4列的数组。
- 访问二维数组元素
-
二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:
int val = a[2][3];
- 二维数组如下:
// 1.二维数组 int aa[5][2] = {{0, 0}, {1, 2}, {2, 4}, {5, 7}, {9, 10}}; for (int i = 0; i < 5; i++){ for (int j = 0; j < 2; j++){ cout << "aa[" << i << "][" << j << "] = " << aa[i][j] << endl; } }
-
二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:
- 多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个x行y列的二维整型数组,形式如下:
- 5.2 指向数组的指针----数组指针
- 数组名是一个指向数组中第一元素的常量指针(int const *p;),因此,double a[40];a是一个指向&a[0]的指针,即数组a的第一个元素的地址。因此,下面的程序片段p赋值给a的第一个元素的地址:
double *p; double a[10]; p = a;
- 使用数组名作为常量指针是合法的,因此*(a+4)是一种访问a[4]数据的合法方式。一旦把第一个元素的地址存储在p中,就可以使用*p,*(p+1),*(p+2)等来访问数组的元素。
// 2.指向数组的指针:数组指针 double b[5] = {12.4, 3.1, 5.6, 0.8, 5.4}; double *p; // 一个指向double型的指针,可以存储一个double类型变量的地址 p = b; cout << "使用指针的数组值 " << endl; for (int i = 0; i < 5; i++) cout << "*(p + " << i << ") = " << *(p + i) << endl; cout << "使用b作为地址的数组值 " << endl; for (int i = 0; i < 5; i++) cout << "*(b + " << i << ") = " << *(b + i) << endl;
- C++中,将char*或char[]传给cout进行输出,结果会是整个字符串,如果想要获得字符串的地址(第一个字符的地址),可以使用方法:强制转化为其他指针(非char),可以是void*, float*,int*,double*等。使用&s[0]不能输出s[0]的地址,因为&s[0]将返回char*,对于char*,cout会将其作为字符串来处理,向下查找字符并输出直到字符结束*。
// C++中,将char*或char[]传递给cout进行输出,结果会是整个字符串。如果想要获得字符串的地址,强制转化为其他指针(非char*) char var[MAX] = {'a', 'b', 'c'}; char *ptr; // 指针中的数组地址 ptr = var; for (int i = 0; i < 3; i++){ cout << "var[" << i << "]的地址是 = " << (int *)ptr << endl; cout << "var[" << i << "] = " << *ptr << endl; ptr++; // 移动到下一个位置 }
- 5.3 C++中传递数组给函数
- C++中可以通过指定不带索引的数组名来传递一个指向数组的指针
- C++传数组给一个函数,数组类型自动转换为指针类型,因此传的实际是地址
- 如果想在函数中传递一个一维数组作为参数,必须用下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样的,也可以传递一个多维数组作为形式参数。
- 方式1(形式参数是一个指针))
void func1(int *param){ ... }
- 方式2(形式参数是一个已定义大小的数组))
void func1(int params[10]){ ... }
- 方式3(形式参数是一个未定义大小的数组)
void func1(int params[]){ ... }
- 方式1(形式参数是一个指针))
- 实例如下:
// 3.C++中把数组传递给函数(方法1) int bb[5] = {1000, 2, 3, 17, 50}; double avg, avg1; // 传递一个指向数组的指针作为参数 avg = getAverage(bb, 5); cout << "平均值: " << avg << endl; /*-----------------------方法2-----------------------*/ int bbb[5] = {1000, 2, 3, 17, 50}; int *ptr1 = bbb; // 分别计算数组元素个数,以及整型指针的字节数 size_t bbb_size = sizeof(bbb) / sizeof(int); size_t ptr1_size = sizeof(ptr1); cout << "bbb size = " << bbb_size << endl; cout << "ptr1 size = " << ptr1_size << endl; avg1 = getAverage1(bbb, 5); cout << "平均值: " << avg1 << endl; // 方法1(下面的例子中把数组作为参数,同时还传递了另一个参数) double getAverage(int arr[], int size){ int i, sum = 0; double avg; cout << "sizeof(arr) = " << sizeof(arr) << endl; for (i = 0; i < size; i++) sum += arr[i]; avg = double(sum) / size; return avg; } // 方法2 double getAverage1(int *arr, int size){ int i, sum = 0; double avg; cout << "sizeof(arr) = " << sizeof(arr) << endl; for (i = 0; i < size; i++) sum += arr[i]; avg = double(sum) / size; return avg; }
- 5.4 从函数返回数组
-
C++不允许返回一个完整的数组作为函数的参数。但是,可以通过指定不带索引的数组名来返回一个指向数组的指针。C++不支持在函数外返回局部变量的地址,除非定义局部变量为static变量。如果想要从函数返回一个一维数组,必须声明一个返回指针的函数(指针函数),如下:
int * func(){ ... }
- 实例如下:
// 要生成和返回随机数的函数 int * getRandom(){ static int r[10]; // C++不支持在函数外返回局部变量的地址,除非定义局部变量为static变量 // 设置随机数种子 srand((unsigned)time(NULL)); for (int i = 0; i < 10; i++){ r[i] = rand(); cout << "r[" << i << "] = " << r[i] << endl; } return r; } // 4.从函数返回数组----指针函数 int *p1; p1 = getRandom(); for (int i = 0; i < 10; i++) cout << "*( p1 + " << i << ") = " << *(p1 + i) << endl;
6.数组中的细节知识
- 直接初始化字符数组char是特殊的,这种初始化需要一个null作为结尾的。如下:
char a1[] = {'p', 'y', 't', 'h', 'o', 'n'}; // 初始化,没有 null char a2[] = {'p', 'y', 't', 'h', 'o', 'n', '\0'}; // 初始化,明确有 null char a3[] = "python"; // null 终止符自动添加 const char a4[6] = "python"; // 报错,没有 null 的位置
- 数组的大小是固定的,不能额外增加元素,当想定义不固定大小的字符时,使用vector!
vector<int> vec; // 创建向量用于存储整型数据 int m; // 显示vec初始大小 cout << "vector size = " << vec.size() << endl; // 向向量vec追加5个整数值 for(int m = 0; m < 5; m++) vec.push_back(m); // 显示追加后vec的大小 cout << "追加后的vector size = " << vec.size() << endl;
- 在C++中,setw(int n)用来控制输出间隔,(n-1个空格),setw()默认填充的内容是空格,可以使用setfill()配合使用设置其他字符填充。
cout << setfill('*') << setw(5) << 'a' << endl;
- 静态与动态数组
静态 int array[100]; 定义了数组 array,并未对数组进行初始化 int array[100] = {1, 2}; 定义并初始化了数组 array 动态 int * array = new int[100]; 分配了长度为 100 的数组 array delete [] array; 动态 int * array = new int[100]{1, 2}; 为长度为100的数组array初始化前两个元素 delete [] array;
- 数组初始化时可以用聚合方法,但是赋值时候不可以用聚合方法。举例如下:
int array[] = {5,10,20,40}; // 合法 int array[]; int main() { array[] = {5,10,20,40}; // 不合法 return 0; }
- 数组在使用时可以是一个含有变量的表达式,但是,在数组声明时必须用常量表达式。例如:
// 合法 const int a=19; long b[a]; // 合法 const int a=19; long b[a+5]; // 不合法 int a=19; long b[a+5];
- 声明一个任意长度的数组,可以用显式的类型转换,例如:
int a=19; int b[(const int)a];
- 也可以定义一个常量来声明,例如:
int a=19; const int a1=a; int b[a1];
- Vector(向量): C++中的一种数据结构,确切的说是一个类。它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间的目的。
- 用法:
- 1.文件包含:
- 首先在程序开头处加上 #include<vector> 以包含所需要的类文件vector;还有一定要加上 using namespace std;
- 2.变量声明:
- 2.1例: 声明一个 int 向量以替代一维的数组: vector <int> a; (等于声明了一个 int 数组 a[],大小没有指定,可以动态的向里面添加删除)。
- 2.2例: 用vector代替二维数组.其实只要声明一个一维数组向量即可,而一个数组的名字其实代表的是它的首地址,所以只要声明一个地址的向量即可,即: vector <int *> a。同理想用向量代替三维数组也是一样,vector <int**>a;
- 3.具体的用法以及函数调用:
- 3.1 得到向量中的元素和数组一样,例如:
vector <int *> a int b = 5; a.push_back(b);//该函数下面有详解 cout << a[0]; //输出结果为5
- 使用数组给向量赋值:
vector<int> v( a, a+sizeof(a)/sizeof(a[0]) );
- 或者:
int a[]={1,2,3,4,5,6,7,8,9}; typedef vector<int> vec_int; vec_int vecArray(a,a+9);
- 3.1 得到向量中的元素和数组一样,例如:
- 1.文件包含:
- 用法: