the statement below the function calling is not executed. i am at a loss, why this is so? could someone please clarify. Please consider the code below :
#include<iostream>
#include<cmath>
using namespace std;
class Matrix
{
private:
int row,col;
double *values;
public:
Matrix();
Matrix(int r, int c, double* x);
void setdim(int m, int n){row=m;col=n;}
int getrowdim() const {return row;}
int getcoldim() const {return col;}
void set_values(int i, double x);
double get_value(int i) const;
friend Matrix operator+(const Matrix &A, const Matrix &B);
};
Matrix::Matrix()
{
this->row = 0;
this->col = 0;
this->values = NULL;
}
Matrix::Matrix(int r, int c, double* x)
{
this->row = r;
this->col = c;
this->values = new double[r*c];
for (int i =0;i<r*c;i++)
{
cout<<"Enter value ["<<i<<"] ";
cin>>this->values[i];
}
}
void Matrix::set_values(int k, double x)
{
this->values[k] = x;
}
Matrix operator+(const Matrix &A, const Matrix &B)
{
int rowa = A.getrowdim();
int cola = A.getcoldim();
int rowb = B.getrowdim();
int colb = B.getcoldim();
if(rowa == rowb && cola == colb)
{
Matrix C;
C.setdim(rowa, colb);
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m );
cout<<"Returned from C.set_values()"<<endl;
// THIS STATEMENT DOES NOT GET PRINTED. PLEASE TELL THE REASON // WHY. I SUSPECT THE ERROR IS HERE
}
return C;
}
else
{
cout<<"Invalid Operation";
return A;
}
}
double Matrix::get_value(int i) const
{
return this->values[i];
}
int main()
{
Matrix A(2,2,NULL);
Matrix B(2,2,NULL);
Matrix C;
C = A+B;
return 0;
}
The statement - Returned from C.set_values() does not get printed at all .
Could someone help clarify why this is the case? Thanks a lot for the help!
Here:
Matrix C; // (1)
C.setdim(rowa, colb); // (2)
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m ); // (3)
You default construct a Matrix (1). The default constructor just sets the member values to NULL. Then you adjust the size members in (2), but values is still NULL. Then, in (3) you call set_values which tries to access array elements, but there is no array.
The problem is that your Matrix has a raw owning pointer as member. When a class manages a resource you must follow the rule of 3/5. If you don't, the class is broken. Managing a resource is not trivial, and following the rule of 3/5 is just the bare minimum.
The simpler alternative that you should strive for is the rule of 0. For a class that does not manage a resource, the compiler generated special members are just right. If you replace the raw pointer member with a std::vector<double> then you do not need to worry about copying, assignment or destruction, because the compiler will generate the required methods for you.
I am working on a homework assignment that involved converting matrix and array classes supplied by my professor into templates. I am getting an error '=': cannot convert from 'Array *' to 'int' in my line m[i] = new Array < Type >(cols);
I would assume this is because m[i] is returning an int but I don't think it should be if I wrote my templates correctly and I can't quite figure out why it is giving back an int instead of a array pointer since m is an array of array pointers here is the code to my array template minus some overloads for << not used in this code.
template
< typename Type >
class Array
{
private:
int len;
Type * buf;
public:
Array(int newLen)
: len(newLen), buf(new Type[newLen])
{
}
Array(const Array & l)
: len(l.len), buf(new Type[l.len])
{
for (int i = 0; i < l.len; i++)
buf[i] = l.buf[i];
}
int length()
{
return len;
}
int & operator [] (int i)
{
assert(0 <= i && i < len);
return buf[i];
}
}
Here is my matrix template the error occurs in minus the same << overloads
#pragma once
#include "Array.h"
template
< typename Type >
class Matrix
{
private:
int rows, cols;
Array< Array<Type> * > m;
public:
Matrix(int newRows, int newCols)
: rows(newRows), cols(newCols), m(rows)
{
for (int i = 0; i < rows; i++)
m[i] = new Array < Type >(cols);
}
int numRows()
{
return rows;
}
int numCols()
{
return cols;
}
Array < Type > & operator [] (int row)
{
return *m[row];
}
}
The [] operator overload in the array class is what's messing you up.
int & operator [] (int i)
{
assert(0 <= i && i < len);
return buf[i];
}
It clearly returns an int as its type and when you try to use it such that: m[i] = new Array < Type >(cols);
m[i] will return an int type which you're trying to assign a new Array to.
The proximal issue is that Array isn't fully templated:
int & operator [] (int i)
Indexing into an Array<T> shouldn't give you an int&, it should give you a T&!
The other issue with your code is that you have a new in your Array constructor - where's the corresponding delete? You're leaking memory!
Same for the Matrix constructor, which additionally has the potential of double deleting memory if you happen to copy it.
See Rule of Three
I've problem with Initialize the element of multidimensional array.
Here's my code:
class A{
int *const e;
const int row, column;
public:
A::A(int r, int c) : row(r), column(c), e(new int[r*c])
{
for (int i = 0; i < r*c; i++)
{
e[i] = 0;
}
}
A(const A &matrix) : row(matrix.row), column(matrix.column) ,e(new int[matrix.row*matrix.column])
{
for (int i = 0; i < matrix.row*matrix.column; i++)
{
e[i] = matrix.e[i];
}
}
virtual ~A() //destructing a A
{
delete[] e;
}
};
But when I'm trying Initialize the element of multidimensional array I've got a error:
int main(int argc, char* argv[])
{
A c(2, 5);
c[0][0] = 1;
A a(c);
return 0;
}
1 IntelliSense: no operator "[]" matches these operands operand types are: MAT [ int ]
Edit:
According to comments I try to write operator []
virtual int *const operator[ ](int r)
{
return e[r][0];
}
It should get first element of the r row. But I've got a error:
1 IntelliSense: expression must have pointer-to-object type
You're trying to apply the [] to the class A, C++ only knows how to use the operator [] on arrays. In order to use them for A you have to tell how [] works for A, so inside your class definition you should put:
int *operator[](int x){
return &e[x*row];
}
It basically receives the number you have put between brackets, and returns the corresponding row(an array), so you can apply [] again easily, so for example:
c[0] returns the first row
c[0][1] access the second element of the first row
Why does this program write 45, 125 and 300?
I know for 45 and 300, I'm more interested in a case sum1(arrD), where program writes 125.
I hope somebody will know.
#include <iostream>
using namespace std;
class B{
public:
B(): b(bCounter++){}
int b;
static int bCounter;
};
int B::bCounter = 0;
class D : public B{
public:
D() : d(bCounter){}
int d;
};
const int N = 10;
B arrB[N];
D arrD[N];
int sum1(B* arr){
int s = 0;
for (int i=0; i<N; i++) s+=arr[i].b;
return s;
}
int sum2 (D* arr){
int s = 0;
for (int i = 0; i<N; i++) s+= arr[i].b + arr[i].d;
return s;
}
int main(){
cout<<" result is: "<<sum1(arrB)<<endl;
cout<<" result is: "<<sum1(arrD)<<endl;
cout<<" result is: "<<sum2(arrD)<<endl;
system("pause");
return 0;
}
The static arrays B arrB[N] and D arrD[N] seem to be causing the trouble here.
Arrays aren't polymorphic; you can pass a D* to a function expecting a B* only if it expects a single element. (Try using std::vector, and you'll get a compile time error.) The reason is simple: the pointer arithmetic needed to access the array elements is based on the static size of the pointed to element, so each time you do i++ in the loop in sum1, and then index, the compiler calculates the address of your element as arr + i * sizeof(B) (at the machine level, where arr is a pure, untyped address).
Trying to do pointer arithmetic when the static type is not the same as the dynamic type is undefined behavior, so as far as the language is concerned, anything can happen.
And this is yet another reason not to use C style arrays.
The problem is that the arrays do not contain pointers to the objects but whole objects.
So when you use the D array via a pointer to the base class, (as James noted) the behaviour is undefined.
What in practice probably happens on most systems: The pointer-based loop only iterates over half the D objects, because a B object contains only one int, while the D objects contain two of them.
So the loop looks only at the first 5 D objects:
b / d
10/11
11/12
12/13
13/14
14/15
which sums up to the ominous 125.
I think it's incorrect to cast an array of D to an array of B. The stride isn't correct. This is why you see these repeats of values.
Run following code , you'll know the reason
#include <iostream>
using namespace std;
class B{
public:
B(): b(bCounter++){
cout<<"B called\n";
}
int b;
static int bCounter;
};
int B::bCounter = 0;
class D : public B{
public:
D() : d(bCounter){
cout<<"D called\n";
}
int d;
};
const int N = 10;
B arrB[N];
D arrD[N];
int sum1(B* arr){
int s = 0;
for (int i=0; i<N; i++)
{
cout<<arr[i].b<<"\n";
s+=arr[i].b;
}
return s;
}
int sum2 (D* arr){
int s = 0;
for (int i = 0; i<N; i++) s+= arr[i].b + arr[i].d;
return s;
}
int main(){
//cout<<" result is: "<<sum1(arrB)<<endl;
cout<<" result is: "<<sum1(arrD)<<endl;
//cout<<" result is: "<<sum2(arrD)<<endl;
system("pause");
return 0;
}
I have a program that looks like the following:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
No, there's no right way to do specifically that. A double[4][4] array is not convertible to a double ** pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
The simplest way to do the latter, i.e. to make your existing double[4][4] array compatible with the function, is to create temporary "index" arrays of type double *[4] pointing to the beginnings of each row in each matrix
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows and inverseRows arrays, since the result will be placed into your original inverseMatrix array correctly.
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
One thing you could do: templates. Make the size of the second dimension a template parameter.
#include <iostream>
template <unsigned N>
void print(double a[][N], unsigned order)
{
for (unsigned y = 0; y < order; ++y) {
for (unsigned x = 0; x < N; ++x) {
std::cout << a[y][x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(arr, 3);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
#include <iostream>
void print(double *a, unsigned height, unsigned width)
{
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
std::cout << a[y * width + x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(&arr[0][0], 3, 3);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
#include <iostream>
using namespace std;
template <int matrix_size>
class SquareMatrix
{
public:
int size(void) { return matrix_size; }
double array[matrix_size][matrix_size];
void copyInverse(const SquareMatrix<matrix_size> & src);
void print(void);
};
template <int matrix_size>
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
{
int inv_x;
int inv_y;
for (int x = 0; x < matrix_size; x++)
{
inv_x = matrix_size - 1 - x;
for (int y = 0; y < matrix_size; y++)
{
inv_y = matrix_size - 1 - y;
array[x][y] = src.array[inv_x][inv_y];
}
}
}
template <int matrix_size>
void SquareMatrix<matrix_size>::print(void)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
cout << array[x][y] << " ";
}
cout << endl;
}
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix);
int main(int argc, char * argList[])
{
SquareMatrix<4> startMatrix;
SquareMatrix<4> inverseMatrix;
Initialize(startMatrix);
inverseMatrix.copyInverse(startMatrix);
cout << "Start:" << endl;
startMatrix.print();
cout << "Inverse:" << endl;
inverseMatrix.print();
return 0;
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix)
{
for (int x = 0; x < matrix_size; x++)
{
for (int y = 0; y < matrix_size; y++)
{
matrix.array[x][y] = (x+1)*10+(y+1);
}
}
}
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]. For your function, the signature should be like:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
There is a solution using the pointer to point by bobobobo
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
int numRows = 16 ;
int numCols = 5 ;
int **a ;
a = new int*[ numRows* sizeof(int*) ];
for( int row = 0 ; row < numRows ; row++ )
{
a[row] = new int[ numCols*sizeof(int) ];
}
The rest of code is the same with bobobobo's.
You can definitely do something like the code below, if you want.
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][]).
by nice coding if c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interface would be
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
the interface is very simple and clear.
once need to modify "m" of matrix internally, you don't need to update the interface.
Or this way
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
void MatrixInversion(void *A, int order, void *B)
{
double _a[4][4];
double _b[4][4];
memcpy(_a, A, sizeof _a);
memcpy(_b, B, sizeof _b);
// processing data here
// copy back after done
memcpy(B, _b, sizeof _b);
}