Re: CArray
"Giovanni Dicanio" <giovanni.dicanio@invalid.it> ha scritto nel messaggio
news:efai7qvHIHA.5208@TK2MSFTNGP04.phx.gbl...
or better, I would implement the 2D matrix using a single array (1D), but
I would define a pair of methods like Get and Set, which take in input two
integers (row and column) and access in read/write the given string
element.
[...]
This is a code I developed, which needs more testing, but seems to work...
The class is called Matrix2D, and in main() function it is shown how to use
it.
<code>
//////////////////////////////////////////////////////////////////////////
// MatrixTest.cpp
//////////////////////////////////////////////////////////////////////////
#include <atlbase.h>
#include <atlstr.h>
//////////////////////////////////////////////////////////////////////////
#include <vector> // Matrix uses vector for its internal
representation
// =======================================================================
// A class to represent a 2D matrix of a generic type.
// By Giovanni Dicanio
// =======================================================================
template <typename T>
class Matrix2D
{
public:
//
// CONSTRUCTION
//
// Builds an empty matrix
Matrix2D()
: m_rowCount( 0 ), m_columnCount( 0 ), m_empty( true )
{
return;
}
// Builds a matrix with given number of rows and columns
explicit Matrix2D( int rows, int columns )
: m_rowCount( 0 ), m_columnCount( 0 ), m_empty( true )
{
// Check input parameters
ATLASSERT( rows > 0 && columns > 0 );
if ( rows <= 0 || columns <= 0 )
throw std::invalid_argument(
"Rows and columns must be positive numbers in Matrix2D
constructor.");
// Set proper matrix size
Resize( rows, columns );
}
//
// PROPERTIES
//
// Returns number of rows
int Rows() const
{
ATLASSERT( m_rowCount >= 0 );
return m_rowCount;
}
// Returns number of columns
int Columns () const
{
ATLASSERT( m_columnCount >= 0 );
return m_columnCount;
}
// Is the matrix empty?
bool IsEmpty() const
{
return m_empty;
}
//
// OPERATIONS
//
// Sets to an empty matrix
void Clear()
{
if ( ! m_empty )
{
// Clear
m_rowCount = 0;
m_columnCount = 0;
m_data.clear();
m_empty = true;
}
}
// Changes matrix size.
// (Current matrix data is lost.)
void Resize( int rows, int columns )
{
// Check input parameters
ATLASSERT( rows > 0 && columns > 0 );
if ( rows <= 0 || columns <= 0 )
throw std::invalid_argument(
"Rows and columns must be positive numbers in Matrix2D
constructor.");
// Check if resize is actually needed
if ( rows != m_rowCount && columns != m_columnCount )
{
// Need resize
m_rowCount = rows;
m_columnCount = columns;
m_data.resize( rows * columns );
}
// Update empty flag: the matrix is no more empty
m_empty = false;
}
// Accesses element at index (row, column) for reading only.
// Row and column indexes are 0-based.
const T & At( int row, int col ) const
{
// Check index
ATLASSERT( IsValidIndex( row, col ) );
if ( ! IsValidIndex( row, col ) )
throw std::out_of_range( "Matrix Index is out of range." );
// Access vector data
return m_data[ GetIndex( row, col ) ];
}
// Accesses element at index (row, column) for reading and writing.
// Row and column indexes are 0-based.
T & At( int row, int col )
{
// Check index
ATLASSERT( IsValidIndex( row, col ) );
if ( ! IsValidIndex( row, col ) )
throw std::out_of_range( "Matrix Index is out of range." );
// Access vector data
return m_data[ GetIndex( row, col ) ];
}
// The type stored in the matrix.
typedef T Type;
//
// IMPLEMENTATION
//
private:
//
// DATA MEMBERS
//
// We use std::vector for matrix implementation
typedef std::vector< T > ArrayT;
// Store matrix data into 1D array
ArrayT m_data;
// Is matrix empty?
bool m_empty;
// Number of rows
int m_rowCount;
// Number of columns
int m_columnCount;
//
// HELPERS
//
// Is the input coordinate valid?
bool IsValidIndex( int row, int col ) const
{
// An empty matrix has no valid index
if ( m_empty )
return false;
// Row and column indexes are 0-based
if ( row >= 0 && row < m_rowCount &&
col >= 0 && col < m_columnCount )
{
return true;
}
// Index out of bounds
return false;
}
// Given a 2D index, convert it into 1D vector index
int GetIndex( int row, int col ) const
{
ATLASSERT( ! m_empty );
ATLASSERT( IsValidIndex( row, col ) );
// Elements are stored row-wise
return ( row * m_columnCount + col );
}
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------
// TEST
// -----------------------------------------------------------------------
int main(int argc, char * argv[])
{
//
// A 2D matrix of strings
//
Matrix2D< CString > strings;
ATLASSERT( strings.IsEmpty() );
// *** Test bounds-checking ***
//strings.At( 2, 3 ) = _T("BAD");
//
// Create 3 x 2 matrix
//
const int rowCount = 3;
const int columnCount = 2;
strings.Resize( rowCount, columnCount );
ATLASSERT( ! strings.IsEmpty() );
ATLASSERT( strings.Rows() == rowCount );
ATLASSERT( strings.Columns() == columnCount );
//
// Write some strings...
//
int row, col;
for ( row = 0; row < rowCount; row++ )
{
for ( col = 0; col < columnCount; col++ )
{
CString s;
s.Format( _T("[R=%d, C=%d]"), row, col );
strings.At( row, col ) = s;
}
}
//
// Show matrix strings
//
CString output;
for ( row = 0; row < rowCount; row++ )
{
for ( col = 0; col < columnCount; col++ )
{
output += strings.At( row, col );
output += _T(" ; ");
}
output += _T("\n");
}
::MessageBox( NULL, output, _T("*** Testing Matrix ***"), MB_OK );
return 0;
}
</code>
Giovanni