2012-06-15 109 views
1

我有固定的寬度座標系作爲陣列

#define gridSize 101 
int _map[gridSize][gridSize]; 

由於我得到的座標系爲一定值的xy座標範圍從-50到50我想打電話給我的地圖例如map[0][0]如縱座標的起點指向_map[51][51]。 換句話說,如果我從我的來源獲取XY值,並希望將其添加到我的地圖我想打電話給

map[x][y] = value 

什麼實際獲得的價值是

_map[51+x][51+y] = value 

所以我不得不創建一個指針,但我不知道如何在多維數組中做到這一點。

#define gridSize 101 // must be an odd number for origin of ordinates in center 
#define gridSizeCenter = (int)(gridSize/2)+1; 
int _map[gridSize][gridSize]; 
int map[gridSize][gridSize]; 
map = &_map[gridSizeCenter][gridSizeCenter]; // wont work 

最後一行代碼錯誤。我該如何做對?

+3

通常的做法是使#define大寫,例如#define GRIZIZE。否則,他們看起來像變量。 – 2012-06-15 09:59:08

回答

1

你不能那樣做。最好的解決方案可能有一組訪問_map變量的函數。例如:

void set_map_value(int map[][gridSize], const int value, const int x, const int y) 
{ 
    map[x + 51][y + 51] = value; 
} 

int get_map_value(int map[][gridSize], const int x, const int y) 
{ 
    return map[x + 51][y + 51]; 
} 

使用函數爲您提供類型檢查,並且還允許您範圍檢查座標。


一個原因就像你想你不能做到這一點,你的編譯錯誤的原因,是該類型不兼容。

另一個原因是你真的不能在數組中有負指數。請記住,整數 -10xffffffff相同,即 4294967295這是一個大數字 的方式超出了數組範圍。

+2

我不相信C標準要求數組/指針下標中的無符號整數,所以我認爲您對有符號值的無符號表示的評論是有誤導性的。 –

0

您可以使用此解決方案

#define gridSize 101 // must be an odd number for origin of ordinates in center 
#define gridSizeCenter gridSize/2 +1 

int main (int argc, char *argv[]) { 

    int _map[gridSize][gridSize]; 
#define MAP(A,B) _map[A+gridSizeCenter][B+gridSizeCenter] 
    MAP(-1,-1) = 5; 
    MAP(0,0) = 6; 
    printf ("MAP(0,0) = %d\r\nMAP(-1,-1) = %d\r\n",MAP(0,0),MAP(-1,-1)); 
    return 0; 
} 
1

是的,你可以!

我不認爲你可以用數組做到這一點,但你可以指針數組元素做。

然而,我不會這樣做,除非我有一個非常好的理由。否定索引的指針不會成爲閱讀你的代碼的人會期望的東西,所以它會很容易被誤操作。爲了清楚起見,使用基於功能的解決方案可能會更好 - 除非它需要非常快。

就這樣,讓我們​​來做吧!

從您的嘗試中,您可能會對數組和指針感到困惑。請記住,他們are not the same thing

現在,C不妨礙您使用負指數,which can make sense when you're using a pointer。所以,你可以這樣做:

int a[5]; 
int *b = a + 2; // or &a[2] 

b[-2] // is a[0] 
b[-1] // is a[1] 
b[0] // ia a[2], etc 

所以,我認爲下面的代碼將適合你。

#define GRIDSIZE 101 

..... 


int map_memory[GRIDSIZE][GRIDSIZE]; 
int *map_rows[GRIDSIZE]; 
int **map; 
int i; 

int gridMidPoint = GRIDSIZE/2; 

for(i = 0; i < GRIDSIZE; i++) { 
    map_rows[i] = &(map_memory[i][0]) + gridMidPoint; 
} 
map = map_rows + gridMidPoint; 

然後你可以使用它完全按照你所期望的 - 與101的網格大小:

for(i = -50; i <= 50; i++) { 
    for(j = -50; j <= 50; j++) { 
     map[i][j] = i+j; 
    } 
} 

,或者更一般地說:

for(i = -1 * gridMidPoint; i <= gridMidPoint; i++) { 
    for(j = -1 * gridMidPoint; j <= gridMidPoint; j++) { 
     map[i][j] = i+j; 
    } 
} 

由於創建兩個數組在堆棧上,沒有必要釋放任何東西。


這裏發生了什麼?讓我分解它。首先,我們創建支持數組:

int map_memory[GRIDSIZE][GRIDSIZE]; 

接下來,我們希望,我們要使用是我們行的指針數組:

int *map_rows[GRIDSIZE]; 

我們需要這些是指針,因爲他們將指向我們剛剛創建的二維數組中的數組中間。

int gridMidPoint = GRIDSIZE/2; 

這裏我們計算中點。我假設你想在零的每一邊有相同數量的數組元素 - 所以你不需要你的例子中的+1。

for(i = 0; i < GRIDSIZE; i++) { 
    map_rows[i] = &(map_memory[i][0]) + gridMidPoint; 
} 

該代碼遍歷我們行數組中的每個元素,並將該行設置爲指向二維數組中的相關行的中間。你也可以寫:

map_rows[i] = &map_memory[i][gridMidPoint]; 

但是我個人認爲,隨着superflous支架和另外的版本更加清晰易讀。我認爲如果你用指針做了不尋常的事情,你應該明確地說明下一個閱讀代碼的人會發生什麼。

最後,我們需要我們的map指針指向行的中間:

map = map_rows + gridMidPoint; 

,我們就大功告成了!


記住二維陣列實際上是連續的存儲器的一個塊。這意味着map[0][gridMidPoint+1]與​​位置相同。這實際上與普通的二維數組沒有什麼不同,但是它在調試時需要注意。