#ifndef ARRAY2D_H #define ARRAY2D_H #include #include #include using namespace std; /***************************************************************** * 2D Array Template Class * * Author: Bill McQuain * Modifications: Ben Keller * * Purpose: Implements a 2-dimensional array as a template class. * Manages 1-dimensional array, and maps 2-dimensional coordinates * into 1-dimensional structure using row-major form. * ******************************************************************/ template class Array2D { private: T *data; // pointer for 1D array int nRows; // number of rows in array int nCols; // number of columns int map(int R, int C) const; // convert 2D coordinates to 1D index bool validCoord(int R, int C) const; // range check for 2D coordinates public: Array2D(); // Create empty array Array2D(int R, int C); // Create R*C array Array2D(const Array2D& Source); Array2D& operator=(const Array2D& Source); bool set(int R, int C, T Value); // Assign Value to location (R,C) T get(int R, int C) const; // Get Value from location (R,C) T& operator() (int R, int C); // Get reference for value at location (R,C) ~Array2D(); class InvalidCoord { // Exception class for invalid coordinates public: int row, col; InvalidCoord(int r, int c): row(r), col(c) {} }; }; // Array2D() -- Default Constructor // Creates empty array, number of rows and columns are set to zero // template Array2D::Array2D() : nRows(0), nCols(0), data(NULL) {} // Array2D(R,C) -- Constructor // Creates array with R rows and C columns // If an error occurs in allocating space for the array, created // array is empty. // template Array2D::Array2D(int R, int C) : nRows(R), nCols(C) { data = new T[nRows * nCols]; if (data == NULL) //if new fails to allocate space nRows = nCols = 0; } // operator= -- Assignment operator // Performs deep copy of Source array. // template Array2D& Array2D::operator=(const Array2D& Source) { if (this != &Source) { delete [] data; nRows = Source.nRows; nCols = Source.nCols; data = new T[nRows * nCols]; //copy data from source array for (int idx = 0; idx < nRows * nCols; idx++) { data[idx] = Source.data[idx]; } } return (*this); } // Copy constructor // Performs deep copy of source array // template Array2D::Array2D(const Array2D& a) : nRows(a.nRows), nCols(a.nCols) { nRows = a.nRows; nCols = a.nCols; data = new T[nRows * nCols]; //copy data from source array a for (int idx = 0; idx < nRows * nCols; idx++) { data[idx] = a.data[idx]; } } // set(R,C,Value) // Assign Value to location (R,C) if coordinates are valid // template bool Array2D::set(int R, int C, T Value) { if ( validCoord(R, C) ) { int idx = map(R, C); data[idx] = Value; return true; } return false; } // operator() --- allows object to be used with function notation. // Returns reference to indexed location so that can be used like // array index expression. Throws exception if coordinates are not // valid. // template T& Array2D::operator() (int R, int C) { if ( validCoord(R,C) ) { int idx = map(R,C); return data[idx]; } else throw Array2D::InvalidCoord(R,C); } // get(R,C) // Retrieve value at location (R,C) if coordinates are valid. // Otherwise, throws exception. // template T Array2D::get(int R, int C) const { if ( validCoord(R, C) ) { int idx = map(R, C); return data[idx]; } else throw Array2D::InvalidCoord(R,C); } // map(R,C) // Converts 2D coordinates into 1D index value. // template int Array2D::map(int R, int C) const { return (R * nCols + C); } // validCoord(R,C) // Verifies that coordinates (R,C) are in proper ranges for // the array. // template bool Array2D::validCoord(int R, int C) const { if ( (R < 0) || (R >= nRows) ) return false; if ( (C < 0) || (C >= nCols) ) return false; return true; } // Destructor // // template Array2D::~Array2D() { delete [] data; } #endif ARRAY2D_H