Your current attempt creates a local array, then fills it, then tries to return a pointer to it. It won't work, because the array, being local, vanishes when the function returns. The pointer you try to return points to somewhere in the stack, where the array used to be.
You need to allocate the memory needed for the matrix dynamically, using malloc().
There are ways to do it without structures, but I really recommend you dive straight into it, and use a proper structure for this, so you can support any size matrices. For example:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
struct matrix {
int rows;
int cols;
double *element;
};
/* Read a matrix from a file or stream,
* into the specified matrix.
* Returns 0 if success, errno error code otherwise.
*/
int fread_matrix(struct matrix *const m, FILE *const input)
{
int rows, cols;
size_t n, i;
/* Invalid parameters? */
if (!m || !input)
return errno = EINVAL;
/* Clear the matrix. */
m->rows = 0;
m->cols = 0;
m->element = NULL;
/* Already a read error in input? */
if (ferror(input))
return errno = EIO;
/* Read the number of rows and columns in the matrix. */
if (fscanf(input, " %d %d", &rows, &cols) != 2)
return errno = ENOENT; /* Bad data in input; yields "no such file or directory" error */
/* Sane matrix size? */
if (rows < 1 || cols < 1)
return errno = ENOENT; /* No, yields "no such file or directory" error */
n = (size_t)rows * (size_t)cols;
/* Allocate matrix elements. */
m->element = malloc(n * sizeof (*m->element));
if (!m->element)
return errno = ENOMEM; /* Not enough memory error. */
/* Read matrix elements in row-major order (C array order). */
for (i = 0; i < n; i++)
if (fscanf(input, " %lf", &(m->element[i])) != 1) {
free(m->element);
m->element = NULL;
return errno = ENOENT; /* Invalid data, yields "no such file or directory" error. */
}
/* Done. */
m->rows = rows;
m->cols = cols;
/* Success. */
return 0;
}
static inline double matrix_get(const struct matrix m, const int row, const int col)
{
if (row >= 0 && col >= 0 && row < m.rows && col < m.cols)
return m.element[row * m.cols + col];
else
return 0.0;
}
static inline double matrix_set(struct matrix m, const int row, const int col, const double value)
{
if (row >= 0 && col >= 0 && row < m.rows && col < m.cols)
return m.element[row * m.cols + col] = value;
else
return 0.0;
}
#define ELEMENT(m, row, col) ((m).element[(col) + (row)*(m).cols])
Because this is C, rows and columns are numbered from 0 onwards.
Because the matrix elements are in row major order, the same order they would be in a two-dimensional C array, the element at row row, column column, is at index row*columns+column.
The two helper functions, matrix_set() and matrix_get() verify the row and column before trying to access the element. If they are outside the matrix, both functions return zero.
If you know you have valid row and column numbers, then you can use the ELEMENT(matrix, row, column) preprocessor macro to access an element.
Here is an example program using the above:
Code:
int main(void)
{
struct matrix a, b;
int row, col;
/* Read matrix a from standard input. */
if (fread_matrix(&a, stdin)) {
fprintf(stderr, "Could not read matrix a from standard input.\n");
return 1;
} else
fprintf(stderr, "Read matrix a: %d rows, %d columns.\n", a.rows, a.cols);
/* Read matrix b from standard input. */
if (fread_matrix(&b, stdin)) {
fprintf(stderr, "Could not read matrix b from standard input.\n");
return 1;
} else
fprintf(stderr, "Read matrix b: %d rows, %d columns.\n", b.rows, b.cols);
/* Are the matrices the same size? */
if (a.rows == b.rows && a.cols == b.cols) {
fprintf(stderr, "Adding matrix b to matrix a.\n");
for (row = 0; row < a.rows; row++)
for (col = 0; col < a.cols; col++)
ELEMENT(a, row, col) += ELEMENT(b, row, col);
} else
fprintf(stderr, "Matrix b is not the same size as matrix a.\n");
/* Print the matrix a. */
fprintf(stderr, "Matrix a: %d rows, %d cols\n", a.rows, a.cols);
fflush(stderr);
for (row = 0; row < a.rows; row++) {
/* All but last column: */
for (col = 0; col < a.cols - 1; col++)
printf("%.16g ", ELEMENT(a, row, col));
/* Last column: */
printf("%.16g\n", ELEMENT(a, row, a.cols - 1));
}
return 0;
}
If you intend to do more complicated stuff with your matrices, I do recommend using GNU Scientific Library.
If you are doing this to get in-depth knowledge about matrix operations, then writing your own implementations of the matrix operations is certainly useful; in that case,
Code:
struct data {
struct data *chain;
long references;
size_t size;
double data[];
};
struct matrix {
long rows;
long cols;
size_t rowstep;
size_t colstep;
double *element;
struct data *owner;
};
where the matrix data is stored in a reference-counted objects maintained in a singly-linked list, will be orders of magnitude more powerful: your matrices can be dynamic, real-time views to any regular rectangular section of any other matrix. Transpose is simply swapping rows and columns; no data needs to be changed. The same for mirroring and rotation.
The code needed to manage the reference-counted objects is pretty advanced stuff, although it makes the code that uses them much easier to write. For one, as long as you dispose of each matrix after you no longer need it, the data objects will be managed correctly (freed after they're no longer needed), without the programmer having to worry about which matrices are actually just views to other matrices, and which matrices have original data.
So, this gets to pretty advanced level. I've just found it to be amazingly useful when developing algorithms based on matrices. (I find BLAS and LAPACK interfaces rather archaic.)