(原創) 由一維陣列模擬二維陣列(多維陣列) (C/C++)

C/C++的陣列是有名的難用!!沒有『真正』支援多維陣列,陣列傳到參數時還必須寫死(C++若用template可不用寫死),若是動態的多維陣列就更難寫了,C/C++還必須到一定的功力才寫的出來!!既然C/C++骨子是用一維陣列『模擬』多維陣列,那我們就乾脆直接用一維陣列去『處理』多維陣列。

用一維陣列去處理多維陣列有幾個好處:
1.寫法較簡單。
2.陣列傳到函數時,參數不用寫死。

以下我們就實際的看看怎麼寫...

 1 ExpandedBlockStart.gif ContractedBlock.gif /**/ /* 
 2InBlock.gif(C) OOMusou 2007 http://oomusou.cnblogs.com
 3InBlock.gif
 4InBlock.gifFilename    : ArrayOneDimSimMultiDim.cpp
 5InBlock.gifCompiler    : Visual C++ 8.0 / gcc 3.4.2 / ISO C++
 6InBlock.gifDescription : Demo how to use 1 dim array to simulate multi dim array
 7InBlock.gifRelease     : 02/19/2007 1.0
 8ExpandedBlockEnd.gif*/

 9 None.gif
10 None.gif#include  < iostream >
11 None.gif
12 None.gif using   namespace  std;
13 None.gif
14 ExpandedBlockStart.gifContractedBlock.gif void  func1( int  ( * ia)[ 3 ], int  sizex,  int  sizey)  dot.gif {
15InBlock.gif  cout << "By 2 dim array : " << endl;
16ExpandedSubBlockStart.gifContractedSubBlock.gif  for(int y = 0; y != sizey; ++y) dot.gif{
17ExpandedSubBlockStart.gifContractedSubBlock.gif    for(int x = 0; x != sizex; ++x) dot.gif{
18InBlock.gif      // cout << ia[y][x] << endl;
19InBlock.gif      cout << *(*ia + y * sizex + x) << " " ;
20ExpandedSubBlockEnd.gif    }

21InBlock.gif    cout << endl;
22ExpandedSubBlockEnd.gif  }

23ExpandedBlockEnd.gif}

24 None.gif
25 ExpandedBlockStart.gifContractedBlock.gif void  func2( int   * ia,  int  sizex,  int  sizey)  dot.gif {
26InBlock.gif  cout << "By 1 dim array simulate 2 dim array:" << endl;
27ExpandedSubBlockStart.gifContractedSubBlock.gif  for(int y = 0; y != sizey; ++y) dot.gif{
28ExpandedSubBlockStart.gifContractedSubBlock.gif    for(int x = 0; x != sizex; ++x) dot.gif{
29InBlock.gif      cout << *(ia + y * sizex + x) << " ";
30ExpandedSubBlockEnd.gif    }

31InBlock.gif    cout << endl;
32ExpandedSubBlockEnd.gif  }

33ExpandedBlockEnd.gif}

34 None.gif
35 ExpandedBlockStart.gifContractedBlock.gif void  func3( int  ( * ia)[ 2 ][ 3 ],  int  sizex,  int  sizey,  int  sizez)  dot.gif {
36InBlock.gif  cout << "By 3 dim array : " << endl;
37ExpandedSubBlockStart.gifContractedSubBlock.gif  for(int z = 0; z != sizez; ++z) dot.gif{
38ExpandedSubBlockStart.gifContractedSubBlock.gif    for(int y = 0; y != sizey; ++y) dot.gif{
39ExpandedSubBlockStart.gifContractedSubBlock.gif      for(int x = 0; x != sizex; ++x) dot.gif{
40InBlock.gif        // cout << ia[z][y][x] << endl;
41InBlock.gif        cout << *(**ia + z * sizey * sizex + y * sizex + x) << " ";
42ExpandedSubBlockEnd.gif      }

43InBlock.gif      cout << endl;
44ExpandedSubBlockEnd.gif    }

45InBlock.gif    cout << endl;
46ExpandedSubBlockEnd.gif  }

47ExpandedBlockEnd.gif}

48 None.gif
49 ExpandedBlockStart.gifContractedBlock.gif void  func4( int   * ia,  int  sizex,  int  sizey,  int  sizez)  dot.gif {
50InBlock.gif  cout << "By 1 dim array simulate 3 dim array: " << endl;
51ExpandedSubBlockStart.gifContractedSubBlock.gif  for(int z = 0; z != sizez; ++z) dot.gif{
52ExpandedSubBlockStart.gifContractedSubBlock.gif    for(int y = 0; y != sizey; ++y) dot.gif{
53ExpandedSubBlockStart.gifContractedSubBlock.gif      for(int x = 0; x != sizex; ++x) dot.gif{
54InBlock.gif        // cout << ia[z][y][x] << endl;
55InBlock.gif        cout << *(ia + z * sizey * sizex + y * sizex + x) << " ";
56ExpandedSubBlockEnd.gif      }

57InBlock.gif      cout << endl;
58ExpandedSubBlockEnd.gif    }

59InBlock.gif    cout << endl;
60ExpandedSubBlockEnd.gif  }

61ExpandedBlockEnd.gif}

62 None.gif
63 ExpandedBlockStart.gifContractedBlock.gif int  main()  dot.gif {
64InBlock.gif  const int sizex = 3;
65InBlock.gif  const int sizey = 2;
66InBlock.gif  const int sizez = 2;
67InBlock.gif  
68ExpandedSubBlockStart.gifContractedSubBlock.gif  int ia1[][3= dot.gif{dot.gif{123},
69ExpandedSubBlockStart.gifContractedSubBlock.gif                  dot.gif{456}}
;
70InBlock.gif  
71ExpandedSubBlockStart.gifContractedSubBlock.gif  int ia2[] = dot.gif{123456};
72InBlock.gif  
73ExpandedSubBlockStart.gifContractedSubBlock.gif  int ia3[][2][3= dot.gif{dot.gif{dot.gif{123},
74ExpandedSubBlockStart.gifContractedSubBlock.gif                      dot.gif{456}}
,
75ExpandedSubBlockStart.gifContractedSubBlock.gif                     dot.gif{dot.gif{789},
76ExpandedSubBlockStart.gifContractedSubBlock.gif                      dot.gif{10,11,12}}
}
;
77InBlock.gif  
78ExpandedSubBlockStart.gifContractedSubBlock.gif  int ia4[] = dot.gif{123456789101112};
79InBlock.gif                  
80InBlock.gif  func1(ia1, sizex, sizey);
81InBlock.gif  cout << endl;
82InBlock.gif  func2(ia2, sizex, sizey);
83InBlock.gif  cout << endl;
84InBlock.gif  func3(ia3, sizex, sizey, sizez);
85InBlock.gif  cout << endl;
86InBlock.gif  func4(ia4, sizex, sizey, sizez);
87ExpandedBlockEnd.gif}


執行結果

None.gif By  2  dim array :
None.gif
1   2   3
None.gif
4   5   6
None.gif
None.gifBy 
1  dim array simulate  2  dim array:
None.gif
1   2   3
None.gif
4   5   6
None.gif
None.gifBy 
3  dim array :
None.gif
1   2   3
None.gif
4   5   6
None.gif
None.gif
7   8   9
None.gif
10   11   12
None.gif
None.gif
None.gifBy 
1  dim array simulate  3  dim array:
None.gif
1   2   3
None.gif
4   5   6
None.gif
None.gif
7   8   9
None.gif
10   11   12


68行ia1為一個二維陣列,71行ia2則為相同資料的一維陣列,14行的func1處理ia1這個二維陣列,25行的func2則處理ia2這個一維陣列。

14行int (*ia)[3],參數必須寫死,此為C/C++陣列語法的問題,但若用25行的一維陣列,int *ia則不用寫死。

若用二維陣列,最大的好處是可以使用18行subscripting寫法,較為直觀,若用pointer寫法,就必須用19行的寫法,由於2維陣列是array of array,所以需兩個pointer,比較29行一維陣列的寫法,其實幾乎完全一樣,差別只在於一個pointer而已,因為C/C++沒有『直接』支援多維陣列,在記憶體中仍使用一維陣列配置記憶體,所以寫法才會類似,因此雖然用了一維陣列,但寫法卻一樣是兩層迴圈,和二維陣列一樣,若配合其他演算法,並不會覺得特別難用。

73行的ia3為三維陣列,78行的ia4為相同資料的一維陣列,func3和func4則對應處理之。

最後要提醒的是,用一維陣列處理三維陣列的公式如下

陣列ia的x(個數sizex),y(個數sizey),z(個數sizez)
address = ia + z * (sizex * sizey) + y * (sizex) + x

更多維度則類推之。

本文只提到靜態的方式由一維陣列模擬二維陣列,若要用動態的方式由一維陣列模擬二維陣列,請參閱(原創) 如何動態建立一維陣列? (初級) (C/C++)

Conclusion
用一維陣列去模擬多維陣列,寫法一樣,但卻大幅簡化了C/C++的語法,可將重心擺在演算法上,而不用跟C/C++語法搏鬥。

Remark
在撰寫處理陣列的迴圈時,應該先從z,再y,最後才是x,為什麼呢?因為當宣告陣列時,是int ia[sizey][sizex],所以是先y,然後才x。

See Also
(原創) 如何使用function template傳遞array? (C/C++) (template)
(原創) 如何動態建立一維陣列? (C/C++)
(原創) 如何動態建立二維陣列(多維陣列)? (C/C++)
(原創) 如何動態建立二維陣列(多維陣列)? (C/C++)

Reference

多維矩陣轉一維矩陣

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值