3

Well, I am doing matrix multiplication and I need to make an m x n array and a p x q array.
However, I do not know how to.

Here is my program which prints correct output when I feed in values manually:

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
    /*
        Rows and columns for matrices.
    */
    int m , n; // rows and columns of the first matrix
    int p , q; // rows and columns of the second matrix

    /*
        1st matrix is a 2x3 matrix
    */
    m = 2;
    n = 3;

    /*
        2nd matrix is a 3x2 matrix
    */
    p = 3;
    q = 2;


    /*
        Create the matrices.
        Give them values.
    */
    int matrix1[m][n] = {
                            {2,3,4},
                            {5,6,7}
                        };
    int matrix2[p][q] = {
                            {1,7},
                            {3,9},
                            {5,11}
                        };

    /*
        Check if we can multiple the matrices.
        For matrix multiplication,
        the number of COLUMNS of FIRST matrix must be equal to
        the number of ROWS of SECOND matrix
    */
    if(n==p){
        /*
            Create a new matrix.
            The resulting matrix will have M rows and Q columns.
            That is, the matrix is a MxQ matrix.
        */
        int matrix3[2][2]; 

        /*
            We need three loops so we have 3 variables.
        */
        int i = 0; // iterates over matrix1 rows
        int j = 0; // iterates over matrix1 columns
        int k = 0; // iterates over matrix2 rows
        int l = 0; // iterates over matrix2 columns


        while(i < m){
            l = 0;
            while(l < q){
                int element = 0;
                while(j < n && k < p){
                    element += matrix1[i][j] * matrix2[k][l];
                    matrix3[i][l] = element;
                    j++;
                    k++;
                }
                printf("\t%d",element);
                l++;
                j = 0;
                k = 0;
            }
            printf("\n");
            i++;
        }

    }else{
        printf("Matrices can not be multiplied");
    }
}  

The matrix declaration gets flagged as an error. How do I solve it?

An SO User
  • 24,612
  • 35
  • 133
  • 221
  • Does your compiler *support* VLAs ? And check your error. VLAs, even if supported, do not support initializers. – WhozCraig Sep 21 '13 at 19:46
  • @WhozCraig What ? :-/ VLA = Variable Length Array. I use Dev-C++ which uses GCC V 4.71 – An SO User Sep 21 '13 at 19:46
  • 3
    There isn't even a *need* for VLAs in this code. the matrices can be const-sized. – WhozCraig Sep 21 '13 at 19:47
  • @WhozCraig yes, but .. I just need to show the instructor that I can do it for any given input matrix :) Easy in Java, you know :) – An SO User Sep 21 '13 at 19:47
  • If you're doing this for any given input you better have an alternative method for populating those arrays than static initialization. But identify the original error message please. *exactly* what does is say (update the question please, to include it). It is likely as I described, VLAs don't support initialization (assuming your compiler supports VLAs, which is testable via macro). – WhozCraig Sep 21 '13 at 19:48
  • @LittleChild: Because in java your arrays are heap allocated – Ed S. Sep 22 '13 at 10:20

3 Answers3

3

How do I solve it?

In first place, by not using a VLA. You don't need VLAs for this particular task.

As to what the actual problem is: variable-length arrays cannot be initialized. You have to assign to their elements one-by-one or use some mass-"assignment" technique such as memcpy().

  • hi there, Carbonic Acid. I figured that out. I cannot use VLA :( – An SO User Sep 21 '13 at 19:49
  • @LittleChild Um, what I'm saying is that it doesn't matter whether or not you can -- you simply don't need them. Declare your array as `int mat[2][3]` and boom, you can suddenly initialize it. –  Sep 21 '13 at 19:50
  • I know I can if I do it that way. I can do that using Macros, too. But same as punching in values myself :) – An SO User Sep 21 '13 at 19:51
  • @L Is your real problem getting user input then? –  Sep 21 '13 at 19:56
  • @LittleChild I beleive you have a [XY](http://meta.stackexchange.com/q/66377/232397) – P0W Sep 21 '13 at 20:21
1

Is it an option to use C99?

Variable Length Arrays

This is 100% valid in C99:

  int m = 2;
  int n = 3;

  int matrix1[m][n];
Cacho Santa
  • 6,846
  • 6
  • 41
  • 73
  • I do not know. Data Structures is being taught in C in the Uni so my knowledge is limited to what I need to write basic programs :) – An SO User Sep 21 '13 at 19:50
  • C99 is the last version of C, and it supports VLA. I believe you should ask @LittleChild. Updated my answer with a link of C99 description. – Cacho Santa Sep 21 '13 at 19:53
  • 3
    "This is 100% valid in C99" - no, it isn't, one cannot initialize VLAs. Only statically-sized arrays can be initialized. –  Sep 21 '13 at 19:54
  • 1
    Expect a stack overflow as soon as you operate on real world sized matrices. VLAs are a bad fit for this problem. – David Heffernan Sep 21 '13 at 20:09
1

'Native' variable length arrays are, according the the current c standard, an optional language construct. You'll have to check your compiler documentation to determine if the compiler you're using has any support for variable length arrays.

Prior to C99 variable length arrays need to be explicitly allocated on the heap and accessed via a pointer. For the matrix problem you have two options.

The first is to allocate an array with sufficient storage, and calculate the correct indices when you need to read or modify a matrix element. For example:

int* matrix_storage = malloc( sizeof( int ) * matrix_width * matrix_height );
// set row 0, column 1 to 0
matrix_storage[ ( 0 * matrix_width ) + ( 1 % matrix_width ) ] = 0; 

Alternatively you can allocate an array of pointers to each row or column:

int** rows = malloc( sizeof( (int*) ) * matrix_height );
for( int i = 0; i < matrix_height; ++i )
{
    rows[i] = malloc( sizeof(int) * matrix_width );
}
row[0][1] = 0; // set row 0, column 1 to 0

This implementation wastes some memory, regardless of the implementation you choose consider using functions and the struct keyword to hide the implementation from the driver code (the code that is actually mutating or reading the matrices).

Some notes: I have used c99 for loop syntax, with older compilers the int i variable will need to be declared outside the for loop. Also note that if your matrix size can be determined at compile time (IE does not rely on user input) you don't need the overhead of malloc and can hard code your array size. The example code you have posted does not require dynamic allocation.

Dan O
  • 4,323
  • 5
  • 29
  • 44