473,320 Members | 1,810 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

How to define a new class "Matrix" based on "Vector<Vector<T>>"?

5
In order to automatically check if the index of an array declared by vector<T> exceeding its boundary, we define the class "Vector" derived from "vector" and do the operator overloading as shown in Vector.h. And it works well.
However, when we need to use the 2-dimensional array, we need to write more than 5 lines in order to initialize the 2-D array, as shown in main.cpp.

My question is: is there any way to define a new class "Matrix" which enjoys the ability of "Vector" for automatically checking the array boundary. and its declaration and initialization could be as simple as:

Matrix<double> tmp;
tmp.assignName("tmp", 3, 4, 0.00);

-----------------------------------------------------
Many thanks for the helps.

"Vector.h" and "main.cpp" could be seen in tmp.zip.

Best regards,
Herbu.
Attached Files
File Type: zip Vector.zip (1.7 KB, 142 views)
Apr 8 '10 #1

✓ answered by akdemirc

adding two similar member functions to matrix class as you have in vector seems to do what you want:

declaration:
Expand|Select|Wrap|Line Numbers
  1.     Vector<T> &operator[] (int);
  2.     const Vector<T> &operator[] (int) const;

definition:

Expand|Select|Wrap|Line Numbers
  1. template <class T>
  2. Vector<T> &Matrix<T>::operator[] (int idx) 
  3. {
  4.     if(idx < 0 || idx >= bitErrCntCI.size()) {
  5.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, bitErrCntCI.size()-1);
  6.         getchar();
  7.         exit(1);
  8.     }
  9.     // printf("size = %d \n", size());
  10.     return bitErrCntCI.at(idx);
  11. }
  12.  
  13. template <class T>
  14. const Vector<T> &Matrix<T>::operator[](int idx) const
  15. {
  16.     if(idx < 0 || idx >= bitErrCntCI.size()) {
  17.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, bitErrCntCI.size()-1);
  18.         getchar();
  19.         exit(1);
  20.     }
  21.     return bitErrCntCI.at(idx);
  22. }

10 2803
perhaps you can think of Matrix class having a member variable of type Vector<Vector<T>> rather than deriving it from Vector<Vector<T>> which makes your matrix code as follows:

Expand|Select|Wrap|Line Numbers
  1. #include "Vector.h"
  2.  
  3. #ifndef _MATRIX
  4.  
  5. #define _MATRIX
  6.  
  7. using namespace std;
  8.  
  9.  
  10. template <class   T>   
  11. class Matrix {   
  12. public:   
  13.     Matrix();   
  14.     void setName(char *matrixName);
  15.     void showName();
  16.     void assignName(char *vectorName, int xSize, int ySize, T initialValue);
  17.     void print();
  18. private:
  19.     char nameOfMatrix[100];
  20.     Vector<Vector<T>> bitErrCntCI;
  21. };   
  22.  
  23. template <class T>
  24. Matrix<T>::Matrix()
  25. {
  26.  
  27. }
  28.  
  29. template <class T>
  30. void Matrix<T>::setName(char *matrixName) 
  31. {    
  32.     if(strlen(matrixName) >= 100) {
  33.         printf("Error: %s is more than 100 characters, please increase the size of nameOfMatrix[] in Matrix.h\n", vectorName);
  34.         getchar();
  35.         exit(1);
  36.     } else {
  37.         strcpy_s(nameOfMatrix, matrixName);
  38.     }
  39. }
  40.  
  41. template <class T>
  42. void Matrix<T>::showName()
  43. {
  44.     printf("The name of the matrix is %s\n", nameOfMatrix);
  45. }
  46.  
  47.  
  48. template <class T>
  49. void Matrix<T>::assignName(char *vectorName, int xSize, int ySize, T initialValue)
  50. {
  51.     if(strlen(vectorName) >= 100) {
  52.         printf("Error: %s is more than 100 characters, please increase the size of nameOfVector[] in Vector.h\n", vectorName);
  53.         getchar();
  54.         exit(1);
  55.     } else {
  56.         strcpy_s(nameOfMatrix, vectorName);
  57.     }
  58.  
  59.     char tmpChar[100];
  60.     int err_sprintf;
  61.     bitErrCntCI.resize(xSize);
  62.     for(int snrIdx = 0;snrIdx < xSize ;snrIdx++)
  63.     {
  64.         err_sprintf = sprintf_s(tmpChar, 100,"bitErrCntCI[%d]", snrIdx);
  65.         if(err_sprintf == -1) {
  66.             printf("Error: sprintf_s for bitErrCntCI[] in main.cpp is wrong.\n");
  67.             getchar();
  68.             exit(1);
  69.         }
  70.  
  71.         bitErrCntCI.at(snrIdx).assignName(tmpChar, ySize, initialValue);
  72.     }
  73. }
  74.  
  75.  
  76. #endif
Apr 8 '10 #2
herbu
5
Many thanks Akdemirc,

But in this way, I could not use the object of "Matrix" just like a regular 2-dimensional array. For example, to access the matrix as

Matrix tmp;
tmp.assignName("tmp", 3, 4, 0.00);

for(int rowIdx = 0;rowIdx < 3;rowIdx++) {
for(int colIdx = 0;colIdx < 4;colIdx++) {
tmp[rowIdx][colIdx] = input[rowIdx][colIdx];
}
}

I had seen codes which could do this but I forget how it is achieved. Any suggestions?

Best regards,
Herbu.
Apr 8 '10 #3
Banfa
9,065 Expert Mod 8TB
I agree about have your data held internally rather than deriving from it however I say why hold it as Vector<Vector<T>>. Just hold a Vector<T> of the right size of all entries in the matrix, so 9 for a 3 x 3 matrix for example.

It is a common mistake to always try and make the internal data representation of a class match what it makes available on the public interface and it is entirely unnecessary. Hold the data in the esiest way to hold the data design your interface to give calling the the interface you require.

As to
Expand|Select|Wrap|Line Numbers
  1. Matrix tmp;
  2. tmp.assignName("tmp", 3, 4, 0.00);
  3.  
  4. for(int rowIdx = 0;rowIdx < 3;rowIdx++) {
  5.     for(int colIdx = 0;colIdx < 4;colIdx++) {
  6.         tmp[rowIdx][colIdx] = input[rowIdx][colIdx];
  7.     }
  8. }
  9.  
are you sure you can't be happy with a member function something like

Expand|Select|Wrap|Line Numbers
  1.         tmp.at(rowIdx,colIdx) = input.at(rowIdx,colIdx);
  2.  
you could even overload operator() for


Expand|Select|Wrap|Line Numbers
  1.         tmp(rowIdx,colIdx) = input(rowIdx,colIdx);
  2.  
However if you insist on

Expand|Select|Wrap|Line Numbers
  1.         tmp[rowIdx][colIdx] = input[rowIdx][colIdx];
  2.  
The trick is to have operator[] return a class representing a row in the matrix that is a friend of the matrix class which also implments operator[].
Apr 8 '10 #4
adding two similar member functions to matrix class as you have in vector seems to do what you want:

declaration:
Expand|Select|Wrap|Line Numbers
  1.     Vector<T> &operator[] (int);
  2.     const Vector<T> &operator[] (int) const;

definition:

Expand|Select|Wrap|Line Numbers
  1. template <class T>
  2. Vector<T> &Matrix<T>::operator[] (int idx) 
  3. {
  4.     if(idx < 0 || idx >= bitErrCntCI.size()) {
  5.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, bitErrCntCI.size()-1);
  6.         getchar();
  7.         exit(1);
  8.     }
  9.     // printf("size = %d \n", size());
  10.     return bitErrCntCI.at(idx);
  11. }
  12.  
  13. template <class T>
  14. const Vector<T> &Matrix<T>::operator[](int idx) const
  15. {
  16.     if(idx < 0 || idx >= bitErrCntCI.size()) {
  17.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, bitErrCntCI.size()-1);
  18.         getchar();
  19.         exit(1);
  20.     }
  21.     return bitErrCntCI.at(idx);
  22. }
Apr 8 '10 #5
herbu
5
@akdemirc
Thanks akdemirc,

However, with this, when declare
Matrix<double> tmp;
tmp.assignName("tmp", 3, 4, 0.00);

When trying to
"tmp[-1][0] = 1.00;" we could see the error message due to operator loading
"template <class T>
Vector<T> &Matrix<T>::operator[] (int idx) "

However, it could not check "tmp[0][-1] = 1.00;".
Actually, the operator overloading "template <class T>
const Vector<T> &Matrix<T>::operator[](int idx) const " is not effective.

Does anyone know the difference between these two operator overloading?
1. template <class T>
Vector<T> &Matrix<T>::operator[] (int idx)
2. template <class T>
const Vector<T> &Matrix<T>::operator[](int idx) const

Best regards,
Herbu.
Apr 11 '10 #6
However, it could not check "tmp[0][-1] = 1.00;" is not completely true i think.. As you have boundary checks in Vector class and the -1 index is passes as parameter to Vector class' [] operator, it is the Vector class that should control the validity of this parameter.
Apr 14 '10 #7
herbu
5
@akdemirc
Thanks Akdemirc,

Yes, it is my fault to forget "#define CHECK_VECTOR_INDEX" such that the operator overloading in "Vector" is not activated. After defining CHECK_VECTOR_INDEX, "tmp[0][-1] = 1.00" would be checked.

However, do you know the meaning of "const T &operator[] (int) const;"
I learned this from a slides which said it is used to check the boundary when the array is at the right-hand-side of the equality. But this function just does not respond to any input.

Best regards,
Herbu.
Apr 14 '10 #8
const T &operator[] (int) const; declaration tells that this function returns a const reference of type T that cannot be modified (that make the return value only a r-value) and the const statement at the end tells us that the function guarantees not to modify any of the members of the class.
Apr 14 '10 #9
herbu
5
Thanks again, akdemirc,

Now I am clearer at the newly defined class. I slightly revise the codes
on Vector.h. It would be very much apprepciated in case I could learn your opinions on the revised codes.

Vector.h (ps: When need to activate the function of checking index of array/matrix boundary, we need to define the flag CHECK_VECTOR_INDEX.)
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <stdlib.h>
  7. #include <malloc.h>
  8. #include <string>
  9. #include <vector>
  10.  
  11. // #define CHECK_VECTOR_INDEX
  12.  
  13. #ifndef _VECTOR
  14. #define _VECTOR
  15.  
  16. using namespace std;
  17.  
  18. template <class   T>   
  19. class Vector : public vector<T>{   
  20.     public:   
  21.         Vector();   
  22.         void setName(char *vectorName);
  23.         void showName();
  24.         void assignName(char *vectorName, int vectorSize, T initialValue);
  25.         #ifdef CHECK_VECTOR_INDEX
  26.         T &operator[] (int);
  27.         const T &operator[] (int) const;
  28.         #endif
  29.     private:
  30.         char nameOfVector[100];
  31. };   
  32.  
  33. template <class T>
  34. Vector<T>::Vector()
  35. {
  36.  
  37. }
  38.  
  39. template <class T>
  40. void Vector<T>::setName(char *vectorName) 
  41. {    
  42.     if(strlen(vectorName) >= 100) {
  43.         printf("Error: %s is more than 100 characters, please increase the size of nameOfVector[] in Vector.h\n", vectorName);
  44.         getchar();
  45.         exit(1);
  46.     } else {
  47.         strcpy_s(nameOfVector, vectorName);
  48.     }
  49. }
  50.  
  51. template <class T>
  52. void Vector<T>::showName()
  53. {
  54.     printf("The name of the vector is %s\n", nameOfVector);
  55. }
  56.  
  57. template <class T>
  58. void Vector<T>::assignName(char *vectorName, int vectorSize, T initialValue)
  59. {
  60.     if(strlen(vectorName) >= 100) {
  61.         printf("Error: %s is more than 100 characters, please increase the size of nameOfVector[] in Vector.h\n", vectorName);
  62.         getchar();
  63.         exit(1);
  64.     } else {
  65.         strcpy_s(nameOfVector, vectorName);
  66.     }
  67.  
  68.     assign(vectorSize, initialValue);
  69. }
  70.  
  71. #ifdef CHECK_VECTOR_INDEX
  72. template <class T>
  73. T &Vector<T>::operator[] (int idx) 
  74. {
  75.     if(idx < 0 || idx >= size()) {
  76.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfVector, idx, size()-1);
  77.         getchar();
  78.         exit(1);
  79.     }
  80.     return at(idx);
  81. }
  82.  
  83. template <class T>
  84. const T &Vector<T>::operator[](int idx) const
  85. {
  86.     if(idx < 0 || idx >= size()) {
  87.         printf("Error: trying to access %s[%d] exceed [0, %d].\n", nameOfVector, idx, size()-1);
  88.         getchar();
  89.         exit(1);
  90.     }    
  91.     return at(idx);
  92. }
  93. #endif
  94.  
  95. #endif
  96. // -------------------------------    Define Class 2-dimensional vector (i.e. Matrix)   ------------------------------- 
  97. #ifndef _MATRIX   
  98. #define _MATRIX 
  99.  
  100. using namespace std; 
  101.  
  102. template <class   T>    
  103. class Matrix {    
  104.     public:    
  105.         Matrix();
  106.         void setName(char *matrixName);
  107.         void showName();
  108.         void assignName(char *vectorName, int xSize, int ySize, T initialValue);
  109.         Vector<T> &operator[] (int); 
  110.         const Vector<T> &operator[] (int) const; 
  111.     private: 
  112.         char nameOfMatrix[100];
  113.  
  114.         Vector< Vector<T> > internalVector;
  115.         Vector<int> tmp;
  116.         int rowSize;
  117.         int columnSize;
  118. };    
  119.  
  120. template <class T> 
  121. Matrix<T>::Matrix() 
  122.     rowSize = 0;
  123.     columnSize = 0;
  124.  
  125. template <class T> 
  126. void Matrix<T>::setName(char *matrixName)  
  127. {     
  128.     if(strlen(matrixName) >= 100) { 
  129.         printf("Error: %s is more than 100 characters, please increase the size of nameOfMatrix[] in Matrix.h\n", vectorName); 
  130.         getchar(); 
  131.         exit(1); 
  132.     } else { 
  133.         strcpy_s(nameOfMatrix, matrixName); 
  134.     } 
  135.  
  136. template <class T> 
  137. void Matrix<T>::showName() 
  138.     printf("The name of the matrix is %s\n", nameOfMatrix); 
  139.  
  140. template <class T> 
  141. void Matrix<T>::assignName(char *vectorName, int xSize, int ySize, T initialValue) 
  142. {
  143.     char tmpChar[100];
  144.     int err_sprintf; 
  145.     if(strlen(vectorName) >= 100) {
  146.         printf("Error: %s is more than 100 characters, please increase the size of nameOfVector[] in Vector.h\n", vectorName);
  147.         getchar();
  148.         exit(1);
  149.     } else {
  150.         strcpy_s(nameOfMatrix, vectorName);
  151.     }
  152.     rowSize = xSize;
  153.     columnSize = ySize;
  154.     internalVector.resize(xSize);
  155.     internalVector.setName(vectorName);
  156.  
  157.     for(int snrIdx = 0;snrIdx < xSize ;snrIdx++) {
  158.         err_sprintf = sprintf_s(tmpChar, 100,"%s[%d]", vectorName, snrIdx);
  159.         if(err_sprintf == -1) {
  160.             printf("Error: sprintf_s for %s[] in assignName of Matrix is wrong.\n", vectorName);
  161.             getchar();
  162.             exit(1);
  163.         }
  164.         internalVector.at(snrIdx).assignName(tmpChar, ySize, initialValue);
  165.     } 
  166.  
  167.  
  168. template <class T> 
  169. Vector<T> &Matrix<T>::operator[] (int idx)  
  170. {
  171.     #ifdef CHECK_VECTOR_INDEX
  172.     if(idx < 0 || idx >= rowSize) {
  173.         printf("Error: try to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, rowSize-1);
  174.         getchar();
  175.         exit(1);
  176.     }
  177.     #endif
  178.  
  179.     return internalVector.at(idx); 
  180.  
  181. template <class T> 
  182. const Vector<T> &Matrix<T>::operator[](int idx) const 
  183.     #ifdef CHECK_VECTOR_INDEX
  184.     if(idx < 0 || idx >= rowSize) {
  185.         printf("Error: try to access %s[%d] exceed [0, %d].\n", nameOfMatrix, idx, rowSize-1);
  186.         getchar();
  187.         exit(1);
  188.     }
  189.     #endif
  190.  
  191.     return internalVector.at(idx); 
  192. }
  193. #endif 
  194.  
Best regards,
Herbu.
Apr 15 '10 #10
Herbu,

The code looks pretty good that make it hard for me to give advice:) Perhaps you can think of removing the member variable tmp of type Vector in Matrix class which i can not see any usage of it.. Besides adding a print method both for Vector and Matrix class may be helpful in using them.. print method of Vector can simply print all elements it holds, while Matrix's print method iterates and calls the member vector's elements' print method and adding a newline at the end of each..

Best Regards,
akdemirc
Apr 15 '10 #11

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: saneman | last post by:
I have a folder 'app' containing a file 'main.cpp' and a subfolder 'types' (containing various header files). In main.cpp some header files from the subdir 'types' are included like: 1)...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.