1. 程式人生 > >C++程式設計實現變長陣列

C++程式設計實現變長陣列

    1.變長一維陣列

    這裡說的變長陣列是指在編譯時不能確定陣列長度,程式在執行時需要動態分配記憶體空間的陣列。實現變長陣列最簡單的是變長一維陣列,你可以這樣做:

  //檔名:   array01.cpp
  #include<iostream>
  using   namespace   std;

  int   main()
  {
    int   len;
    cin>>len;
    //用指標p指向new動態分配的長度為len*sizeof(int)的記憶體空間
    int   *p=new   int[len];
    ...........
    delete[]   p;
    return   0;
  }

    注意int   *p=new   int[len];這一句,你不能這樣做:

    int   p[len];

    C++編譯器會報錯說len的大小不能確定,因為用這種形式宣告陣列,陣列的大小需要在編譯時確定。而且這樣也不行:

    int   p[]=new   int[len];

    編譯器會說不能把int*型轉化為int[]型,因為用new開闢了一段記憶體空間後會返回這段記憶體的首地址,所以要把這個地址賦給一個指標,所以要用int   *p=new   int[len];

    array01.cpp實現了一個變長的一維陣列,但是要養成一個好習慣,就是注意要登出指標p,使程式釋放用new開闢的記憶體空間。

    當然使用C++標準模版庫(STL)中的vector(向量)也可以實現變長陣列:

 //檔名:   array02.cpp
  #include<iostream>
  #include<vector>
  using   namespace   std;

  int   main()
  {
    int   len;
    cin>>len;
    vector<int>   array(len);//宣告變長陣列

    for(int   i=0;i<len;i++)
    {
      array[i]=i;
      cout<<array[i]<<"\t";
    }
    return   0;
  }

    這裡的變長陣列讓我聯想到了java的java.util包中的vector和C#中的ArrayList,它們也可以在各自的語言中實現變長陣列。不過C++中的vector不能像C#一樣有託管的垃圾回收機制回收被佔用的記憶體空間,但是你可以在使用完vector後呼叫~vector()解構函式釋放記憶體。

    2.變長n維陣列

    變長的n維陣列實現起來有些麻煩,但是在工程與軟體設計應用中常使用的是二維陣列,所以在這裡著重介紹變長的二維陣列,變長的n維陣列可以按照類似的方法實現。首先看一個經典的用C實現變長二維陣列的例子:

 //檔名:   array03.c
  #include     <stdio.h>
  #include     <malloc.h>

  void     main()

  {
                        int     x,y,i,j;
                        float     **a,*b;
                                                printf("請輸入你所求解的線性方程組的行數x:x=");
                        scanf("%d",&x);
                                                printf("請輸入你所求解的線性方程組的列數y:y=");
                        scanf("%d",&y);

                a=(float     **)malloc(sizeof(float     *)     *x);
                b=(float     *)malloc(sizeof(float)     *x);
                        for(i=0;i<x;i++)
                        {
                                                *(a+i)=(float     *)malloc(sizeof(float)     *y);
                        }

  /*讀入資料*/

                        printf("請按行的順序依次輸入係數的值(共%d項):",x*y);
                        for(i=0;i<=x-1;i++)
                                                for(j=0;j<=y-1;j++)
                                                                        scanf("%f",&a[i][j]);
                        printf("請按列的順序依次輸入常數的值(共%d項):",x);
                        for(j=0;j<=x-1;j++)
                                                                        scanf("%f",&b[j]);

                        printf("您輸入方程組的增廣矩陣為:\n");
                        for(i=0;i<=x-1;i++)
                        {
                                                for(j=0;j<=y-1;j++)
                                                                        printf("%.5f         ",a[i][j]);
                                                printf("%.5f         ",b[i]);
                                                printf("\n");
                        }
                        free(b);
                        for(i=0;i<x;i++)
                                                free     (*(a+i));
  }

    那麼用C++怎樣實現呢?在C++中可以通過new和delete運算子動態開闢和釋放空間,其中new與C中malloc函式的功能相似,delete與C中free函式的功能相似。用C++實現變長二維陣列時可以採用兩種方法:雙指標方法和使用STL中vector(向量)的方法。

    首先介紹一下雙指標方法,在這裡雙指標就是指像指標的指標,比如你可以這樣宣告一個數組:

    int   **p   =   new   int*[num1];

    而對每一個*p(一共num1個*p)申請一組記憶體空間:

    for(int   i=0;   i<num1;   ++i)

    p[i]   =   new   int[num2];

    其中,num1是行數,num2是陣列的列數。測試的源程式如下:

  //檔名:   array04.cpp
  #include   <iostream>
  #include   <iomanip>
  using   namespace   std;

  int   main()
  {
    int   num1,//行數
            num2;//列數

    cout<<"Please   enter   the   number   for   row   and   column:   "<<endl;
    cin   >>   num1   >>   num2;

    //為二維陣列開闢空間
    int   **p   =   new   int*[num1];
    for(int   i=0;   i<num1;   ++i)
      p[i]   =   new   int[num2];

    for(int   j=0;j<num1;j++)
    {
      for(int   k=0;k<num2;k++)
      {
        p[j][k]=(j+1)*(k+1);
        cout<<setw(6)<<p[j][k]<<':'<<setw(8)<<&p[j][k];
      }
      cout<<endl;
    }

    //釋放二維陣列佔用的空間
    for(int   m=0;m<num1;m++)
      delete[]   p[m];
    delete[]   p;

    return   0;
  }

    以下是執行結果:

  Please   enter   the   number   for   row   and   column:
  4   5
            1:004915F0           2:004915F4           3:004915F8           4:004915FC           5:00491600
            2:00491180           4:00491184           6:00491188           8:0049118C         10:00491190
            3:00491140           6:00491144           9:00491148         12:0049114C         15:00491150
            4:00491100           8:00491104         12:00491108         16:0049110C         20:00491110
  Press   any   key   to   continue

     程式清單array04.cpp可以顯示分配的記憶體空間單元的地址,大家可以看到,由於陣列空間是動態分配的,陣列行之間的地址空間是不連續的,因為不同行的陣列元素的地址空間是用不同的new來分配的。而每一行之中列之間的地址空間是連續的。

    那麼用vector(向量)怎樣實現二維陣列呢?以下給出源程式:

   //檔名:   array05.cpp
  #include   <iostream>
  #include   <vector>
  #include   <iomanip>
  using   namespace   std;
  int   main()
  {
    int   i,
            j,
            m,   //行數
            n;   //列數

    cout   <<   "input   value   for   m,n:";
    cin>>m>>n;

    //注意下面這一行:vector<int後兩個">"之間要有空格!否則會被認為是過載">>"。
    vector<vector<int>   >   vecInt(m,   vector<int>(n));
    for   (i   =   0;   i   <   m;   i++)
      for   (j   =   0;   j   <   n;   j++)
        vecInt[i][j]   =   i*j;

    for   (i   =   0;   i   <   m;   i++)
    {
      for   (j   =   0;   j   <   n;   j++)
        cout<<setw(5)<<vecInt[i][j]<<":"<<setw(9)<<&vecInt[i][j];
      cout<<endl;
    }
    return   0;
  }

    以下是執行結果:

  input   value   for   m,n:3   4
          0:   00491180         0:   00491184         0:   00491188         0:   0049118C
          0:   00491140         1:   00491144         2:   00491148         3:   0049114C
          0:   00491100         2:   00491104         4:   00491108         6:   0049110C
  Press   any   key   to   continue

    大家可以看到,這裡vector中元素的記憶體的地址分配也有同雙指標實現的二維陣列有同樣的特點。不過用vector的方法比使用雙指標簡單地多,分配記憶體空間時會更安全,陣列初始化程式碼也更簡單,所以本人建議使用STL中的vector來實現變長多維陣列。以下是一個變長三維陣列:)

 //檔名:   array06.cpp
  #include   <iostream>
  #include   <vector>
  #include   <iomanip>
  using   namespace   std;
  int   main()
  {
    int   i,
      j,
      k,
      m,   //一維座標
      n,   //二維座標
      l;   //三維座標

    cout   <<   "input   value   for   m,n,l:";
    cin>>m>>n>>l;
    vector<vector<vector<int>   >   >   vecInt(m,   vector<vector<int>   >(n,   vector<int>(l)));
    for   (i   =   0;   i   <   m;   i++)
      for   (j   =   0;   j   <   n;   j++)
        for(k   =   0;   k   <   l;   k++)
          vecInt[i][j][k]   =   i+j+k;

    for   (i   =   0;   i   <   m;   i++)
    {
      for   (j   =   0;   j   <   n;   j++)
      {
        for(k   =   0;   k<l;   k++)
          cout<<setw(5)<<vecInt[i][j][k]<<":"<<setw(9)<<&vecInt[i][j][k];
        cout<<endl;
      }
      cout<<endl;
    }

    return   0;
  }

    執行結果:
  input   value   for   m,n,l:2   3   4
          0:   00492FE0         1:   00492FE4         2:   00492FE8         3:   00492FEC
          1:   00492FA0         2:   00492FA4         3:   00492FA8         4:   00492FAC
          2:   00492F60         3:   00492F64         4:   00492F68         5:   00492F6C

          1:   00492EC0         2:   00492EC4         3:   00492EC8         4:   00492ECC
          2:   00492E80         3:   00492E84         4:   00492E88         5:   00492E8C
          3:   00492E40         4:   00492E44         5:   00492E48         6:   00492E4C

【責編:ben】