Variable size matrix in C

How can I implement a variable dimensional matrix (int) in C? For clarification, I should be able to add rows and columns in accordance with the facts of the situation (inside the if clause).

Thanks Vi.

+4
source share
6 answers

You can write a reusable component that separates an interface from an implementation. The main decision you must make is to implement a sparse or dense layout.

Assuming a dense scheme, an object can be

in matrix.h

#include <stdio.h> typedef struct matrix { int nrows, ncols, *data; } matrix; matrix* allocate(matrix *mat, int nrows, int ncols); int *cell(const matrix *mat, int row, int col); matrix *addrow(matrix *mat); matrix *addcol(matrix *mat); matrix *print(FILE *f, matrix *mat); 

in matrix.c

 #include "matrix.h" #include <assert.h> #include <stdlib.h> #include <string.h> matrix* allocate(matrix *mat, int nrows, int ncols) { assert(nrows > 0 && ncols > 0); mat->nrows = nrows; mat->ncols = ncols; mat->data = malloc(sizeof(int) * nrows * ncols); return mat; } int *cell(const matrix *mat, int row, int col) { assert(row >= 0 && row < mat->nrows); assert(col >= 0 && col < mat->ncols); return mat->data + row * mat->ncols + col; } matrix *addrow(matrix *mat) { mat->nrows++; mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols); return mat; } /* adding a column it an expensive operation */ matrix *addcol(matrix *mat) { mat->ncols++; mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols); /* shift rows' elements, to make room for last column */ for (int r = mat->nrows - 1; r > 0; --r) { int *dest = mat->data + r * mat->ncols, *orig = mat->data + r * (mat->ncols - 1); memmove(dest, orig, sizeof(int) * (mat->ncols - 1)); } return mat; } matrix *print(FILE *f, matrix *mat) { for (int r = 0; r < mat->nrows; ++r) { for (int c = 0; c < mat->ncols; ++c) fprintf(f, "%4d ", *cell(mat, r, c)); fprintf(f, "\n"); } return mat; } int main_matrix(int argc, char **argv) { matrix m; allocate(&m, 3, 5); for (int r = 0; r < m.nrows; ++r) for (int c = 0; c < m.ncols; ++c) *cell(&m, r, c) = 35; print(stdout, &m); fprintf(stdout, "\n"); addrow(&m); for (int c = 0; c < m.ncols; ++c) *cell(&m, m.nrows - 1, c) = 45; print(stdout, &m); fprintf(stdout, "\n"); addcol(&m); for (int r = 0; r < m.nrows; ++r) *cell(&m, r, m.ncols - 1) = 46; print(stdout, &m); fprintf(stdout, "\n"); // remember to free memory free(m.data); return argc; } 

test output:

  35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 45 45 45 45 45 35 35 35 35 35 46 35 35 35 35 35 46 35 35 35 35 35 46 45 45 45 45 45 46 
+3
source

As I see, you do not want to declare: int arr[5][5] ;

You can use my malloc and realloc . For example, to create a two-dimensional array dynamically:

 int nrows; int ncolumns; scanf("%d %d", &nrows, &ncolumns); int **arr = malloc(nrows * sizeof(int *)); for(i = 0; i < nrows; i++) arr[i] = malloc(ncolumns * sizeof(int)); 

Then up to realloc if you want to resize. The advantage of using realloc is that it automatically takes care of copying values ​​from the original memory locations to a new location in case it cannot expand the memory in the same region.

Note that here it is for a two-dimensional array. If you want to resize it yourself, or if you want to be able to resize, you can link similarly to the above with a different function for each of these cases. Again, this will look a little ugly. But there is no elegant way to do such things in C.

+2
source

Just because C does not support language support for object-oriented ideas, such as encapsulating and hiding information, does not mean that you cannot use them in your code; you just need to work hard to put them into action.

Too much time has passed since I wrote C to be more specific, but Eric Roberts at Stanford taught some excellent C programming techniques. I would recommend you study them.

The idea would be that you would have to redo the memory for the new matrix, copy the old elements into it, initialize the new values, clear the old memory and assign the new matrix to the pointer variable. If you hide all this in a method, the clients of your code will simply call it and will not worry about the magic that you do under it. You do not have to repeat difficulties in several places. You just call one method and do it.

+1
source

Once you know the size, you need to allocate enough space on the heap to accommodate that size. You can allocate space on the heap using malloc or calloc .

For instance:

 #include <stdio.h> #include <stdlib.h> void set_value(int * matrix, int row, int col, int value); int get_value(int * matrix, int row, int col); int main() { int rows = 5; /* arbitrary */ int cols = 3; /* arbitrary */ int * matrix = (int *) calloc(rows * cols, sizeof(int)); if (matrix == NULL) { printf("Error with allocation!\n"); return -1; } set_value(matrix, 0, 0, 5); set_value(matrix, 0, 1, 2); set_value(matrix, 4, 2, 1); printf("%d\n", get_value(matrix, 0, 0)); printf("%d\n", get_value(matrix, 0, 1)); printf("%d\n", get_value(matrix, 4, 2)); free(matrix); return 0; } void set_value(int * matrix, int row, int col, int value) { *(matrix + col * sizeof(int) + row) = value; } int get_value(int * matrix, int row, int col) { return *(matrix + col * sizeof(int) + row); } 

Just make sure you always verify that the call to malloc or calloc works, and that you always free up memory later free .

If you need to resize the matrix, you will either have to use realloc or request more space on the heap, copy your values ​​and free up older memory.

+1
source

I think you can create a buffer with dynamic allocation of memory "malloc"

0
source

I just wrote ... I hope it works.

 int **matrix; int m=10; int n=10; int i,j; matrix = (int)** malloc (m*sizeof(int*)); for(i=0;i<m;i++){ matrix[i]= (int)* malloc (n*sizeof(int)); for(j=0;j<n;j++) matrix[i][j] = (10.0*rand()); } free(matrix); 
-2
source

Source: https://habr.com/ru/post/1403238/


All Articles