在C++中實現變長陣列 (轉)

amyz發表於2007-08-17
在C++中實現變長陣列 (轉)[@more@]

在C++中實現變長陣列


1.變長一維陣列

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

//名: array01.cpp
#include
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
#include
using namespace std;

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

 for(int i=0;i {
 array[i]=i;
 cout< }
 return 0;
}

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

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

//檔名: array03.c
#include   
#include   
 
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  { 
  *(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("您輸入方程組的增廣矩陣為: "); 
  for(i=0;i<=x-1;i++) 
  { 
  for(j=0;j<=y-1;j++) 
  printf("%.5f  ",a[i][j]); 
  printf("%.5f  ",b[i]); 
  printf(" "); 
  } 
  free(b); 
  for(i=0;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 p[i] = new int[num2];
其中,num1是行數,num2是陣列的列數。測試的源程式如下:

//檔名: array04.cpp
#include
#include
using namespace std;

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

 cout< cin >> num1 >> num2;

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

 for(int j=0;j {
 for(int k=0;k {
 p[j][k]=(j+1)*(k+1);
 cout< }
 cout< }

 //釋放二維陣列佔用的空間
 for(int m=0;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
#include
#include
using namespace std;
int main()
{
 int i,
  j,
  m, //行數
  n; //列數

 cout << "input value for m,n:";
 cin>>m>>n;
 
 //注意下面這一行:vector"之間要有空格!否則會被認為是過載">>"。
 vector > vecInt(m, vector(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< cout< }

 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
#include
#include
using namespace std;
int main()
{
 int i,
 j,
 k,
 m, //一維座標
 n, //二維座標
 l; //三維座標
 

 cout << "input value for m,n,l:";
 cin>>m>>n>>l;
 vector > > vecInt(m, vector >(n, vector(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 cout< cout< }
 cout< }

 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

Press any key to continue

按照相似的方法,你也可以用vector實現四維、五維,乃至n維的變長陣列,不過直接使用指標實現n維陣列的話會讓你的腦袋變大的:)

(本文有程式均在VC6中編譯執行透過)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-963086/,如需轉載,請註明出處,否則將追究法律責任。

相關文章