What Is the Matrix?

Environment: Visual Studio, All Windows platforms

The Matrix, in its simplest form, simplifies working with arrays. This is the first of several articles that explains how to use the different features of the Matrix. In this article, I will explain the most basic features.

The Matrix can be downloaded from CodeGuru, along with a brief overview of what it does.

The following code shows how to create a basic, two-dimensional array

CMatrix<int> matrix ;
matrix.cell(0,0)=100 ;
matrix.cell(1,0)=200;
matrix.cell(0,1)=300;
matrix.cell(1,1)=400;

You now have a matrix that looks like this:

100 200
300 400

The Matrix is now a two-dimensional array that contains four cells. The following code shows how to retrieve the values:

int n1=m.cell(0,0)    //n1 contains 100;
int n2=m.cell(1,0)    //n2 contains 200;
int n3=m.cell(0,1)    //n3 contains 300;
int n4=m.cell(1,1)    //n4 contains 400;

The orientation of the matrix is from the top left and indexed by X,Y; so, to get the contents of the tenth cell across and the 5th cell down, you would use cell(10,5).

Pretty simple stuff and not much reason to start using the Matrix. Hopefully, what follows will explain how you can save a lot of coding by using the Matrix.

Templates

The matrix is a template utility class. The code below demonstrates its use with strings:

CMatrix<CString> matrix ;
matrix.cell(0,0)="string@0,0" ;
matrix.cell(1,0)="string@1,0";
matrix.cell(0,1)="string@0,1";
matrix.cell(1,1)="string@1,1";

CString s1=m.cell(0,0);   s1=string@0,0
CString s3=m.cell(0,1);   s3=string@0,1
//and so on...

The MATRIX and COM

Because matrix is a template utility class, you can store almost anything in the Matrix, including VARIANTs. Those of you who've created SAFEARRAYs know how tedious they are to create and manipulate. This is probably the benefit of using the Matrix because it takes away all of the complications of creating arrays for marshalling with COM. The code below represents a simple, two-dimensional array using the COM API:

SAFEARRAYBOUND saBound[ 2 ] ;
saBound[ 0 ].cElements = 2 ; saBound[ 0 ].lLbound = 0 ;
saBound[ 1 ].cElements = 2 ; saBound[ 1 ].lLbound = 0 ;
SAFEARRAY FAR* psa = SafeArrayCreate( VT_VARIANT, 2 , saBound ) ;

_variant_t v1=1L, v2=2L, v3=3L, v4=4L;

long idx[ 2 ] ;
idx[ 0 ] = 0 ; idx[ 1 ] = 0;
HRESULT hr = SafeArrayPutElement( psa , idx , &v1 ) ;

idx[ 0 ] = 0 ; idx[ 1 ] = 1;
hr = SafeArrayPutElement( psa , idx , &v2 ) ;

idx[ 0 ] = 1 ; idx[ 1 ] = 0;
hr = SafeArrayPutElement( psa , idx , &v3 ) ;

idx[ 0 ] = 1 ; idx[ 1 ] = 1;
hr = SafeArrayPutElement( psa , idx , &v4 ) ;

VARIANT v ; VariantInit(&v);
v.parray = psa ; v.vt = VT_ARRAY | VT_VARIANT ;

// now get the stuff back out
long xLow, xHigh, yLow, yHigh, ix[2] ;
xLow = xHigh = yLow = yHigh = ix[0] = ix[1] = 0 ;
SafeArrayGetUBound ( v.parray, 1, &xHigh ) ; 
SafeArrayGetLBound (v.parray , 1 , &xLow ) ;

SafeArrayGetUBound ( v.parray, 2, &yHigh ) ; 
SafeArrayGetLBound( v.parray , 2 , &yLow ) ;

_variant_t vcell1, vcell2,vcell3, vcell4 ;

ix[0] = 0 ; ix[1] = 0 ;
hr = SafeArrayGetElement( v.parray, ix, &vcell1 ) ;

ix[0] = 0 ; ix[1] = 1 ;
hr = SafeArrayGetElement( v.parray, ix, &vcell2 ) ;

ix[0] = 1 ; ix[1] = 0 ;
hr = SafeArrayGetElement( v.parray, ix, &vcell3 ) ;

ix[0] = 1 ; ix[1] = 1 ;
hr = SafeArrayGetElement( v.parray, ix, &vcell4 ) ;

cout <<
"vcell1=" << vcell1.iVal << "\n" <<
"vcell2=" << vcell2.iVal << "\n" <<
"vcell3=" << vcell3.iVal << "\n" <<
"vcell4=" << vcell4.iVal << "\n" <<

"press enter to continue";

cin.get();

As you can see, this code is quite convoluted. Of course, it could be simplified, but it's convoluted nonetheless. Using the Matrix to achieve the exactly the same result looks like this:

_variant_t v1=1L, v2=2L, v3=3L, v4=4L;

CMatrix<_variant_t> matrix ;
matrix.cell(0,0)=v1 ;
matrix.cell(0,1)=v2 ;
matrix.cell(1,0)=v3;
matrix.cell(1,1)=v4;

VARIANT vIn=matrix;

// now get the stuff back out

_variant_t vcell1, vcell2, vcell3, vcell4;
CMatrix<_variant_t> m ;
m=vIn ;
vcell1=m.cell(0,0);
vcell2=m.cell(0,1);
vcell3=m.cell(1,0);
vcell4=m.cell(1,1);

cout <<
"vcell1=" << vcell1.iVal << "\n" <<
"vcell2=" << vcell2.iVal << "\n" <<
"vcell3=" << vcell3.iVal << "\n" <<
"vcell4=" << vcell4.iVal << "\n" <<

"press enter to continue";

cin.get();

The above example creates a Matrix and then creates a VARIANT SAFEARRAY from the Matrix. The items that are written to the screen are from another Matrix created from the VARIANT SAFEARRAY. To simplify things yet further, the code below does exactly the same thing:

CMatrix<_variant_t> matrix ;
matrix.cell(0,0)=1L ;
matrix.cell(0,1)=2L ;
matrix.cell(1,0)=3L;
matrix.cell(1,1)=4L;

VARIANT vIn=matrix;

// now get the stuff back out
CMatrix<_variant_t> m(vIn) ;
cout <<
"vcell1=" << m.cell(0,0).iVal << "\n" <<
"vcell2=" << m.cell(0,1).iVal << "\n" <<
"vcell3=" << m.cell(1,0).iVal << "\n" <<
"vcell4=" << m.cell(1,1).iVal << "\n" <<

"press enter to continue";

cin.get();

Conclusion

Hopefully, this article has shown you how simple it is to use the Matrix class and how much coding it takes away when dealing with arrays. In the next article, I will discuss how to use the Matrix class to marshal SAFEARRAYS in COM.

Downloads

Download demo project - 180 Kb


Comments

  • derive from std::?

    Posted by Legacy on 05/16/2003 12:00am

    Originally posted by: John Torjo

    Why did you derive Matrix from std::vector and std::map?
    Especially publically?

    This seems to me a major design flaw.

    someone could do something like:
    CMatrix<_variant_t> matrix;
    // fill it
    std::vector<...> & v = matrix;

    v.clear();

    This would probably crash your stuff.

    Reply
  • test

    Posted by Legacy on 03/04/2003 12:00am

    Originally posted by: Webmaster

    test

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds