2009-10-18 58 views
12

我有一個程序,如下所示:轉換多維數組的指針在C++

double[4][4] startMatrix; 
double[4][4] inverseMatrix; 
initialize(startMatrix) //this puts the information I want in startMatrix 

我現在要計算startMatrix的倒數,放入inverseMatrix。我有這個目的,其原型庫函數如下:

void MatrixInversion(double** A, int order, double** B) 

,需要一個取反,並把它放在B.的問題是,我需要知道如何轉換的雙重[4] [ 4]變成雙**來賦予該功能。我試過這樣做的「明顯方式」:

MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix)) 

但這似乎並不奏效。這實際上是正確的做法嗎?

+0

&startMatrix,4,&inverseMatrix – 2009-10-18 05:37:13

+1

爲什麼不製作一個矩陣類,而是用C方法來做事? (將對象傳遞給函數,而不是調用對象的方法) – GManNickG 2009-10-18 05:40:33

+2

@GMan:由於OP說函數是「庫函數」,他很可能沒有自由改變接口。上課或沒有課,在某些時候,他必須得到適當的「雙**」才能傳遞給該函數。 – AnT 2009-10-18 06:03:40

回答

17

不,沒有正確的方法來做具體的事情。 A double[4][4]數組不能轉換爲double **指針。這是實現二維數組的兩種不兼容的方式。有些東西需要改變:函數的接口或者作爲參數傳遞的數組結構。

做後者的最簡單的方法,即讓現有的double[4][4]陣列與功能兼容,是創建double *[4]類型的臨時「指數」陣列指向每一行的開始在每個矩陣

double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] }; 
double *inverseRows[4] = { /* same thing here */ }; 

,並通過這些「指標」數組來代替

MatrixInversion(startRows, 4, inverseRows); 

一旦函數後工作,你可以忘掉startRowsinverseRows陣列,因爲其結果將是PL正確地讀入您的原始inverseMatrix陣列。

1

二維數組不是指針或類似的指針。 startMatrix的正確類型是double (*)[4]。對於您的功能,簽名應該是這樣的:

MatrixInversion(double (*A)[4], int order, double (*B)[4]); 
+1

該函數顯然適用於任何大小的矩形(順序)。僅限於4x4矩陣是難以接受的。此外,現在沒有必要通過'訂單'。 – AnT 2009-10-18 05:44:34

+0

@AndreyT,我只是向他/她展示瞭如何去做。如果我想成爲一般人,我可以向他展示如何創建一個代表矩陣的類。 – leiz 2009-10-18 05:54:33

+0

在*正方形*矩陣中,行數與列數相同。您將列計數硬編碼爲4.現在沒有必要再通過行計數 - 它也必須是4並且只能是4. – AnT 2009-10-18 05:57:09

-1

問題是二維數組與指針數組不一樣。一個二維數組將一行一行地存儲元素—因此,當您傳遞這樣一個數組時,只會給出一個指向開始的指針。接收函數可以計算出如何查找數組的任何元素,但只有在知道每行的長度爲的情況下才可以使用

因此,您的接收功能應聲明爲void MatrixInversion(double A[4][], int order, double B[4][])

+1

如果您知道陣列的大小,並知道它是如何填充的,您可以將它作爲&A傳遞,但您有很多事項需要提前知道,但可以這樣做。 – 2009-10-18 05:46:56

+0

這不是一個正確的聲明。在數組參數聲明中只能刪除第一個大小。此外,固定矩陣的大小會殺死函數的預期可聯繫性(即處理任何大小矩陣的能力)。 – AnT 2009-10-18 05:49:06

+0

@詹姆斯布萊克:確實如此。如果我們要修正方矩陣的大小,聲明參數的正確方法將是double(&A)[4] [4]',而不是'double A [] [4]'。至少它會保留完整的數組類型,而不是將其衰減到'double(*)[4]'。 – AnT 2009-10-18 06:07:06

2

由於您使用的是C++,正確的做法是使用自定義類和一些模板。下面的例子很粗糙,但它得到了基本點。

#include <iostream> 

using namespace std; 

template <int matrix_size> 
class SquareMatrix 
{ 
    public: 
     int size(void) { return matrix_size; } 
     double array[matrix_size][matrix_size]; 
     void copyInverse(const SquareMatrix<matrix_size> & src); 
     void print(void); 
}; 

template <int matrix_size> 
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src) 
{ 
    int inv_x; 
    int inv_y; 

    for (int x = 0; x < matrix_size; x++) 
    { 
     inv_x = matrix_size - 1 - x; 
     for (int y = 0; y < matrix_size; y++) 
     { 
      inv_y = matrix_size - 1 - y; 
      array[x][y] = src.array[inv_x][inv_y]; 
     } 
    } 
} 

template <int matrix_size> 
void SquareMatrix<matrix_size>::print(void) 
{ 
    for (int y = 0; y < 4; y++) 
    { 
     for (int x = 0; x < 4; x++) 
     { 
      cout << array[x][y] << " "; 
     } 
     cout << endl; 
    } 
} 

template <int matrix_size> 
void Initialize(SquareMatrix<matrix_size> & matrix); 

int main(int argc, char * argList[]) 
{ 
    SquareMatrix<4> startMatrix; 
    SquareMatrix<4> inverseMatrix; 

    Initialize(startMatrix); 

    inverseMatrix.copyInverse(startMatrix); 

    cout << "Start:" << endl; 
    startMatrix.print(); 

    cout << "Inverse:" << endl; 
    inverseMatrix.print(); 

    return 0; 
} 

template <int matrix_size> 
void Initialize(SquareMatrix<matrix_size> & matrix) 
{ 
    for (int x = 0; x < matrix_size; x++) 
    { 
     for (int y = 0; y < matrix_size; y++) 
     { 
      matrix.array[x][y] = (x+1)*10+(y+1); 
     } 
    } 
} 
+0

我喜歡你的想法,正確的C++方式。不管作品與否都是一個很好的例子。 – Test 2009-10-18 06:51:44

+0

也很好採取模板類型T,這是元素將是。並可能使尺寸無符號,因爲負尺寸沒有意義。 – GManNickG 2009-10-18 07:03:03

+0

由於代碼將爲每個特定大小重新實例化,但是實現相對較大的操作(其反轉,BTW,而不是轉置)作爲通過矩陣大小參數化的模板函數可能導致代碼膨脹。處理這個問題的正確方法是通過一個以運行時間大小爲參數的函數實現大部分功能(如原始問題),然後在該函數之上構建一個「精簡」模板。但是這使我們回到了原來的問題。 – AnT 2009-10-18 07:52:29

-2

通過漂亮的編碼,如果C++:

struct matrix { 
    double m[4][4]; 
}; 

matrix startMatrix; 
matrix inverseMatrix; 

所以接口

void MatrixInversion(matrix &A, int order, matrix &B); 

,並用它

MatrixInversion(startMatrix, 4, inverseMatrix); 

好處

  1. 界面非常簡單明瞭。
  2. 一旦需要在內部修改「m」矩陣,則不需要更新接口。

還是這樣

struct matrix { 
    void Inversion(matrix &inv, int order) {...} 
protected: 
    double m[4][4]; 
}; 

matrix startMatrix; 
matrix inverseMatrix; 
... 

C中的醜陋的方式

void MatrixInversion(void *A, int order, void *B); 
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix); 

編輯:爲MatrixInversion參考代碼不會崩潰:

void MatrixInversion(void *A, int order, void *B) 
{ 
    double _a[4][4]; 
    double _b[4][4]; 

    memcpy(_a, A, sizeof _a); 
    memcpy(_b, B, sizeof _b); 
    // processing data here 

    // copy back after done 
    memcpy(B, _b, sizeof _b); 
} 
+0

與其他一些響應相同的設計錯誤...您在矩陣類型中對固定矩陣大小進行了硬編碼。如果你需要5x5矩陣,你會怎麼做? 6x6的?當4已經被硬編碼爲矩陣類型時,傳遞4的意義是什麼? – AnT 2009-10-18 06:19:58

+0

你的「在C中醜陋的方式」只會使程序崩潰。 OP已經嘗試過了,如果你注意到了,它不起作用(出於顯而易見的原因)。 – AnT 2009-10-18 06:21:50

+0

重構規則:必要時改進設計。請參閱「福利」部分。 「4」是一個具體的例子,也就是一個整數,它的值是4. – Test 2009-10-18 06:23:35

4

對於給定的原因,二維數組(一個連續的內存塊)和一個數組指針(不是連續的)是非常不同的東西,你不能將一個二維數組傳遞給一個使用指針指針的函數。

你可以做的一件事:模板。使第二個維度的大小成爲模板參數。

#include <iostream> 

template <unsigned N> 
void print(double a[][N], unsigned order) 
{ 
    for (unsigned y = 0; y < order; ++y) { 
     for (unsigned x = 0; x < N; ++x) { 
      std::cout << a[y][x] << ' '; 
     } 
     std::cout << '\n'; 
    } 
} 

int main() 
{ 
    double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}}; 
    print(arr, 3); 
} 

另一個,有點笨拙的方式可能是使函數接受一個指針指向一個一維陣列,並且寬度和高度作爲參數,並計算索引成二維表示自己。

#include <iostream> 

void print(double *a, unsigned height, unsigned width) 
{ 
    for (unsigned y = 0; y < height; ++y) { 
     for (unsigned x = 0; x < width; ++x) { 
      std::cout << a[y * width + x] << ' '; 
     } 
     std::cout << '\n'; 
    } 
} 

int main() 
{ 
    double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}}; 
    print(&arr[0][0], 3, 3); 
} 

當然,矩陣是值得它自己的一類的東西(但如果需要編寫幫助函數,上面的代碼仍然是相關的)。

0

有出自bobobobo

威廉·謝里夫(bobobobo)使用該指針指向一個解決方案中使用C版本,我只是想表明bobobobo的答案的C++版本。

int numRows = 16 ; 
int numCols = 5 ; 
int **a ; 

a = new int*[ numRows* sizeof(int*) ]; 
for(int row = 0 ; row < numRows ; row++) 
{ 
    a[row] = new int[ numCols*sizeof(int) ]; 
} 

其餘代碼與bobobobo相同。