简体   繁体   中英

How to pass two-dimensional array as an argument?

My Matrx class is defined as

class Matrx
{
 double A[50][50];
 int m,n;
public:
 Matrx(void);
 Matrx(int a, int b)
 {
  m=a;
  n=b;
 }
 Matrx operator +(Matrx b);
 Matrx Transpose(Matrx b);
 Matrx operator *(Matrx b);
 CString printMatrx();
 void readMatrx(double a[][]);
 Matrx TransposeMat(Matrx b);
};

void Matrx::readMatrx(double a[][])
{
 for(int i=0;i< m;i++)
  {
   for(int j=0;j< n;j++)
    A[i][j]=a[i][j];
  }
}

The intellisense gives error like the below

1 IntelliSense: an array may not have elements of this type d:\\bmadaptive_dd_v1.02\\matrx.h 17 27 TestServer

Why?

How to pass a two dimensional array as argument of the function?

The problem is that when passing multidimensional arrays as parameters in C++, you must specify the dimension of the outermost array. For example:

void ThisIsIllegal(int arr[][]); // Wrong!
void ThisIsAlsoIllegal(int arr[10][]); // Also wrong
void ThisIsLegal(int arr[][10]); // Okay

If you want to be able to have a function that takes in an array of any size, you can use templates:

template <size_t N, size_t M>
void ThisIsAlsoLegal(int (&arr)[M][N]);

This last version accepts any multidimensional array of the right type, and is probably what you're looking for.

You need to properly learn about arrays and pointers. This includes the lesson "huh! They are not as useful as I thought they were". After you've gotten familiar with how arrays and pointers work exactly you should rethink your design.

For example, in my opinion, the following design has lots of advantages:

#ifndef MATRIX_HPP_INCLUDED
#define MATRIX_HPP_INCLUDED

#include <vector>
#include <algorithm>

class matrix
{
public:
    typedef std::vector<double>::size_type st;
    matrix() : rows_(0), cols_(0) {}
    matrix(int r, int c) : rows_(r), cols_(c), coeffs_(st(r)*c,0.0) {}
    void reset(int r, int c)
    { rows_=r; cols_=c; coeffs_.clear(); coeffs_.resize(st(r)*c,0.0); }
    int rows() const {return rows_;}
    int cols() const {return cols_;}
    double const& operator()(int i, int j) const {return coeffs_[indexof(i,j)];}
    double      & operator()(int i, int j)       {return coeffs_[indexof(i,j)];}
    double const* operator[](int i) const {return &coeffs_[indexof(i,0)];}
    double      * operator[](int i)       {return &coeffs_[indexof(i,0)];}
    void swap(matrix& that)
    {
      std::swap(this->rows_,that.rows_);
      std::swap(this->cols_,that.cols_);
      this->coeffs_.swap(that.coeffs_));
    }
private:
    int rows_, cols_;
    std::vector<double> coeffs_;
    st indexof(int i, int j) const {return st(i)*cols+j;} // row major storage
};

inline void swap(matrix& a, matrix& b) {a.swap(b);}

matrix& operator+=(matrix& lhs, matrix const& rhs);
matrix operator+(matrix const& lhs, matrix const& rhs);
matrix operator*(matrix const& lhs, matrix const& rhs);
inline matrix& operator*=(matrix& lhs, matrix const& rhs)
{ matrix tmp = lhs * rhs; swap(tmp,lhs); return lhs; }
...

#endif

This way you won't waste any space for small matrices, and you can support large matrices. Also, the use of std::vector instead of a pointer member which points to dynamically allocated memory removes the need to define your own copy constructor, assignment operator and destructor.

Of course, you could use boost::multi_array as a matrix replacement but using a custom matrix class allows you to declare overloaded operators in your own namespace which is desirable due to ADL (argument dependent lookup).

You might think that this doesn't really answer your question. In that case, let me stress that I think you don't fully understand how arrays and pointers work / behave. This is something you should look up in a decent C++ book. One could write many pages about this topic. You can't expect to see a short answer explaining all the quirks.

Check out the Definite C++ Book Guide thread.

You need to specify all but the first dimension, eg

void Matrx::readMatrx(double a[][50])

From this you should be able to see that you have a fundamental problem with the way you have implemented your class, but at least you should now be able to get the code to compile.

You can to specify all dimensions or only last dimension to pass an array:

void Matrx::readMatrx(double a[][50])
{
 for(int i=0;i< m;i++)
  {
   for(int j=0;j< n;j++)
    A[i][j]=a[i][j];
  }
}

Thanks to all of you people...you were really helping...I have found myself a new definition of the class and the function definition for the matrix that fitted my need. I need you r comment on it...Below is the example of the class declaration..

#include<iostream>
#include"stdafx.h"
using namespace std;  
const int M=100; const int N=100;  
class Matrix  
{  
    double A[M][N];  
    int m,n;  
public:  
    Matrix(void);  
    Matrix(int a, int b)  
    {  
        m=a;  
        n=b;  
        for(int i=0;i<m;i++)  
        {  
            for(int j=0;j<m;j++)  
                A[i][j]=0.0;  
        }  
    }  
    Matrix operator +(Matrix b);  
    Matrix operator -(Matrix b);  
    Matrix operator *(Matrix b);  
    void TransPose(Matrix b);  
    CString printMatrix();  
    void readMatrix(double*);  
};

and then the function implementation

#include "stdafx.h"
#include "Matrix.h"

Matrix::Matrix(void)  
{  
}  

Matrix Matrix::operator *(Matrix b)  
{  
 Matrix c(m,m);  
 if(n!=b.m)  
 {  
    HWND hndOwner(0);   
    MessageBoxW(hndOwner,L"Multiplication not possible row and column does not match",L"Error",NULL);  
    Matrix errMat(1,0);  
    double er[1][1]={0}; errMat.readMatrix((double *)er);  
    return errMat;  
 }  
for(int i=0;i< m;i++)  
{  
for(int k=0;k< m;k++)  
{  
c.A[i][k]=0;  
for(int j=0;j< n;j++)  
{  
c.A[i][k] = c.A[i][k]+(A[i][j] * b.A[j][k]) ;  
}  
}  
}  
return c;  
}  
Matrix Matrix::operator +(Matrix b)  
{  
    Matrix c(m,n);  
    if((n!=b.n)||(m!=b.m))  
 {  
    HWND hndOwner(0);   
    MessageBoxW(hndOwner,L"Addition not possible row and column does not match",L"Error",NULL);  
    Matrix errMat(1,0);  
    double er[1][1]={0}; errMat.readMatrix((double *)er);  
    return errMat;  
 }  
    for(int i=0;i<m;i++)  
        {  
            for(int j=0;j< n;j++)  
                {  
                    c.A[i][j]=0.0;  
                }  
        }  
        for(int i=0;i< m;i++)  
        {  
            for(int j=0;j< n;j++)  
                {  
                    c.A[i][j]=A[i][j]+b.A[i][j];  
                }  
        }  
return c;  
}    
CString Matrix::printMatrix()  
{  
    CString strB(" "),strDisp;  
    for(int iRow=0;iRow<m;iRow++)  
    {  
        for(int iColumn=0;iColumn<n;iColumn++)  
        {  
            strB.Format(L"%lf ",A[iRow][iColumn]);  
            strDisp+=strB;  
        }  
            strDisp+="\r\n";  
    }  
        return strDisp;  
}  
void Matrix::readMatrix(double *ptrarr)  
{  
    for(int i=0;i< m;i++)  
        {  
            for(int j=0;j< n;j++)  
                A[i][j]=*(ptrarr+i*n+j);  
        }  
}  
void Matrix::TransPose(Matrix b)  
{  
    for(int i=0;i<b.n;i++)  
    {  
        for(int j=0;j<b.m;j++)  
            A[i][j]=b.A[j][i];  
    }  
}   

The simple codes in the above are working well till now...if you have any suggestion for the improvement please suggest..

You're lucky, then because:

for(int j=0;j<m;j++)
    A[i][j]=0.0;

should probably be:

for(int j=0;j<**n**;j++)
    A[i][j]=0.0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM