Subhranil Dey
Subhranil Dey

Reputation: 25

Returning a 2D dynamic array from a fuction

I need some help with returning a 2d dynamic array(matrix) from a function. The function takes the matrix inputted and finds the transpose and returns the matrix. My main takes the number of rows and columns the user wants and then takes the entries for the matrix. Then I call my function and try to hold it in another dynamic matrix I created and try to court the matrix but I have a problem doing that. I do not know how to hold the resultant matrix. Any help is much-appreciated thanks. Can you also check if my deallocation process is alright?

Just realized the program works for square matrices but not if rows and cols are different, can you please point out my mistake?

int** transpose(int** arr, int rows, int cols)
{
    int** array1 = new int*[cols];

    for(int i =0; i < cols; i++)              
    {
        array1[i] = new int[rows];
    }

    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            array1[i][j] = arr[j][i];
        }
    }
    
    return array1;
for(int i =0; i < cols; i++)
{
    delete[] array1;
}
delete[] array1;
}

int main()
{
int rows, cols;
    cout << "Please enter the number of rows for the matrix: ";
    cin >> rows;
    cout << "Please enter the number of columns for the matrix: ";
    cin >> cols;

    int** array0 = new int*[rows];

    for(int i =0; i < rows; i++)
    {
        array0[i] = new int[cols];
    }

    // how to cin the elements for the matrix now
    //basicalliy it is thnesame as any 2d array
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            cin >> array0[i][j];
        }
    }

    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            cout << array0[i][j] << " ";
        }
        cout << endl;
    }

    int** array2 = new int*[cols];
    for(int i = 0; i < cols; i++)
    {
        array2[i] = new int[cols];
    }
    array2 = transpose(array0, rows, cols);

    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            cout << array2[i][j] << " ";
        }
        cout << endl;
    }
    for(int i =0; i < cols; i++)
    {
        delete[] array2;
    }
    delete[] array2;

    for(int i =0; i < rows; i++)
    {
        delete[] array0;
    }
     delete[] array0;



    system("pause");
    return 0;
}

Upvotes: 1

Views: 198

Answers (1)

A M
A M

Reputation: 15277

First of all. In C++ the usage of new and delete and raw pointers for owned memory is strongly discouraged. It is that error prone that it is even forbidden to use it in many products. For example in the automotive industry.

But, I understand that your teacher wants you to do this, to understand the underlying mechanisms in dynamic memory management.

So, lets use it for your learning purposes.

Basically you approach is not bad. But you are mixing up rows and columns for the transposed matrix. And this will cause an out of bounds runtime exception.

Then, in your function transpose, your are trying to delete the just allocated array. But you still need this in the main function. You want to return array1 from your function. So do not delete it. But, because you moved the return statement before the delete operation, this will never be called. It is dead code. After return the code will not be executed, because your return out of the function.

Anyway. It must not be used here, so delete it.

A further problem is your naming of the variables. If you would use meaningful "speaking" names, then you would have seen your problem already by yourself.

Let us look at your code:

#include <iostream>
using namespace std;
int** transpose(int** arr, int rows, int cols)
{
    int** array1 = new int* [cols];

    for (int i = 0; i < cols; i++)
    {
        array1[i] = new int[rows];
    }

    for (int i = 0; i < rows; i++) // *** Mixing of indices. Should be cols here
    {
        for (int j = 0; j < cols; j++) // *** Mixing of indices. Should be rows here
        {
            array1[i][j] = arr[j][i];
        }
    }

    return array1;

    // *** Dead code, will nver be called
    // And, must NOT be done in this function
    for (int i = 0; i < cols; i++)
    {
        delete[] array1;
    }
    delete[] array1;
}

int main()
{
    int rows, cols;
    cout << "Please enter the number of rows for the matrix: ";
    cin >> rows;
    cout << "Please enter the number of columns for the matrix: ";
    cin >> cols;

    int** array0 = new int* [rows];

    for (int i = 0; i < rows; i++)
    {
        array0[i] = new int[cols];
    }

    // how to cin the elements for the matrix now
    //basicalliy it is thnesame as any 2d array
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cin >> array0[i][j];
        }
    }

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            cout << array0[i][j] << " ";
        }
        cout << endl;
}

    // Completely unessecarry. Arry will be allocated in subfunction
    int** array2 = new int* [cols];
    for (int i = 0; i < cols; i++)
    {
        array2[i] = new int[cols];
    }


    array2 = transpose(array0, rows, cols);  // *** Simply define array2 as int**

    for (int i = 0; i < rows; i++) // *** Mixing of indices. Should be cols here
    {
        for (int j = 0; j < cols; j++) // *** Mixing of indices. Should be rows here
        {
            cout << array2[i][j] << " ";
        }
        cout << endl;
    }
    for (int i = 0; i < cols; i++)
    {
        delete[] array2; // You need to delete array2[i]
    }
    delete[] array2;

    for (int i = 0; i < rows; i++)
    {
        delete[] array0; // You need to delete array0[i]
    }
    delete[] array0;

    system("pause");
    return 0;
}

I added comments where the errors are.

If we correct these errors, then we will see the following working code:

#include <iostream>

int** transpose(int** arr, int rows, int cols)
{
    int** array1 = new int* [cols];

    for (int i = 0; i < cols; i++)
    {
        array1[i] = new int[rows];
    }

    for (int i = 0; i < cols; i++)
    {
        for (int j = 0; j < rows; j++)
        {
            array1[i][j] = arr[j][i];
        }
    }

    return array1;
    for (int i = 0; i < cols; i++)
    {
        delete[] array1;
    }
    delete[] array1;
}

int main()
{
    int rows, cols;
    std::cout << "Please enter the number of rows for the matrix: ";
    std::cin >> rows;
    std::cout << "Please enter the number of columns for the matrix: ";
    std::cin >> cols;

    int** array0 = new int* [rows];

    for (int i = 0; i < rows; i++)
    {
        array0[i] = new int[cols];
    }

    // how to cin the elements for the matrix now
    //basicalliy it is thnesame as any 2d array
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            std::cin >> array0[i][j];
        }
    }

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            std::cout << array0[i][j] << " ";
        }
        std::cout << std::endl;
    }
    /*
    int** array2 = new int* [cols];
    for (int i = 0; i < cols; i++)
    {
        array2[i] = new int[cols];
    }
    */

    int** array2 = transpose(array0, rows, cols);

    for (int i = 0; i < cols; i++)
    {
        for (int j = 0; j < rows; j++)
        {
            std::cout << array2[i][j] << " ";
        }
        std::cout << std::endl;
    }

    for (int i = 0; i < cols; i++)
    {
        delete[] array2[i];
    }
    delete[] array2;

    for (int i = 0; i < rows; i++)
    {
        delete[] array0[i];
    }
    delete[] array0;

    return 0;
}

And now the same code. But with better varaiable names and comments.

This is by far better understandable.

#include <iostream>

// Function to transpose a given 2d array and return a new dynamically create transposed array
int** transpose2dArray(int** arrayToTranspose, unsigned int numberOfRowsOriginal, unsigned int numberOfColumnsOriginal)
{
    // Transposing means basically a swap of rows and columns
    unsigned int numberOfRowsTransposed = numberOfColumnsOriginal;
    unsigned int numberOfColumnsTransposed = numberOfRowsOriginal;

    // Allocate a new 2d array. But now, with new (transposed) dimensions
    int** arrayTransposed = new int* [numberOfRowsTransposed];
    for (unsigned int row = 0; row < numberOfRowsTransposed; ++row)
    {
        arrayTransposed[row] = new int[numberOfColumnsTransposed];
    }

    // Now do the transpose action. Simply exchange orws and columns
    for (unsigned int row = 0; row < numberOfRowsTransposed; ++row)
    {
        for (unsigned int col = 0; col < numberOfColumnsTransposed; ++col)
        {
            arrayTransposed[row][col] = arrayToTranspose[col][row];
        }
    }
    // And thats it. Return transposed array to caller of this function
    return arrayTransposed;
}

int main()
{
    // Get the numer of rows and coulmns for the array to transpose from the user
    unsigned int numberOfRows, numberOfColumns;
    std::cout << "Please enter the number of rows for the matrix: ";
    std::cin >> numberOfRows;
    std::cout << "\nPlease enter the number of columns for the matrix: ";
    std::cin >> numberOfColumns;

    // Allocate 2d array dynamically, based on user input
    int** array = new int* [numberOfRows];
    for (unsigned int row = 0; row < numberOfRows; ++row)
    {
        array[row] = new int[numberOfColumns];
    }
    // Read all values for the 2d array from the user
    for (unsigned int row = 0; row < numberOfRows; ++row)
    {
        for (unsigned int col = 0; col < numberOfColumns; ++col)
        {
            std::cin >> array[row][col];
        }
    }
    // Some debug output
    for (unsigned int row = 0; row < numberOfRows; ++row)
    {
        for (unsigned int col = 0; col < numberOfColumns; ++col)
        {
            std::cout << array[row][col] << " ";
        }
        std::cout << std::endl;
    }

    // Call the transpose function and get a new dynamically allocated 2d array
    int** arrayTransposed = transpose2dArray(array, numberOfRows, numberOfColumns);

    // Now we have a swapped number of rows and columns
    unsigned int numberOfRowsTransposed = numberOfColumns;
    unsigned int numberOfColumnsTransposed = numberOfRows;

    // Show the transposed output. Use other row and column numbers
    for (unsigned int row = 0; row < numberOfRowsTransposed; ++row)
    {
        for (unsigned int col = 0; col < numberOfColumnsTransposed; ++col)
        {
            std::cout << arrayTransposed[row][col] << " ";
        }
        std::cout << std::endl;
    }
    // And delete the dynamically allocated memory
    for (unsigned int row = 0; row < numberOfRowsTransposed; ++row)
    {
        delete[] arrayTransposed[row];
    }
    delete[] arrayTransposed;

    for (unsigned int row = 0; row < numberOfRows; ++row)
    {
        delete[] array[row];
    }
    delete[] array;

    return 0;
}

Upvotes: 1

Related Questions