简体   繁体   中英

How to create a matrix structure in C?

I'm a beginner in C, but I'm currently trying to create a matrix data structure that could be used in different functions without having to explicitly pass the number of columns and number of rows (example: matrixMult(matrix A, matrix B) instead of matrixMult(A, B, rowsA, columnsA, rowsB, columnsB) ). My approach so far has been to declare a struct such as

typedef struct matrix{
    int rows;
    int columns;
    int **data;
}matrix;

And then, to properly allocate the matrix, I'm trying to use the following function

matrix startmatrix(matrix mat,int n_row, int n_col){
    int i=0;
    mat.rows=n_row;
    mat.columns=n_col;

    mat.data=(int **) calloc(n_row,sizeof(int *));

    for(i=0;i<n_row;i++){
        mat.data[i]=(int *) calloc(n_col,sizeof(int));
    }
    return mat;
}

Which (to my understanding) allocates the rows containing the columns, and then allocates memory for the columns, which then contain the actual data.

The above part of the code seems to work fine, however when I try to input some data to the matrix and then visualize it later, eg:

A=startmatrix(A,2,3);
A.data[1,1]=1;
printf("%d",A.data[1,1]);

It returns a warning (assignment makes pointer from integer without a cast) and the number 4 inside the actual matrix.

Can anyone please explain what am I doing wrong?


EDIT: Adding the full code I'm using. So far it just consists of 2 files, mainfile.c and matrix.h. I also understand now (thanks!) that passing mat to startmatrix is useless and that i should use A.data[][] , so I edited the code accordingly. The main file is, so far:

//Mainfile.c
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"


int main(){
    matrix A=startmatrix(2,3); //2 by 3 matrix
    A.data[1][1]=1; /*testing to see if the value 1 is passed to the first cell*/

    printf("\n%d\n",A.rows); //Prints number of rows stored by A
    printf("\n%d\n",A.columns); //Prints number of cols stored by A
    printf("\n%d\n\n",A.data[1][1]);  //Is supposed to print the value stored in the first cell
    return 0;
}

This calls the file "matrix.h", which contains the following (and the following only, so far)

#include <stdlib.h>

typedef struct matrix{
    int rows, columns;
    int **data;
}matrix;

matrix startmatrix(int n_row, int n_col){
    matrix mat;
    int i=0;
    mat.rows=n_row;
    mat.columns=n_col;

    mat.data=(int **) calloc(n_row,sizeof(int *));

    for(i=0;i<n_row;i++){
        mat.data[i]=(int *) calloc(n_col,sizeof(int));
    }
    return mat;
}

So far, that is all the code I used for this problem, nothing more or less. I am reading the suggested answers and comments and trying them out, to see if they work. Thanks for the help, in advance.

You can't access a two dimensional array like that - C doesn't treat it as such, to the compiler it's just a pointer-to-pointer-to-integer. C also doesn't recognise the notation of multiple indexing (a number of indices separated with commas).

You should access the row with A.data[1] , which gives you a pointer to the specific row, and then access the desired item in it - A.data[1][1] .

As a beginner C programmer you should get to know and at least initially avoid complex cases of pointer arithmetic. For the matrix case you can actually do things simple. I took the liberty of adding very basic error detection using assert .

To begin with, use single pointer when possible:

typedef struct matrix{
    int rows;
    int columns;
    int *data;
}matrix;

Adapt your allocation procedure:

matrix startmatrix(int n_row, int n_col){
    assert(n_row>0 && n_col>0);
    matrix mat;
    mat.rows=n_row;
    mat.columns=n_col;
    mat.data=calloc(n_row*n_col,sizeof(int)); /* allocate memory and clear to zero */
    return mat; /* return copy of mat */
}

The prototype of this functions looked a little funny to me so I changed it a bit. It should have the same effect as the old one.

If you want to make the most of the structure, make accessor functions instead of working with the raw array index:

int* matrixcell(matrix mat, int column, int row){
    assert(column < mat.columns && row < mat.rows);
    return &mat.data[row*mat.columns + column]; /* pointer arithmetic */
}
/* example of using it */
*matrixcell(mat, 1, 1) = new_value;

The arithmetic is a very basic way of navigating through 2D data in a 1D array. Try it out on pen and paper, writing does the addresses of each cell. You'll see it makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM