-1

I'm trying to take my 2D array program and just change a class private setting from (UML CODE) -m_array: Array<T> to -m_array : T**. This is a requirement for the Data Structures Class... for one of the assignments

Array<TYPE> m_array;    // m_array : Array<TYPE> 

to

TYPE ** m_array;        // m_array : T** 

Array2D.h

template <class TYPE>
class Array2D
{
public:
    Array2D();
    Array2D(int row, int col);
    Array2D(const Array2D<TYPE> & copy);
    ~Array2D() {}

    const Array2D<TYPE> & operator=(const Array2D<TYPE>& rhs);
    const Row<TYPE> operator[](int index) const;
    Row<TYPE> operator[](int index);
    const int getRow() const { return m_rows; }
    void setRow(int rows);
    const int getColumn() const { return m_cols; }
    void setColumn(int columns);
    TYPE & Select(int row, int col);

private:
    Array<TYPE> m_array;  // This needs to change
    int m_rows;
    int m_cols;

    bool ValidCol(int column) { return (column < m_cols || column >= 0);}
    bool ValidRow(int row) { return (row < m_rows || row >= 0); }
};

If I change the private Array<TYPE> m_array to TYPE ** m_array;, I have issues with some of the Array2D functions. Not sure how to change my code to work with the double pointers.

template<class TYPE>
Array2D<TYPE>::Array2D(int row, int col) : m_rows(row), m_cols(col)
{
    cout << "User specified 2D constructor " << endl;
    cout << "Row = " << row << " and Col = " << col << "... R*C = " << (row * col) << endl << endl;

    if (m_rows < 1 || m_cols < 1)
        throw Exception("Invalid dimensions");
    else
        m_array = Array<TYPE>(m_rows*m_cols);   // <--- Issues
}

I get an Error like

... error C2440: '=': cannot convert from 'Array' to 'int **'

if I leave the example above alone.

Array.h

template <class TYPE>
class Array
{
public:
    Array();
    Array(int length, int beg_index = 0);
    Array(const Array<TYPE>& copy);
    ~Array();

    const Array<TYPE> & operator=(const Array<TYPE>& rhs);    
    TYPE & operator[](int index);
    const TYPE & operator[](int index) const;
    int  getLength() const { return m_length; }
    inline void setLength(int new_length);
    int  getStartIndex() const {return m_start_index; }
    void setStartIndex(const int new_start_index) {m_start_index = new_start_index;}

private:
    bool WithinBounds(const int loc_request) const;
    bool ValidLength(const int requested_length)const;

    TYPE * m_array = 0;
    int m_length;
    int m_start_index;
};

Any suggestions you can give would be appreciated. I never fully understood pointers, but have a basic grasp.

SU3
  • 5,064
  • 3
  • 35
  • 66

2 Answers2

0

The typical way to use pointer to pointer to allocate a matrix would be:

int **M = new int*[numRows];

for (i = 0; i < numRows; i++) {
    M[i] = new int[numCols];
}

You first allocate an array of integer pointers, then allocate an array of integers for each pointer. Then you can do things like:

for (i = 0; i < numRows; i++) {
    for (j = 0; j < numCols; j++ ) {
        M[i][j] = (10 * i) + j;
    }
}

for (i = 0; i < numRows; i++) {
    for (j = 0; j < numCols; j++) {
        std::cout << M[i][j] << " ";
    }
    std::cout << std::endl;
}
Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
  • Typical perhaps, but absolutely horrible. Please don't write more examples doing this. Have a look at https://stackoverflow.com/a/29375830/103167 – Ben Voigt Jan 25 '18 at 23:48
0

If a shallow copy suffices, you can create an array with calloc( sizeof(TYPE*), a.getLength() ); and then initialize each element to &a[i][0] inside a loop. (Or addressof.) If you must make a deep copy, create each row of the matrix with new[] and use memcpy().

Alternatively, you can do everything with std::vector and just call .data() when you need to convert to a C-style pointer and the <algorithm> library to manipulate them.

I'll second the reaction that this is not a good data structure to use when you do get to choose your own.

Davislor
  • 14,674
  • 2
  • 34
  • 49