2015-12-14 488 views
2

基本上,我的問題是:我有用戶定義的2D陣列的大小(N,M),然後我聲明:傳遞未知大小的2D陣列的函數C++

INT矩陣[N ] [M];

那麼我就需要這個未初始化的矩陣傳遞給從.csv文件中讀取一些數據,並把它放入矩陣的功能,所以我嘗試:

void readwrite(int &matrix[N][], const int N, const int M){....}; 


int main(){ 
.... 
cin>>N; 
cin>>M; 

int matrix[N][M]; 
readwrite(matrix,N,M); 
}; 

然而,當我編譯它,它給我以下錯誤:「N沒有在此範圍內聲明」。

如何使這項工作的任何想法?

謝謝你們!

+2

題外話:'INT矩陣[N] [M];'具有可變'N'和'M'是不合法的C++。它可以在一些編譯器中進行擴展。謹慎並且不要指望它在移植到不同的編譯器時工作。 – user4581301

+0

也許這會有幫助嗎? http://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new –

回答

0

int &matrix[N][] - N必須是一個編譯時常量,而不僅僅是const而且根本不是一個參數。並且對數組的引用聲明如下:int (&matrix)[size]

嘗試傳遞int **matrix,並且還需要更改創建此數組的方式。 Variable lenght arrays are not supported in C++,您需要動態分配內存。或者說,如果您知道編譯時的大小,請堅持使用std::vector,std::array

+0

你試過編譯過嗎? – juanchopanza

+0

int&matrix [N] []'並不意味着一個建議。 – LogicStuff

+0

但是你的主導語句暗示,如果'N'是一個編譯時常量,這就是確定的,這就是我問的原因。 – juanchopanza

0

什麼OP正在嘗試是如此令人討厭的難以得到正確的做法,並且與成本相比,拉動它的好處是微不足道的......好吧,我會引用經典。

The only winning move is not to play.

-Joshua,戰爭遊戲

你不能安全地通過在C++中動態分配二維數組到一個函數,因爲你總是要在編譯時知道至少有一個尺寸。

我可以指向Passing a 2D array to a C++ function,因爲這看起來像一個很好的重複。我不會因爲它指的是靜態分配的數組。

你可以玩愚蠢的鑄造遊戲來強制數組進入函數,然後將其重新投射到裏面。我不會解釋如何做到這一點,因爲它是史詩級的愚蠢,應該是一個射擊罪。

您可以將指針傳遞給指針int **,但構造和銷燬邏輯是一個奇怪的集合new和循環。此外,最終結果會散佈RAM周圍的已分配內存,削弱處理器在預測和緩存方面的嘗試。在現代處理器上,如果你無法預測和緩存,你會拋棄CPU的大部分性能。

你想要做的是保持一維。一維數組很容易通過。索引算法非常簡單,易於預測。這都是一個內存塊,所以緩存命中更有可能不會。

製作一維數組很簡單:不要。改爲使用std::vector

std::vector<int> arr(rows*columns); 

如果您必須因爲賦值規範說「無向量!」那麼你卡住了。

int * arr = new int[rows*columns]; 

注意我使用rowscolumnsMN。當遇到MN這是哪個?誰知道,誰在乎,爲什麼這樣對自己首先呢?給你的變量提供一個好的描述性的名字,並且在稍後調試時能夠節省讀取代碼的時間。

使用的膽與陣列和矢量相同:

int test = arr[row * columns + column]; 

將在[row][column]恢復在二維空間中的元件。我不應該解釋這些變量的含義。死亡至MN

定義函數是:

void function (std::vector<int> & arr, size_t rows, size_t columns) 

或(呸)

void function (int * arr, size_t rows, size_t columns) 

注意rowscolumnssize_t類型。 size_t是無符號數(負數組大小不是你想要的,所以爲什麼允許它?),並且它保證足夠大以保存可以使用的最大可能數組索引。換句話說,它比int更合適。但爲什麼到處通過rowscolumns?在這一點上做的聰明的事情是圍繞數組及其控制變量進行封裝,然後使用幾個函數來使事情更易於使用。

template<class TYPE> 
class Matrix 
{ 
private: 
    size_t rows, columns; 
    std::vector<TYPE> matrix; 
public: 
    // no default constructor. Matrix is BORN ready. 

    Matrix(size_t numrows, size_t numcols): 
     rows(numrows), columns(numcols), matrix(rows * columns) 
    { 
    } 
// vector handles the Rule of Three for you. Don't need copy and move constructors 
// a destructor or assignment and move operators 

    // element accessor function 
    TYPE & operator()(size_t row, size_t column) 
    { 
     // check bounds here 
     return matrix[row * columns + column]; 
    } 

    // constant element accessor function 
    TYPE operator()(size_t row, size_t column) const 
    { 
     // check bounds here 
     return matrix[row * columns + column]; 
    } 

    // stupid little getter functions in case you need to know how big the matrix is 
    size_t getRows() const 
    { 
     return rows; 
    } 
    size_t getColumns() const 
    { 
     return columns; 
    } 

    // and a handy-dandy stream output function 
    friend std::ostream & operator<<(std::ostream & out, const Matrix & in) 
    { 
     for (int i = 0; i < in.getRows(); i++) 
     { 
      for (int j = 0; j < in.getColumns(); j++) 
      { 
       out << in(i,j) << ' '; 
      } 
      out << '\n'; 
     } 

     return out; 
    } 

}; 

粗糙的陣列版本將不得不看起來像只是爲了顯示允許向量來做它的工作的好處。未經測試。可能包含咯咯聲。重點在於更多的代碼和更多的錯誤空間。

template<class TYPE> 
class ArrayMatrix 
{ 
private: 
    size_t rows, columns; 
    TYPE * matrix; 
public: 
    ArrayMatrix(size_t numrows, size_t numcols): 
     rows(numrows), columns(numcols), matrix(new TYPE[rows * columns]) 
    { 
    } 

    // Array version needs the copy and move constructors to deal with that damn pointer 
    ArrayMatrix(const ArrayMatrix & source): 
     rows(source.rows), columns(source.columns), matrix(new TYPE[rows * columns]) 
    { 
     for (size_t i = 0; i < rows * columns; i++) 
     { 
      matrix[i] = source.matrix[i]; 
     } 
    } 

    ArrayMatrix(ArrayMatrix && source): 
     rows(source.rows), columns(source.columns), matrix(source.matrix) 
    { 
     source.rows = 0; 
     source.columns = 0; 
     source.matrix = nullptr; 
    } 

    // and it also needs a destructor 
    ~ArrayMatrix() 
    { 
     delete[] matrix; 
    } 

    TYPE & operator()(size_t row, size_t column) 
    { 
     // check bounds here 
     return matrix[row * columns + column]; 
    } 

    TYPE operator()(size_t row, size_t column) const 
    { 
     // check bounds here 
     return matrix[row * columns + column]; 
    } 

    // and also needs assignment and move operator 
    ArrayMatrix<TYPE> & operator=(const ArrayMatrix &source) 
    { 
     ArrayMatrix temp(source); 
     swap(*this, temp); // copy and swap idiom. Read link below. 
     // not following it exactly because operator=(ArrayMatrix source) 
     // collides with operator=(ArrayMatrix && source) of move operator 
     return *this; 
    } 

    ArrayMatrix<TYPE> & operator=(ArrayMatrix && source) 
    { 
     delete[] matrix; 
     rows = source.rows; 
     columns = source.columns; 
     matrix = source.matrix; 

     source.rows = 0; 
     source.columns = 0; 
     source.matrix = nullptr; 

     return *this; 
    } 

    size_t getRows() const 
    { 
     return rows; 
    } 
    size_t getColumns() const 
    { 
     return columns; 
    } 
    friend std::ostream & operator<<(std::ostream & out, const ArrayMatrix & in) 
    { 
     for (int i = 0; i < in.getRows(); i++) 
     { 
      for (int j = 0; j < in.getColumns(); j++) 
      { 
       out << in(i,j) << ' '; 
      } 
      out << std::endl; 
     } 

     return out; 
    } 

    //helper for swap. 
    friend void swap(ArrayMatrix& first, ArrayMatrix& second) 
    { 
     std::swap(first.rows, second.rows); 
     std::swap(first.columns, second.columns); 
     std::swap(first.matrix, second.matrix); 
    } 

}; 

創建,其中之一是

Matrix<int> arr(rows, columns); 

現在通過陣列周圍是

void func(Matrix & arr); 

使用數組是

int test = arr(row, column); 

所有索引數學是隱藏從視線。

其它參考文獻:

What is the copy-and-swap idiom?

What is The Rule of Three?