4
\$\begingroup\$

This exercise surprised me a little bit. I did not expect that gcc (GCC 6.3.0 in the MinGW suite) would use the C11 standard by default, which I realised after I read the documentation. Here's the code that compiles without any errors or warnings:

matrix.c

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

void input(int m, int n, int a[m][n])
{
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d, %d : ", i, j);
            scanf("%d", &a[i][j]);
        }
    }
}

void print(int m, int n, int a[m][n])
{
    int i, j;
    for (i = 0; i < m; i++) {
        for (j = 0; j < n; j++) {
            printf("%3d ", a[i][j]);
        }
        printf("\n");
    }   
}

void multiply(int m, int n, int p, int a[m][n], int b[n][p], int c[m][p])
{
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < p; j++) {
            c[i][j] = 0;
            for (int k = 0; k < n; k++) {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
}

int main()
{
    int r1, c1, r2, c2;
    printf("Row and column for matrix #1 :\n");
    scanf("%d %d", &r1, &c1);
    printf("Row and column for matrix #2 :\n");
    scanf("%d %d", &r2, &c2);

    if (r2 != c1) {
        printf("The matrices are incompatible.\n");
        exit(EXIT_FAILURE);
    }

    int mat1[r1][c1], mat2[r2][c2], ans[r1][c2];
    printf("Enter elements of the first matrix.\n");
    input(r1, c1, mat1);
    printf("The elements of the first matrix are :\n");
    print(r1, c1, mat1);
    printf("Enter elements of the second matrix.\n");
    input(r2, c2, mat2);
    printf("The elements of the second matrix are :\n");
    print(r2, c2, mat2);

    multiply(r1, r2, c2, mat1, mat2, ans);
    printf("The product is :\n");
    print(r1, c2, ans);

    return EXIT_SUCCESS;
}

Feedback and criticism on any and all aspects are welcome.

\$\endgroup\$
3
  • \$\begingroup\$ Can this code even work? The functions expect a two-dimensional array, and you pass a one-dimensional to them. This is a tricky part of the C language. Defining a struct helps against that. \$\endgroup\$ Commented Oct 29, 2017 at 11:18
  • 1
    \$\begingroup\$ I personally find this a celebration of progress. Extremely clean and simple thanks to C11. I fail to see how is C98 "solution" better or simpler? \$\endgroup\$
    – DBJDBJ
    Commented Feb 25, 2019 at 6:20
  • \$\begingroup\$ This is a good start. You are using VLA. For larger matrices, you will need to do heap allocation and in any case, you will be better of if you use "real matrices" not "fake matrices" please proceed here ... You are also using VM types. That multiply function is going to work for int matrices of any size (memory permitting) unchanged. That is the key advantage vs using structs as the "answer" below suggests. Please proceed here \$\endgroup\$
    – DBJDBJ
    Commented Apr 9, 2021 at 7:01

1 Answer 1

5
\$\begingroup\$

I suggest you roll an explicit matrix type. For example:

typedef struct matrix_t {
    size_t rows;
    size_t cols;
    int* data;
} matrix_t;

void matrix_t_multiply(matrix_t* left, matrix_t* right, matrix_t* result) {
    ...
}
\$\endgroup\$
3
  • \$\begingroup\$ I've read some posts that propagate against the use of typedef structs. Do they have a valid reason to do so? I personally find this soution elegant. \$\endgroup\$ Commented Oct 30, 2017 at 20:07
  • 2
    \$\begingroup\$ @Astrobleme A matter of taste, and it is said that arguing about such is insane. \$\endgroup\$
    – coderodde
    Commented Oct 30, 2017 at 22:48
  • 2
    \$\begingroup\$ @Astrobleme, you may have been reading reviews of C++ code, where the typedef provides no additional function (the structure tag is automatically also its name in C++, but not in C). \$\endgroup\$ Commented Oct 31, 2017 at 8:22

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.