4

The input to this function is supposed to be a pair of integers - size of matrix - followed by col*row integers. It looks something like this

2 3
76 98 -31
30 30 32

This is the code I've written so far. It works for row and column sizes but when I try to pass pointer to the read matrix, it crashes. I'm confused about how I'm supposed to pass the int** matrix argument into the function. (I've seen an example of similar function at the lecture, so I'd prefer a solution using the double pointer.

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

int load_matrix(int *ro,int *co, int **matrix);

int main(int argc, char* argv[]) {
    int row = 3;
    int col = 3;
    int *ro = &row;
    int *co = &col;
    //int matx[1];
    int **matrix; //= matx[0];
    load_matrix(ro,co,matrix);
}

int load_matrix(int* ro,int* co, int** matrix) {
    int rows, cols;
    if(scanf("%d %d",&rows,&cols)==2) {
        int *mat = malloc(sizeof(int)*rows*cols);
        int read=0;
        for(int i = 0; i<rows &&read>=0; i++) {
            for(int j = 0; j<cols && read >=0; j++) {
                if(scanf("%d", &(mat[i*cols+j]))!=1) {
                    read = -1;
                } else {
                    read++;
                }
            }
        }
        if(read == (rows*cols)) {
            *ro = rows;
            *co = cols;
            **matrix = mat; --- this crashes the program
        } else {
            free(mat);
            *matrix = 0;
        }
    } else {
        return 100;
    }
    return 0;
}

As marked in the code, the part where it crashes is when I try to assign the pointer int** matrix a new value to the address where the read matrix is allocated. How am I supposed to work with the pointers here?

sg7
  • 6,108
  • 2
  • 32
  • 40
user145760
  • 124
  • 9

3 Answers3

1

The immediate problem is that you are trying to dereference an uninitialized pointer matrix from main. Judging from the flow of your program, you should call your function like this:

int main(int argc, char* argv[]){
    int row;
    int col;
    int *matrix;
    if (load_matrix(&row, &col, &matrix) != 0) {
        // Report an error
        return -1;
    }
    printf("Got a matrix %d by %d\n", row, col);
    // ... 
    // At the end you should free the matrix
    free(matrix);
    return 0;
}

Note that you can pass pointer expressions for &row and &col directly, without making pointer variables for them. Same goes with matrix, which in your implementation is a flat array of integers, with your own 2D-addressing scheme overlaid on it.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

you cannot do that. The problem is that you cannot allocate a bidimensional array and use it if you have not fixed at compilation time the sizes of both dimensions. To be able to do that and continue to use the matrix with the subindex notation, you need to use array of pointers to arrays of integers:

#include <stdlib.h>
#include <stdio.h>
int **load_matrix(int *colsref, int *rowsref)
{
    int cols, rows, r, c;

    scanf("%d%d", &rows, &cols);
    int **res = malloc(sizeof (int *) * rows); // array of pointers to rows.
    if (!res) return NULL; // no memory.
    for(r = 0; r < rows; r++) {
        res[r] = malloc(sizeof (int) * cols); // each row.
        if (!res[r]) {
            int i, j; // free all allocated memory
            for (i = 0; i < r; i++) free(res[i]);
            free(res);
            return NULL;
        }
        for (c = 0; c < cols; c++)
            scanf("%d", &res[r][c]);
    }
    *colsref = cols; *rowsref = rows;
    return res;
}

Now you can refer to the matrix cells as mat[row][col]. You'll need a similar model to free the matrix. I've changed the interface a little to make more readable the code: (complete example)

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

int **load_matrix(int *rowsref, int *colsref)
{
    int cols, rows, r, c;

    scanf("%d%d", &rows, &cols);
    int **res = malloc(sizeof (int **) * rows); // array of pointers to arrays.
    if (!res) return NULL;
    for(r = 0; r < rows; r++) {
            res[r] = malloc(sizeof (int *) * cols);
            if (!res[r]) {
                    int i, j; // free all allocated memory
                    for (i = 0; i < r; i++) free(res[i]);
                    free(res);
                    return NULL;
            }
            for (c = 0; c < cols; c++)
                    scanf("%d", &res[r][c]);
    }
    *colsref = cols; *rowsref = rows;
    return res;
}

void print_matrix(int **matrix, int rows, int cols)
{
    int r, c;
    printf("%d %d\n", rows, cols);
    for (r = 0; r < rows; r++) {
            for (c = 0; c < cols; c++)
                    printf("\t%d", matrix[r][c]);
            printf("\n");
    }
}

void free_matrix(int **matrix, int rows)
{
    int r;
    for (r = 0; r < rows; r++)
            free(matrix[r]);
    free(matrix);
}

int main()
{
    int **matrix, rows, cols;

    matrix = load_matrix(&rows, &cols);
    print_matrix(matrix, rows, cols);
    free_matrix(matrix, rows);
}
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
1

There are 2 mistakes in your code:

  • You should define matrix in main as int *matrix;, not a double pointer, yet you should pass the address of matrix to the load_matrix function.

  • in load_matrix, you should store the mat pointer simply as *matrix = mat; instead of **matrix = mat;

Here is a corrected and simplified version:

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

int load_matrix(int *ro, int *co, int **matrix) {
    int rows, cols;
    if (scanf("%d %d", &rows, &cols) == 2) {
        int *mat = malloc(sizeof(int) * rows * cols);
        int read = 0;
        for (int i = 0; i < rows && read >= 0; i++) {
            for (int j = 0; j < cols && read >= 0; j++) {
                if (scanf("%d", &mat[i * cols + j]) != 1) {
                    read = -1;
                } else {
                    read++;
                }
            }
        }
        if (read == rows * cols) {
            *ro = rows;
            *co = cols;
            *matrix = mat;
        } else {
            free(mat);
            *matrix = NULL;
        }
        return 0;
    } else {
        return 100;
    }
}

int main(int argc, char *argv[]) {
    int row, col, *matrix;
    load_matrix(&row, &col, &matrix);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189