0

I'm new to C programming. I'm trying to create some code that allows me to resize a Matrix of m x n. Nonetheless, whenever it gets to the realloc function it gives an exception and terminates the execution on this line:

newMatrix = realloc(matrix, sizeof(int *)**m);

I'm looking for some advice on how to make it work, or what I'm doing wrong. Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void printMatrix(int** p,int m,int n);
int **createMatrix(int m,int n);
void obtainMatrixDim(int* m,int* n);
void printOptnMenu();
int** optionsMenuSwitch(int op,int** matriz,int *m,int *n);
void menu(int** matriz,int m,int n);

int main(){

    int **matrix,m,n;
    obtainMatrixDim(&m,&n);
    matrix=createMatrix(m,n);
    menu(matrix,m,n);
    
    return 0;
}

//Functions

void obtainMatrixDim(int* m,int* n){
    printf("Provide the number of rows of the Matrix:\t");
    scanf("%d",m);
    printf("Provide the number of columns of the Matrix:\t");
    scanf("%d",n);
}

int **createMatrix(int m,int n){

    int **matrix,i,j;
    srand((unsigned)time(NULL));
    matrix=(int**)malloc(m*sizeof(int*));
    for(i=0;i<m;i++){
        matrix[i]=(int*)malloc(m*sizeof(int));
    }
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            matrix[i][j]=rand()%999+1;
        }
    }
    return matrix;
    
}

void menu(int** matrix,int m,int n){
    int op;
    do{
        printOptnMenu();
        scanf("%d",&op);
        matrix=optionsMenuSwitch(op,matrix,&m,&n);
    }while(op!=3);
}
void printOptnMenu(){
    printf("\nSelect an option:\n");
    printf("\n1.Resize the Matrix\n");
    printf("\n2.Print the Matrix\n");
    printf("\n3.Exit\n");
    printf("\n\t:");
}
int** optionsMenuSwitch(int op,int** matrix,int* m,int* n){
    int **newMatrix,l=0;
    switch(op){
        case 1:{
            printf("\nProvide the new size of rows and columns, in that order.\n");
            printf("\nIf you reduce the size you will loose information.\n");
            printf("\nRows:");
            scanf("%d",m);
            printf("\nColumns:");
            scanf("%d",n);
            //Reallocating rows
            newMatrix = realloc(matrix, sizeof(int *)**m);
            if(newMatrix==NULL){
                return NULL;
            }
            //Reallocating columns
            for(l=0; l<*n; ++l){ 
                *(newMatrix+l) = realloc(*(newMatrix+l), sizeof(int)**n); 
            } 

            return newMatrix;
            break;
        }
        case 2:{
            printMatrix(matrix,*m,*n);
            break;
        }
        case 3:{
            printf("\n<<< Bye >>>");
            break;
        }
        default:printf("Please select a valid menu option.\n");break;
    }
}

void printMatrix(int** p,int m,int n){
    int i,j;
printf("\nThe created matrix is:\n\n");
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            printf(" %d ",p[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}
Vlad GAG
  • 1
  • 1

1 Answers1

0

The main problem with your code is that the optionsMenuSwitch is declared as returning an int ** – but it only does so in the case 1: block. In all other cases, no return value is specified, so you have undefined behaviour.

Thus, in the loop in your menu function, the matrix=optionsMenuSwitch(op,matrix,&m,&n); line will replace the matrix pointer with something that is "who knows what", and any subsequent operations on that (such as an attempt to reallocate it or its elements) will cause completely unpredictable behaviour (most likely resulting in a crash).

That optionsMenuSwitch function should return its given matrix argument in all cases other than the reallocation (case 1); so, just add a return matrix; line to the end of that function.

Note that enabling compiler warnings would have helped you spot this error! For example, MSVC gives the following for your code:

warning C4715: 'optionsMenuSwitch': not all control paths return a value

Another problem is that, in the for (l = 0; l < *n; ++l) ... loop (in the same function, and which should run to *m rather than *n), you are (when increasing the number of rows) using uninitialized values as arguments to the realloc call when using the 'added' rows (note that realloc does not zero-initialize any new memory it allocates); so, you also need to set those new row pointers to NULL before that loop. Here is a possible 'fixed' version of your optionsMenuSwitch function, with comments added on the parts I have changed:

int** optionsMenuSwitch(int op, int** matrix, int* m, int* n) {
    int** newMatrix, l = 0;
    int oldM = *m; // Save old value of m
    switch (op) {
    case 1: {
        printf("\nProvide the new size of rows and columns, in that order.\n");
        printf("\nIf you reduce the size you will loose information.\n");
        printf("\nRows:");
        scanf("%d", m);
        printf("\nColumns:");
        scanf("%d", n);
        //Reallocating rows
        newMatrix = realloc(matrix, sizeof(int*) * *m);
        if (newMatrix == NULL) {
            return NULL;
        }
        for (l = oldM; l < *m; ++l) newMatrix[l] = NULL; // Set new row pointers to NULL!
        //Reallocating columns
        for (l = 0; l < *m; ++l) { // Should be *m here, not *n !!
            newMatrix[l] = realloc(newMatrix[l], sizeof(int) * *n);
        }
        return newMatrix;
        // No need for a "break" here!
    }
    case 2: {
        printMatrix(matrix, *m, *n);
        break;
    }
    case 3: {
        printf("\n<<< Bye >>>");
        break;
    }
    default:printf("Please select a valid menu option.\n"); break;
    }
    return matrix; // Here, we MUST return the 'old' matrix pointer!
}

On another point regarding your code, maybe read Do I cast the result of malloc?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83