1

I am searching for solution in this problem. We have to program a program which can add/multiple unknown amount of matrix. Which means multiplication don't have to be at first position, but you have to do it first due to operand precedence. I have a idea of saving all matrix to an array. But I don't know how to save a matrix(2D array) to an array. We are programming in C. Anyone know a solution or a better solution? Thanks.

4 Answers 4

3

I would probably create a struct representing a matrix, something like: (i use int but it will work with doubles too you just need to change every int, apart from n, to double)

typedef struct m{
    //stores the size of the matrix (assuming they are square matrices)
    //otherwise you can just save the same n for everyone if they have the same size
    int n; 
    int **map;
}matrix;

and then a pointer being an array of those structs, something like the following: (note that i omitted the checks that ensures the allocations will work, you'll need to write them) i use calloc because i like it more since it initializes all the positions to 0 but malloc will work too

// if you already know how many matrices you'll have
int number = get_matrix_number();
matrix *matrices = calloc(number, sizeof(matrix));

// otherwise
int numer = 1;
matrix *matrices = calloc(number, sizeof(matrix));
matrices[number - 1].n = get_matrix_dimension();

// then every time you need to add another matrix
number++;
matrices = realloc(number * sizeof(matrix));
matrices[number - 1].n = get_matrix_dimension();

After that to create the actual matrices you could do:

for (int i = 0; i < number; i++){
    matrices[i].map = calloc(matrices[i].n, sizeof(int));
    for (int j = 0; j < matrices[i].n; j++){
        matrices[i].map[j] = calloc(matrices[i].n, sizeof(int));
    }
}

After all of that to access, let's say, the position (3,5) in the 4th matrix you'll just need to do

int value = matrices[4].map[3][5];

I didn't test it (just wrote it as i think i would've) but i think it should work.

As i said you'll need to add the checks for the mallocs and the frees but i think it's easier to understand than straight triple pointers, especially if you don't have much experience in C (but you have to write more code since you need to create the struct).

The nice part is that this will work for matrices of different size and for non square matrices (provided you don't store just "n" but "n" and "m" to remember how many columns and rows each matrix has).

You could also make the allocation faster by allocating more than what you need when calling realloc (E.G. number * 2) so that you don't need to realloc every time but i think you'll need another variable to store how many free spaces you still have (never done it so this is just what i studied as theory hence i prefeared to do it this way since i'm pretty sure it will work).

P.S. There could be some errors here and there, i wrote it pretty fast without checking too carefully.

Sign up to request clarification or add additional context in comments.

2 Comments

The dereference operator '*' goes with the variable, Not the type. (e.g. matrix *matrices, not matrix* matrices) Why? int* a, b, c; where b and c are certainly Not pointers to int, simply int, but when you attach the '*' to the type, it incorrectly looks as if you are attempting to create the type int*. Don't get me wrong, your approach is fine (although reallocation for the addition of every element is a bit inefficient), it is just the misplaced operator that can cause confusion to new users.
@DavidC.Rankin changed it, to me it's more clear with the dereference near the type but that's just personal preference so i changed it to be more clear for everyone else. As for the reallocation, yeah i wrote that it could be more efficient to allocate something like double the space every time instead of doing it for every matrix, i never had the need to reallocate many times so i'm not really sure what's the best way to do it, hence i prefeared to leave it open for him to decide how to do it.
1

Although your question is still confusing, for that part where you want to save a 2D array to 1D array, the following code can help you .. int n = 10; int array2D[n][n]; int yourArray[n*n];

int i,j,k=0;
for(i = 0; i<n; i++){
    for(j = 0; j<n ;j++){
        yourArray[k++] = array2D[i][j];
    }
}

1 Comment

I want to save it to an array because I need to know the index of it and then possibly can multiple it before addition.
0

You need 3D array for this. Something like double *** arrayOfMatrices.

3 Comments

Oukej a jak s tím pracovat? Trochu víc informací by se šiklo 😃
You can dynamically alocate like this: double *** arrayOfMatrices = (double ***)malloc(arrSize*sizeof(double**));. Then you can assign a matrix double ** matrix to it like this: arrayOfMatrices[i] = matrix. If you're not familiar with dynamic allocation, I suggest you try it first with 1D and 2D array.
Being a 3 star programmer in C isn't a compliment. Rarely, when passing the address of a pointer to pointer to type it is needed, but for all other cases, there is generally a more proper way to accomplish the task.
0

I think that the simplest thing to do, if you want to work with matrices of different shapes, is to declare a struct that holds a pointer to double, which should simulate a 1d array, and the number of rows and columns of the matrix. The main code can declare a pointer to a matrix struct, and this simulates an array of matrices.

When you add a matrix, which I take to be a VLA so that different matrix shapes can easily be handled, the VLA is stored in the 1d simulated array.

Storing the matrix information in a struct this way also makes it easy to verify that matrix operations are defined for the matrices in question (e.g., matrix addition is only defined for matrices of the same shape).

Here is a simple example of how this idea could be implemented. The program defines 3 VLAs and adds them to a list of Matrix structs called matrices. Then the matrices are displayed by reading them from matrices.

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

typedef struct {
    double *array;
    size_t rows;
    size_t cols;
} Matrix;

Matrix * add_matrix(size_t rs, size_t cs, double arr[rs][cs], Matrix *mx, size_t *n);
void show_matrix(Matrix mx);

int main(void)
{
    Matrix *matrices = NULL;
    size_t num_matrices = 0;

    double m1[2][2] = {
        { 1, 2 },
        { 3, 4 }
    };
    double m2[2][3] = {
        { 1, 0, 0 },
        { 0, 1, 0 }
    };
    double m3[3][2] = {
        { 5, 1 },
        { 1, 0 },
        { 0, 0 }
    };

    matrices = add_matrix(2, 2, m1, matrices, &num_matrices);

    matrices = add_matrix(2, 3, m2, matrices, &num_matrices);

    matrices = add_matrix(3, 2, m3, matrices, &num_matrices);

    show_matrix(matrices[0]);
    show_matrix(matrices[1]);
    show_matrix(matrices[2]);

    /* Free allocated memory */
    for (size_t i = 0; i < num_matrices; i++) {
        free(matrices[i].array);
    }
    free(matrices);

    return 0;
}

Matrix * add_matrix(size_t rs, size_t cs, double arr[rs][cs], Matrix *mx, size_t *n)
{   
    Matrix *temp = realloc(mx, sizeof(*temp) * (*n + 1));
    if (temp == NULL) {
        fprintf(stderr, "Allocation error\n");
        exit(EXIT_FAILURE);
    }

    double *arr_1d = malloc(sizeof(*arr_1d) * rs * cs);
    if (arr_1d == NULL) {
        fprintf(stderr, "Allocation error\n");
        exit(EXIT_FAILURE);
    }

    /* Store 2d VLA in arr_1d */
    for (size_t i = 0; i < rs; i++)
        for (size_t j = 0; j < cs; j++)
            arr_1d[i * cs + j] = arr[i][j];

    temp[*n].array = arr_1d;
    temp[*n].rows = rs;
    temp[*n].cols = cs;
    ++*n;

    return temp;
}

void show_matrix(Matrix mx)
{
    size_t rs = mx.rows;
    size_t cs = mx.cols;
    size_t i, j;

    for (i = 0; i < rs; i++) {
        for (j = 0; j < cs; j++)
            printf("%5.2f", mx.array[i * cs + j]);
        putchar('\n');
    }
    putchar('\n');
}

Output is:

1.00 2.00
3.00 4.00

1.00 0.00 0.00
0.00 1.00 0.00

5.00 1.00
1.00 0.00
0.00 0.00

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.