Reputation: 4664
I am stuck at the very basics. It's not homework, I'm just presenting the problem in a simplistic way.
I need a matrix print function, and the matrix is passed as an argument along with row and col count information. The matrix is allocated on the stack.
In function prototype mentioned below MAT_COL is a compile time define.
void matrix_print(uint8_t (*mat)[MAT_COL], int row, int col)
and print matrix elements as
print mat[i_row][i_col];
The approach will not work if I have multiple matrix with different sizes i,e "MAT_COL" is no more available.
One possible way out would be
void matrix_print(uint8_t *in_mat, int row, int col)
{
uint8_t (*mat)[col] = in_mat; // typecast "col" is an arg
// access them as eariler
print mat[i_row][i_col];
}
Any problems with this approach ? What is the standard solution to this problem in C.
Upvotes: 0
Views: 2621
Reputation: 1329
I have made an "ultimate" solution to this problem in gcc C11/C99 using these links:
http://c-faq.com/aryptr/dynmuldimary.html
http://c-faq.com/aryptr/ary2dfunc3.html
//compile with gcc --std=c11 program.c
#include <stdio.h>
#include <stdlib.h>
#define MV(array, ncolumns, i, j) array[i * ncolumns + j]
#define MX 9
#define MY 14
void input_matrix(int row, int column, double matrix[row][column]);
void print_matrix(int row, int column, double matrix[row][column]);
int main()
{
int i=MX, j=MY;
printf("Generate input values and print matrices with functions fn(int w, int k, double matrix[w][k]) (in C99 and C11)\n");
double matrix1[i][j];
input_matrix(MX,MY,matrix1);
printf("matrix static\n");
print_matrix(MX,MY,matrix1);
double **matrix2;
matrix2=malloc(MX*sizeof(double*));
matrix2[0] = (double *)malloc(MX*MY*sizeof(double));
for(i = 1; i < MX; i++)
matrix2[i] = matrix2[0]+i*MY;
input_matrix(MX,MY,(double (*)[])(*matrix2));
printf("matrix two times allocated one for pointers, the second for data (double (*)[])(m[0])\n");
print_matrix(MX,MY,(double (*)[])(matrix2[0]));
free(*matrix2);
free(matrix2);
double *matrix3;
matrix3=malloc(MX*MY*sizeof(double));
input_matrix(MX,MY,(double (*)[])matrix3);
printf("matrix alocated as twodimensional array\n");
print_matrix(MX,MY,(double (*)[])matrix3);
free(matrix3);
j=MY;
double (*matrix4)[j];
matrix4 = (double (*)[])malloc(MX * sizeof(*matrix4));
input_matrix(MX,MY,matrix4);
printf("matrix alocated as an array of pointers to arrays m = (double (*)[])malloc(MX * sizeof(*m))\n");
print_matrix(MX,MY,matrix4);
free(matrix4);
printf("\nThe End!\n");
return 0;
}
void input_matrix(int row, int column, double matrix[row][column]){
for(int i=0; i<row; i++){
for(int j=0; j<column; j++)
matrix[i][j]=i+1;
}
}
void print_matrix(int row, int column, double matrix[row][column]){
for(int i=0; i<row; i++){
for(int j=0; j<column; j++)
printf("%.2lf ", matrix[i][j]);
printf("\n");
}
}
Upvotes: 1
Reputation: 6707
I think you could go for a structure to help yuo with handling the type. If the type is relevant to your Design you should make it explicit.
The following is an Ansi-C Version since you wrote C/C++ as a tag. In C++ you would make your matrix a class.
typedef struct
{
int * data;
int IsAllocated;
unsigned row_max;
unsigned col_max;
} Matrix;
void Matrix_construct(Matrix * m, int cols, int rows);
void Matrix_destruct(Matrix * m, int cols, int rows);
static int Private_GetElement(Matrix * m, unsigned col, unsigned row, int * element);
void Matrix_print(Matrix * m);
void Matrix_construct(Matrix * m, int cols, int rows)
{
m->col_max = cols;
m->row_max = rows;
m->data = (int*) malloc(sizeof(int) * cols * rows);
m->IsAllocated = 1;
}
void Matrix_destruct(Matrix * m, int cols, int rows)
{
m->col_max = 0;
m->row_max = 0;
if(m->IsAllocated)
{
free(m->data);
m->IsAllocated = 0;
}
}
static int Private_GetElement(Matrix * m, unsigned col, unsigned row, int * element)
{
int e = 0;
if(m && element && col < m->col_max && row < m->row_max && m->IsAllocated)
{
*element = m->data[col + row * m->col_max];
}
else
{
e |= 1;
}
return e;
}
void Matrix_print(Matrix * m)
{
unsigned col, row;
int element;
for( col = 0; col < m->col_max; ++col)
{
for( row = 0; row < m->row_max; ++row)
{
if(!Private_GetElement(m, col, row, &element))
{
printf("%i", element);
}
}
printf("\n");
}
}
If you allocate different sizes in Matrix_construct
the printing would still work since Matrix_print
uses the maximum values that are stored in the structure.
Using different sizes would lead to changing the structure in the above example, the Matrix_print
should still work as expected.
The example was edited to show how dynamic allocation of variable sizes would look like.
Upvotes: 0
Reputation: 182
C99 supports the following way of function declaration:
void matrix_print(int row, int col, uint8_t in_mat[row][col])
Upvotes: 3
Reputation: 9930
I corrected your typecast from an int
to a uint8_t
so the following should indeed work.
void matrix_print(uint8_t *in_mat, int row, int col)
{
uint8_t (*mat)[col] = (uint8_t (*)[col])in_mat;
// access them like mat[y][x];
}
But if you're trying to avoid typecasts where available (which may or may not be good practice), you could implement it with offsets like so
void matrix_print(uint8_t *in_mat, int row, int col)
{
// access them like mat[x + y*col];
}
Upvotes: -1