C/C++的陣列是有名的難用!!沒有『真正』支援多維陣列,陣列傳到參數時還必須寫死(C++若用template可不用寫死),若是動態的多維陣列就更難寫了,C/C++還必須到一定的功力才寫的出來!!既然C/C++骨子是用一維陣列『模擬』多維陣列,那我們就乾脆直接用一維陣列去『處理』多維陣列。
C/C++的陣列是有名的難用!!沒有『真正』支援多維陣列,陣列傳到參數時還必須寫死(C++若用template可不用寫死),若是動態的多維陣列就更難寫了,C/C++還必須到一定的功力才寫的出來!!既然C/C++骨子是用一維陣列『模擬』多維陣列,那我們就乾脆直接用一維陣列去『處理』多維陣列。
用一維陣列去處理多維陣列有幾個好處:
1.寫法較簡單。
2.陣列傳到函數時,參數不用寫死。
以下我們就實際的看看怎麼寫...
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
2
(C) OOMusou 2007 http://oomusou.cnblogs.com
3![](/Images/OutliningIndicators/InBlock.gif)
4
Filename : ArrayOneDimSimMultiDim.cpp
5
Compiler : Visual C++ 8.0 / gcc 3.4.2 / ISO C++
6
Description : Demo how to use 1 dim array to simulate multi dim array
7
Release : 02/19/2007 1.0
8
*/
9![](/Images/OutliningIndicators/None.gif)
10
#include <iostream>
11![](/Images/OutliningIndicators/None.gif)
12
using namespace std;
13![](/Images/OutliningIndicators/None.gif)
14![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void func1(int (*ia)[3],int sizex, int sizey)
{
15
cout << "By 2 dim array : " << endl;
16![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int y = 0; y != sizey; ++y)
{
17![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int x = 0; x != sizex; ++x)
{
18
// cout << ia[y][x] << endl;
19
cout << *(*ia + y * sizex + x) << " " ;
20
}
21
cout << endl;
22
}
23
}
24![](/Images/OutliningIndicators/None.gif)
25![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void func2(int *ia, int sizex, int sizey)
{
26
cout << "By 1 dim array simulate 2 dim array:" << endl;
27![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int y = 0; y != sizey; ++y)
{
28![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int x = 0; x != sizex; ++x)
{
29
cout << *(ia + y * sizex + x) << " ";
30
}
31
cout << endl;
32
}
33
}
34![](/Images/OutliningIndicators/None.gif)
35![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void func3(int (*ia)[2][3], int sizex, int sizey, int sizez)
{
36
cout << "By 3 dim array : " << endl;
37![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int z = 0; z != sizez; ++z)
{
38![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int y = 0; y != sizey; ++y)
{
39![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int x = 0; x != sizex; ++x)
{
40
// cout << ia[z][y][x] << endl;
41
cout << *(**ia + z * sizey * sizex + y * sizex + x) << " ";
42
}
43
cout << endl;
44
}
45
cout << endl;
46
}
47
}
48![](/Images/OutliningIndicators/None.gif)
49![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void func4(int *ia, int sizex, int sizey, int sizez)
{
50
cout << "By 1 dim array simulate 3 dim array: " << endl;
51![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int z = 0; z != sizez; ++z)
{
52![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int y = 0; y != sizey; ++y)
{
53![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int x = 0; x != sizex; ++x)
{
54
// cout << ia[z][y][x] << endl;
55
cout << *(ia + z * sizey * sizex + y * sizex + x) << " ";
56
}
57
cout << endl;
58
}
59
cout << endl;
60
}
61
}
62![](/Images/OutliningIndicators/None.gif)
63![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
64
const int sizex = 3;
65
const int sizey = 2;
66
const int sizez = 2;
67
68![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
int ia1[][3] =
{
{1, 2, 3},
69![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{4, 5, 6}};
70
71![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
int ia2[] =
{1, 2, 3, 4, 5, 6};
72
73![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
int ia3[][2][3] =
{
{
{1, 2, 3},
74![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{4, 5, 6}},
75![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
{7, 8, 9},
76![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{10,11,12}}};
77
78![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
int ia4[] =
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
79
80
func1(ia1, sizex, sizey);
81
cout << endl;
82
func2(ia2, sizex, sizey);
83
cout << endl;
84
func3(ia3, sizex, sizey, sizez);
85
cout << endl;
86
func4(ia4, sizex, sizey, sizez);
87
}
執行結果
By 2 dim array :
1 2 3
4 5 6
![](/Images/OutliningIndicators/None.gif)
By 1 dim array simulate 2 dim array:
1 2 3
4 5 6
![](/Images/OutliningIndicators/None.gif)
By 3 dim array :
1 2 3
4 5 6
![](/Images/OutliningIndicators/None.gif)
7 8 9
10 11 12
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
By 1 dim array simulate 3 dim array:
1 2 3
4 5 6
![](/Images/OutliningIndicators/None.gif)
7 8 9
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
多維矩陣轉一維矩陣