C++ multiplying matrices using dynamically allocated memory - c++

I am trying to write a function in C++ that multiplies two matrices A, B which have been dynamically allocated. I am currently trying to get the multiplication code working, then I will attempt to turn it into a function. Right now I am getting an error of sorts; "segmentation fault (core dumped)". I have narrowed it down to the multiplication part of my code but I have no idea what is wrong with it. Can someone help me please? My code is shown below.
#include <iostream>
#include <cassert>
int main()
{
int rowsA = 5; // number of rows
int colsA= 3; // number of coloumns
// dynamically allocating A
double** A;
A = new double* [rowsA];
A[0] = new double [rowsA*colsA];
for (int i = 1; i < rowsA; i++)
{
A[i] = A[i-1] + colsA;
}
// Storing elements of matrix A
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsA; ++j)
{
std::cout << "Enter element A" << i + 1 << j + 1 << " : ";
std::cin >> A[i][j];
}
}
int rowsB = 3; // number of rows
int colsB = 5; // number of coloumns
// dynamically allocating B
double** B;
B = new double* [rowsB];
B[0] = new double [rowsB*colsB];
for (int i = 1; i < rowsB; i++)
{
B[i] = B[i-1] + colsB;
}
// Storing elements of matrix B
for(int i = 0; i < rowsB; ++i)
{
for(int j = 0; j < colsB; ++j)
{
std::cout << "Enter element B" << i + 1 << j + 1 << " : ";
std::cin >> B[i][j];
}
}
// checking matrix multiplication qualification
assert(colsA == rowsB);
// dynamically allocating C
double** C;
C = new double* [rowsA];
C[0] = new double [rowsA*colsB];
for (int i = 1; i < rowsA; i++)
{
C[i] = C[i-1] + colsB;
}
// Initializing elements of matrix C to 0
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsB; ++j)
{
C[i][j]=0;
}
}
// multiplication
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsB; ++j)
{
for(int k = 0; k < colsB; ++k)
{
C[i][j] += A[i][k] * B[k][j];
}
}
}
// Displaying the multiplication of matrices A, B
std::cout<< "Matrix C: " << std::endl;
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsB; ++j)
{
std::cout << " " << C[i][j];
if(j == colsB-1)
{
std::cout << std::endl;
}
}
}
// deallocation
delete[] C[0];
delete[] C;
delete[] B[0];
delete[] B;
delete[] A[0];
delete[] A;
}

First, you say you are allocating the matrix properly but I'm not seeing any proof of that. You are allocating an array of pointers and only initializing the first index.. A[0] for example. This is incorrect. You need to allocate EACH ROW.
You have:
double** A;
A = new double* [rowsA];
A[0] = new double [rowsA*colsA]; //Incorrect. You only allocated A[0].
You need to allocate A[0] through A[rowsA - 1]..
Next, your multiplication loop (the inner most loop) is incorrect. It should be:
Iterate ColsA for that inner loop.
You have:
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsB; ++j)
{
for(int k = 0; k < colsB; ++k) //ColsB is incorrect. Should be colsA..
{
C[i][j] += A[i][k] * B[k][j]; //Segfaults here due to bad iteration..
}
}
}
The following would be correct:
#include <iostream>
#include <cassert>
double** create_matrix(int rows, int cols)
{
double** mat = new double* [rows]; //Allocate rows.
for (int i = 0; i < rows; ++i)
{
mat[i] = new double[cols](); //Allocate each row and zero initialize..
}
return mat;
}
void destroy_matrix(double** &mat, int rows)
{
if (mat)
{
for (int i = 0; i < rows; ++i)
{
delete[] mat[i]; //delete each row..
}
delete[] mat; //delete the rows..
mat = nullptr;
}
}
int main()
{
int rowsA = 5; // number of rows
int colsA= 3; // number of coloumns
double** matA = create_matrix(rowsA, colsA);
int rowsB = 3; // number of rows
int colsB = 5; // number of coloumns
double** matB = create_matrix(rowsB, colsB);
//Checking matrix multiplication qualification
assert(colsA == rowsB);
double** matC = create_matrix(rowsA, colsB);
//Multiplication
for(int i = 0; i < rowsA; ++i)
{
for(int j = 0; j < colsB; ++j)
{
for(int k = 0; k < colsA; ++k) //ColsA..
{
matC[i][j] += matA[i][k] * matB[k][j];
}
}
}
//Clean up..
destroy_matrix(matA, rowsA);
destroy_matrix(matB, rowsB);
destroy_matrix(matC, rowsA);
}

Related

Nested for loop not looping through second array

How do I get the second array to be properly looped through? It is a simple matrix multiplication operation (using Visual Studio 2019) and arr is being looped through, but arr2 isn't being looped through completely. Only the first 2 elements are being multiplied by all elements of arr.
#include <iostream>
using namespace std;
int main() {
int r1 = 2, c1 = 3, r2 = 3, c2 = 3;
int** arr = new int* [r1];
for (int i = 0; i < c1; i++) {
arr[i] = new int[c1];
}
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c1; j++) {
arr[i][j] = j;
}
}
int** arr2 = new int*[r2];
for (int i = 0; i < c2; i++) {
arr2[i] = new int[c2];
}
for (int i = 0; i < c2; i++) {
for (int j = 0; j < r2; j++) {
arr2[i][j] = j;
}
}
int** arr3 = new int*[r1];
for (int i = 0; i < c2; i++) {
arr3[i] = new int[c2];
}
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
arr3[i][j] = 0;
}
}
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
for (int g = 0; g < c1; g++) {
arr3[i][j] += arr[i][g] * arr2[g][j];
cout << "[" << i << "][" << g << "] " << arr[i][g] << "\tX\t" << "[" << g << "][" << j << "] " << arr2[g][j] << " => " << arr3[i][j] << endl;
}
}
}
cout << "\n" << endl;
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
cout << "New Array Element: [" << i << "][" << j << "] => " << arr3[i][j] << endl;
}
}
return 0;
}
You make the same basic mistake in all of your loops -- that mistake being that you are not iterating over the rows correctly.
You are using the column count when you should be using the row count:
int** arr = new int* [r1];
for (int i = 0; i < c1; i++) { // <-- This should be i < r1, not i < c1;
arr[i] = new int[c1];
}
Second, you could have written a function to lessen the chance of error, and also have a better chance of finding bugs like this:
int **createArray(int rows, int cols)
{
int** arr = new int* [rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = j;
}
}
return arr;
}
int main()
{
int r1 = 2, c1 = 3, r2 = 3, c2 = 3;
int** arr = createArray(r1, c1);
int** arr2 = createArray(r2,c2);
int** arr3 = createArray(r1,c2);
//...
}
Now the creation code is not repeated over and over again, plus the issue of using the wrong variables becomes minimized, if not eliminated.
Having said this, this way of creating 2D arrays is one of the worst ways of doing this. Right now, your code has memory leaks (it still is considered a leak, even though the program will terminate -- memory tools such as valgrind and others would indicate the errors as soon as your program exits).
Ideally, you would use a container class such as std::vector<int> to handle the dynamic memory management automatically.
But even if this is an exercise where you must use int**, it is still a very bad way of creating two-dimensional arrays under those constraints. Here is an answer that goes in detail about this issue, why it's bad, and how it can be alleviated.

How can I find the size of a matrix which passed to function?

In this C++ code sizeof (ar) doesn't help me to find cols and rows variables and always gives me the same wrong cols and rows.
How can I find the size of the matrix without passing sizeX and sizeY variables to the IsMagicSquare(arr) function? Can you help me to understand this problem and find a way to solve it?
int main()
{
int sizeX, sizeY;
cout << "Size of Matrix:";
cin >> sizeX >> sizeY;
int** arr = new int* [sizeY];
for (int i = 0; i < sizeY; ++i)
{
arr[i] = new int[sizeX];
}
cout << "Elements of the Matrix:";
for (int i = 0; i < sizeX; i++)
for (int j = 0; j < sizeY; j++)
cin >> arr[i][j];
if (IsMagicSquare(arr))
{
for (int i = 0; i < sizeX; i++)
{
cout << "\n";
for (int j = 0; j < sizeY; j++)
cout << arr[i][j];
}
}
else
{
for (int i = 0; i < sizeY; i++)
{
delete[] arr[i];
}
delete[] arr;
}
return 0;
}
bool IsMagicSquare(int** ar)
{
int rows = sizeof (ar)/ sizeof (ar[0]);
int cols = sizeof (ar[0]) / sizeof(int);
cout << rows << cols;
if (rows == cols)
{
int* ver = new int[rows]();
int* hor = new int[cols]();
int cross0=0;
int cross1=0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
hor[i] += ar[i][j];
ver[j] += ar[i][j];
if (i == j)
cross0 += ar[i][j];
else if ((i+j) == cols)
cross1 += ar[i][j];
}
}
if (cross0 != cross1)
return false;
else
{
for (int i = 0; i < rows; i++)
if ((cross0 != ver[i]) || (cross1 != hor[i]))
return false;
}
}
else
return false;
return true;
}
Just sum the allocations you are making for a reasonable estimate:
The outer array: sizeY * sizeof(int*).
The inner arrays: sizeY * sizeX * sizeof(int)
Of course, the size calculations you got in IsMagicSquare() won’t work: sizeof operates on the types rather than the actual allocated memory. That information is lost and can’t be recovered from the pointers. You are best off to use, e.g., a std::vector<std::vector<int>>. That deals with automatic memory allocation and it tracks the sizes of the structure.

Adding two 2D arrays together in C++ - Why do this program crash?

Hey I am beginner at C++ programming. I have made a program that is meant to add two 2D arrays together. However, The program outputs the values until the program crashes. Can someone help me to identify the problem?
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int a[10][10], c[10][10], i, j;
for (i = 1; i <= 10; ++i)
{
for(j=0; j < 10; ++j)
{
a[i][j] = i * j;
}
}
// We are able to treat the individual columns as arrays
for (int i = 0; i < 10; ++i)
{
int *b = a[i];
for (int j = 0; j < 10; ++j)
{
cout << b[j] << " ";
}
cout << endl;
}
cout << "****" << endl;
// Declare a multidimensional array on the heap
int **b = new int*[10];
// need to allocate all members individually
for (int i = 0; i < 10; ++i)
{
b[i] = new int[10];
}
// Set the values of b
for (int i = 0; i < 10; ++i)
{
for (j = 0; j < 10; ++j)
{
b[i][j] = (i * 10) + j;
}
}
for (i = 0; i < 10; ++i)
{
for (j = 1; j <= 10; ++j)
{
c[i][j] = a[i][j] + b[i][j];
}
}
for (i = 0; i < 10; ++i)
{
for (j = 1; j <= 10; ++j)
{
cout << c[i][j] << endl;
}
}
// Delete the multidimensional array - have to delete each part
for (int i = 0; i < 10; ++i)
{
delete[] b[i];
}
delete[] b;
return 0;
}
I corrected your code.Now, It's working and program didn't crash. You can try it out.
#include<conio.h>
#include<iostream.h>
int main(int argc, char** argv)
{
int a[10][10], c[10][10], i, j;
for (i = 0; i <10; ++i)
{
for(j=0; j < 10; ++j)
{
a[i][j] = i * j;
}
}
//We are able to treat the individual columns as arrays;
for (i = 0; i < 10; ++i)
{
int *b = a[i];
for (int j = 0; j < 10; ++j)
{
cout << b[j] << " ";
}
cout << endl;
}
cout << "****" << endl;
//Declare a multidimensional array on the heap;
int **b = new int*[10];
//need to allocate all members individually
for (i = 0; i < 10; ++i)
{
b[i] = new int[10];
}
//Set the values of b
for ( i = 0; i < 10; ++i)
{
for (j = 0; j < 10; ++j)
{
b[i][j] = (i * 10) + j;
}
}
for (i = 0; i < 10; ++i)
{
for (j = 0; j <10; ++j)
{
c[i][j] = a[i][j] + b[i][j];
}
}
for (i = 0; i < 10; ++i)
{
for (j = 0;j < 10; ++j)
{
cout << c[i][j] << " ";
}
cout<<endl;
}
// Delete the multidimensional array - have to delete each part
for (i = 0; i < 10; ++i)
{
delete[] b[i];
}
delete[] b;
return 0;
}

Matrix multiplication with class operator

i am working on multiplication of matrix
it is something like
m5 = m2 * m3;
cout << "m2 * m3 is : " << endl<< m5 << endl;
and this is my code
const Matrix Matrix::operator*(const Matrix &a)
{
Matrix temp(a.row,a.col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
for (int k = 0; k<a.row; k++)
{
temp.data[i][j] = temp.data[i][j] + data[i][k] * a.data[k][j];
}
}
}
return temp;
}
However, there is an error always showing at my printing function
ostream& operator<<(ostream &output, const Matrix &a)
{
for (int i = 0; i < a.row; i++)
{
for (int j = 0; j < a.col; j++)
{
output << a.data[i][j] << "\t";
}
output << "" << endl;
}
return output;
}
seems there has a problem on a.data[i][j] which i dont know what's the problem
it works fine on addition.
it is showing an error {data0x005fba90{0xfeeefeee{???}}
can anybody give any advice or suggestions or help on this situation
this is my copy constructor
Matrix::Matrix(const Matrix&m2)
{
row = m2.row;
col = m2.col;
setUp(row, col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = m2.data[i][j];
}
}
}
this is the set up and default
Matrix::Matrix()
{
row =0;
col = 0;
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
}
Matrix::Matrix(int a, int b, double d[], int c)
{
row = a;
col = b;
setUp(row, col);
int counter = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = d[counter];
counter++;
}
}
}
and the set up
void Matrix::setUp(int a, int b)
{
row = a;
col = b;
data = new double*[row];
for (int i = 0; i < row; i++) data[i] = new double[col];
}
Without seeing your Matrix constructor, or the class definition, it's hard to say for certain, but if you look at this expression
temp.data[i][j] + data[i][k] * a.data[k][j]
Depending on what data is, if you don't explicitly initialize the data member in the constructor when you create temp then its contents will not automatically be initialized, and the contents will be indeterminate and using it will lead to undefined behavior.
Another possible source of problems might be the lack of a copy-constructor, or a faulty copy-constructor. This is a problem since you return temp by value which invokes the copy-constructor.

Position 2D array bug as parameter causes memory dumps

This is my program in C++, which accepts an 2D array a[m][n]. If an element a[i][j] is zero, then set all the ith row and jth column elements to zero.
This is code sample:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class SetZero{
public:
static void setZero(int **, int , int);
};
void SetZero::setZero(int ** a, int m, int n){
int i, j, k;
int ** b = new int *[m]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i][j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i][j] == 0 && b[i][j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
for(k = 0; k < m; k++){
a[k][j] = 0;
b[k][j] = 0;
}
j = n;//break. next row loop.
}
for(int i = 0; i < m; i++)
delete[] b[i];
delete[] b;
}
int main(){
int a[4][5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i][j] = rand() % 100;
cout << a[i][j] << " ";
}
cout << endl;
}
SetZero::setZero((int **)a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
Environment: WIN8 Visual Studio 2012.
Edit:
The program can compile but cannot execute normally. It will stop when it reaches if(a[i][j] == 0 && b[i][j]){
The error message is:
Unhandled exception at 0x012875DD in CCLC.exe: 0xC0000005: Access
violation reading location 0x0000004B.
SetZero::setZero((int **)a, 4, 5)
a is not an array of pointers, it is simply a 2 dimensional array.
notice how the access violation is reading address 0x0000004B? that's 75, a number between 0 and 99 :) because you are treating a 2 dimensional array (which is just a one dimensional array with a neat way of accessing it) as an array of arrays, it is taking one of the values in your array (75) to be the address of a sub array, then trying to read the non existent array at address 75 (or 0x0000004B)
I suggest that you 'flatten' your arrays and work with them as one dimensional arrays, which I find simpler:
void SetZero::setZero(int * a, int m, int n){
int i, j, k;
int * b = new int [m*n]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i*n+j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i*n+j] == 0 && b[i*n+j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i*n+k] = 0;//but there is NO dump here. Weird!
b[i*n+k] = 0;
}
for(k = 0; k < m; k++){
a[k*n+j] = 0;
b[k*n+j] = 0;
}
j = n;//break. next row loop.
}
delete[] b;
}
int main(){
int a[4*5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i*5+j] = rand() % 100;
cout << a[i*5+j] << " ";
}
cout << endl;
}
SetZero::setZero(a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i*5+j] << " ";
cout << endl;
}
return 0;
}
One suggestion about the SetZero(). There is a function called memset() which allows you to set all bytes to a specific value given a starting pointer and the range. This function could make your SetZero() function more cleaner:
void * memset ( void * ptr, int value, size_t num );
Fill block of memory. Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
Parameters
ptr: Pointer to the block of memory to fill.
value: Value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
num: Number of bytes to be set to the value, size_t is an unsigned integral type.
For example, the following code block from your program:
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
can be achieved by memset in a cleaner way:
memset(a[i], 0, n * sizeof(int));
memset(b[i], 0, n * sizeof(int));