list initialization for a matrix class - c++

I am trying to write a matrix class for linear algebra calculations. I have almost finished writing what I wanted. but I have a little trouble in creating a constructor that uses list initialization to create a matrix.
this is my class data members:
template <typename T>
class Matx
{
private:
// data members
//rows and columns of matrix
int rows, cols;
//pointer to pointer to type T
T** matrix;
and this is my code for initialization:
template <typename T>
Matx<T>::Matx(T* ptM[], int m, int n) : rows(m), cols(n)
{
matrix = new T*[rows];
for (int i = 0; i < rows; i++)
matrix[i] = new T[cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i][j] = *(ptM[i] + j);
}
in main:
double mat[][5] = { {5,5,-1,7,54},{4,-9,20,12,-6},{9,-18,-3,1,21},{ 61,-8,-10,3,13 },{ 29,-28,-1,4,14 } };
double* pm[5];
for (int i=0;i<5;i++)
pm[i]=mat[i];
Matx<double> yourMat = Matx<double>(pm, 5,5);
but I think there is a better way to do it.
what I want is to be able to initialize it like arrays. something like this:
Matx<double> yourMat = { {5,5,-1,7,54},{4,-9,20,12,-6},{9,-18,-3,1,21},{ 61,-8,-10,3,13 },{ 29,-28,-1,4,14 } };
Is it possible?

It is definitely possible, I have made constructors that use initializer lists for similar classes. A constructor like this should do the job:
template <typename T>
Matx<T>::Matx(std::initializer_list<std::initializer_list<T>> listlist) {
rows = (int)(listlist.begin())->size();
cols = (int)listlist.size();
matrix = new T*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new T[cols];
for (int j = 0; j < cols; j++) {
matrix[i][j] = ((listlist.begin()+i)->begin())[j];
}
}
}

For anyone with similar issue, this version has some minor corrections to the other answer. Tried this and it works in gcc 7.3, ubuntu 16.04.
template <typename T>
Matx<T>::Matx(std::initializer_list<std::initializer_list<T>> listlist) {
rows = (int)(listlist.begin())->size(); /* pointer correction here */
cols = (int)listlist.size();
matrix = new T*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new T[cols];
for (int j = 0; j < cols; j++) {
matrix[i][j] = ((listlist.begin()+i)->begin())[j]; /* again minor correction */
}
}
}

Related

How to transferring an array of main functions to a class?

First of all, I made this class.
class Matrix
{
public:
double ele[4][4];
int numOfRow;
int numOfColumns;
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = 0;
}
Matrix(double mat[][4], int Row, int Col) {
numOfRow = Row;
numOfColumns = Col;
for (int i = 0; i < numOfRow; i++) {
for (int j = 0; i < numOfColumns; j++) {
ele[i][j] = mat[i][j];
}
}
}
Matrix Add(Matrix m) {
Matrix output;
for (int i = 0; i < numOfRow; i++) {
for (int j = 0; j < numOfColumns; j++) {
output.ele[i][j] = ele[i][j] + m.ele[i][j];
}
}
return output;
}
Matrix Subtract(Matrix m);
Matrix Multiply(Matrix m);
Matrix Transpose(void);
};
This is part of the main function. In this way, I'm going to bring up the values of the txt files that I've already made in matA and matB and replace them. It's just a process of putting numbers in.
double matA[4][4];
for (int i = 0; i < RowA; i++) {
for (int j = 0; j < ColA; j++) {
fscanf(fpInput, "%lf", &matA[i][j]);
}
}
double matB[4][4];
for (int i = 0; i < RowB; i++) {
for (int j = 0; j < ColB; j++) {
fscanf(fpInput, "%lf", &matB[i][j]);
}
}
And we substitute matrixA and matrixB class objects, respectively.
Matrix matrixA(matA, RowA, ColA);
Matrix matrixB(matB, RowB, ColB);
I tried substitute Value obtained by 'Add' function into class object called matrixO. but, The substituted values did not work smoothly. For example, if matrixA contains (1, 2, 3) in order and matrixB has (4, 5, 6), then the 'add function' requires that the array of matrixO contains (5, 7, 9), but it does not. The value of the matrixO.ele is not output at all.
Matrix matrixO = matrixA.Add(matrixB);
for (int i = 0; i < RowA; i++) {
for (int j = 0; j < ColA; j++) {
fprintf(fpOutput, "%lf ", matrixO.ele[i][j]);
printf("%lf", matrixO.ele[i][j]);
}
fprintf(fpOutput, "\n");
}
In the Matrix constructor section, I changed it like this.
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = ele[0][0];
}
public:
Matrix() {
numOfRow = 0;
numOfColumns = 0;
ele[4][4] = {};
}
But both of these cases are wrong. How do we solve this issue?
You are assigning a value to your matrix out-of-bounds:
ele[4][4] = 0;
The last element of double ele[4][4]; is ele[3][3];
This is undefined behavior, so it makes no sense to analyze what happens after it.
You can 0-initialize your Matrix in its constructor like this:
Matrix(): ele(), numOfRow(), numOfColumns() {}

How can I dynamically allocate matrix that is made from triple pointer to a class?

So this is my class
class Map {
Field*** f;
int rows;
int columns;
};
How can I make a matrix of pointers to the class Field?
I tried this but it doesnt work.
Map(int rows_, int columns_) : rows(rows_), columns(columns_) {
f = new Field*[][];
*f = new Field*[rows];
for (int i = 0; i < rows; i++) {
*f[i] = new Field[columns];
}
}
You may consider rethinking about what you are doing. A flattened one dimensional array is a better choice.
If you still want to a *** pointer here is how you can make one:
f = new Field**[Row];
for(int i =0; i<Row; i++){
f[i] = new Field*[Col];
for(int j =0; j<Col; j++){
f[i][j] = new Field[H];
for(int k = 0; k<H;k++){
f3D[i][j][k] = 0;
}
}
}
Don't forget to free it.

Arbitrary matrix dimension in matrix class

The task is as follows: Describe the class "matrix of numbers" with component data: the dimensions of the matrix, a pointer to the elements. Overload operations: << (matrix output to the screen), + (addition of matrices), unary ¬– (change the sign of each element), / = (divide each element by a number). I performed it, and performed it correctly, but you need to set the matrix dimension from the keyboard, and as you can see, it is set in advance for me [3] [3]. It sounds pretty simple, but something I'm really dumb. Thanks in advance for your help. Here is the code:
#include "pch.h"
#include <iostream>
using namespace std;
class Matrix
{
public:
Matrix()
{
int Table[3][3];
}
int Table[3][3];
void Create()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
Table[i][j] = 10;
}
};
ostream& operator <<(ostream& t, Matrix a)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
t << a.Table[i][j] << " ";
t << "\n";
}
return t;
}
Matrix& operator /=(Matrix& a, int num)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] /= num;
return a;
}
Matrix& operator -(Matrix& a, int empty)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] = -a.Table[i][j];
return a;
}
Matrix& operator +(Matrix& a, Matrix b)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
int main()
{
int u;
setlocale(LC_ALL, "Russian");
Matrix Example;
Example.Create();
Matrix Example1;
Example1.Create();
cout << Example;
cout << Example1;
cout << "Сумма матриц: "<<endl;
cout << Example + Example1;
Example - 1;
Example1 - 1;
cout<< Example + Example1;
cout << "На сколько вы хотите её поделить?\n";
cin >> u;
Example /= u;
Example1 /= u;
cout << Example;
cout << Example1;
}`
You need to dynamically create the matrix.
In order to this you need to use pointers(*). Change int table[3][3]
double table**;
An example of how it could be implemented (note that I use matrix instead of table)
class Matrix {
private:
double** matrix;
int col;
int row;
public:
Matrix(){};
void Create(int row, int col);
};
void Matrix::Create(int row_, int col_){
double val = 0.0;
col = col_; // initalize private members
row = row_;
matrix = new double*[row]; // Create a new array of size row_
for(int i = 0; i < row; i++)
{
matrix[i] = new double[col]; // Create new cols of size col (inside array of row)
}
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
matrix[i][j] = val;
val = val + 1.0;
}
}
}
I tried to reuse your design for simplicity, but I really suggest that you try to specify the dimensions of the matrix in a constructor instead and maybe even construct the matrix in it as well.
Something like this:
Matrix(int row_, int col_) : row(row_), col(col_) {*/ create matrix here /*};
You can skip the "create matrix here" part and use your own Create() if you want to.
You need dynamic memory allocation for that. I won't fiddle around with pointers (new / delete) unless you are explicitly told to. As a beginner you should probably use the standard template library (STL) tools:
#include <vector> and use std::vector<std::vector<int>> Table instead of int Table[3][3]. Then write a constructor like this:
Matrix(std::size_t rows, std::size_t cols)
{
Table.resize(rows);
for (unsigned int i = 0; i < Table.size(); ++i)
Table[i].resize(cols);
}
You can additionally store the dimension of the matrix, but there is no need to do it since you can get the information from the vectors. Replace the hardcoded dimensions in all loops by the corresponding dynamic sizes (stored or extracted from the vectors). For example:
Matrix& operator +(Matrix& a, Matrix b)
{
unsigned int rows = a.Table.size();
unsigned int cols = a.Table[0].size();
for (unsigned int i = 0; i < rows; i++)
for (unsigned int j = 0; j < cols; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
However, this vector of vectors is not really effective. Better would be a single vector but I guess for a beginner it is okay.
Greetings

Adding template class to container without stl

I have template class Matrix and I want to create container to it without stl, but i have a problem with addding matrices to container (same matrices!!!). I create temp container that gets all the data and then delete all my data from container. I create new space for +1 Matrix in container and then try to put everything to my new container:
template<int row, int col, typename T=int>
class MatrixContainer {
public:
MatrixContainer<row, col, T>() {
size = 0;
container = new Matrix<row,col,T>[size];
}
void addMatrix(const Matrix<row, col, T> &mat) {
this->size=this->size+1;
Matrix<row,col,T> *temp = new Matrix<row,col,T>[this->size-1];
for (int i = 0; i < size-1; ++i) {
temp[i] = this->container[i];
}
delete[] this->container;
this->container = new Matrix<row,col,T>[size];
for (int i = 0; i < size-1; ++i) {
this->container[i] = temp[i];
}
container[size]=mat;
delete[]temp;
}
private:
Matrix<row, col, T> *container;
int size;
};
Everything compiles but when it sees
container[size]=mat;
it calls to copy constructor and then fails. That's a copy constructor in template class Matrix:
Matrix(const Matrix &other) {
this->elements = new T *[other.rows];
for (int i = 0; i < other.rows; i++) {
this->elements[i] = new T[other.cols];
}
this->rows = other.rows;
this->cols = other.cols;
for (int i = 0; i < this->rows; ++i) {
for (int j = 0; j < this->cols; ++j) {
this->elements[i][j] = other.elements[i][j];
}
}
}
I already tried everything but it fails every time when it gets this line

Trouble initializing multidimensional array inside class

So I count with the following excerpt of code:
template<class DT>
class AdjMat
{
protected:
DT** myMatrix;
int noOfNodes;
int noOfEdges;
public:
AdjMat(int _noOfNodes, int _noOfEdges);
//Destructor, constructors and other methods
};
template<class DT>
AdjMat<DT> :: AdjMat(int _noOfNodes, int _noOfEdges)
{
myMatrix = new DT*[_noOfNodes+1];
for(int i = 0; i < _noOfNodes+1; i++)
{
myMatrix[i] = new DT[_noOfNodes+1];
for(int j = 0; j < noOfNodes+1; j++)
myMatrix[i][j] = 0;
}
noOfNodes = _noOfNodes;
noOfEdges = _noOfEdges;
}
int main()
{
adjMat<int> m(5, 9);
}
The problem occurs in the constructor. The array doesn't seem to be initialized at all and much less the inner arrays, I have tried to go in different ways, but it won't initialize anything. Could anyone give me a hint of whatever I am doing wrong?
The error is in this line.
for(int j = 0; j < noOfNodes+1; j++)
noOfNodes has not been initialized yet. You probably meant:
for(int j = 0; j < _noOfNodes+1; j++)
You can avoid such errors by following a safer practice. Initialize as many members as you can in the initializer list.
template<class DT>
AdjMat<DT> :: AdjMat(int _noOfNodes, int _noOfEdges) : noOfNodes(_noOfNodes),
noOfEdges(_noOfEdges),
myMatrix(new DT*[_noOfNodes+1])
{
for(int i = 0; i < noOfNodes+1; i++)
{
myMatrix[i] = new DT[noOfNodes+1];
for(int j = 0; j < noOfNodes+1; j++)
myMatrix[i][j] = 0;
}
}