C++中的数组

技术交流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.与数组有关的概念

与数组有关的概念.png
  • 5.1 多维数组
  • C++支持多维数组。多维数组声明的一般形式如下:
        数据类型名 数组名[size1][size2]...[sizeN];
    
  • 例如,下面的声明创建了一个三维整型数组:
        int tridim[5][10][4];
    
  • 二维数组
    • 多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个x行y列的二维整型数组,形式如下:
          数据类型 数组名[x][y];
      
    • 一个二维数组可以被认为是一个带有x行和y列的表格。下面是一个二维数组,包含3行和4列:


      二维数组.png
    • 因此,数组中的每个元素是使用形式为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};  
        
    • 访问二维数组元素
      • 二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:
            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;
                }
            }
        
  • 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[]){
              ...
          }
      
  • 实例如下:
    // 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);
          
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343