0
#include <stdio.h>

int main()
{
    int matrix;
    printf("ENTER NUMBER OF MATRICES\n");
    scanf("%d", &matrix);
    getchar();
    int row[matrix], column[matrix];

    for (int m = 0; m < matrix; m++) {
        printf("ENTER NUMBER OF ROWS IN %d MATRICE\n", m + 1);
        scanf("%d", &row[m]);
        getchar();
        printf("ENTER NUMBER OF column IN %d MATICE\n", m + 1);
        scanf("%d", &column[m]);
        getchar();
        int x[m][row[m]][column[m]];
        int g = 1;

        printf("ENTER ALL ELEMENT LEFT TO RIGHT\n");
        for (int j = 0; j < row[m]; j++) {
            for (int u = 0; u < column[m]; u++) {
                printf("%d\n", g);
                scanf("%d", &x[m][j][u]);
                g = g + 1;
            }
        }
        for (int k = 0; k < row[m]; k++) {
            printf("|");
            for (int l = 0; l < column[m]; l++) {
                printf("%d", x[m][k][l]);
                if (l < column[m] - 1) {
                    printf("  ");
                }
            }
            printf("|");
            printf("\n");
        }
    }
    return 0;
}

OUTPUT:

 ENTER NUMBER OF MATRICES
 1
 ENTER NUMBER OF ROWS IN 1 MATRICE
 1  
 ENTER NUMBER OF column IN 1 MATICE
 2
 ENTER ALL ELEMENT LEFT TO RIGHT
 1 // COUNTING JUST FOR USER
 3 // INPUT 1
 2  // COUNTING
 4  // INPUT 2
 3     //WHY IS IT ASKING ME THIRD ELEMENT WHEN I HAVE SET SIZE OF 
  MATRIX TO BE 1-2
2    // INPUT 3
|3  4  2|


 EXPECTATIONS:
 ENTER NUMBER OF MATRICES
   1
 ENTER NUMBER OF ROWS IN 1 MATRICE
 1
 ENTER NUMBER OF column IN 1 MATICE
 2
 ENTER ALL ELEMENT LEFT TO RIGHT
 1
 3
 2
 4
 |3  4|

HERE AS YOU CAN SEE I GIVE ROWS AND COLUMN TO BE 1-2 BUT STILL MATRIX SIZE IS 1 ROW AND 3 COLUMN FOR SOME REASON THE THE FIRST INPUT GIVE TO MY MATRIX IS BEING SET AS NO. OF TIMES FOR LOOP SHOULD RUN FOR AND NO. OF COLUMN IN MATRIX

i have made a program with matrix however 'for' loop is running different from my expectations i could not understand what value is 'for' loop taking as input to run for , i have managed to figure that for some reason the first value in 'for' loop's scanf is what is setting no. of columns for matrix and determining the turns the loop is going to run for. since i could not figure solution to my problem i request you to help me resolve this error.

mch
  • 9,424
  • 2
  • 28
  • 42
vatsal
  • 11
  • 6
  • 2
    Be clear about your expectation. What input are you providing? What output are you expecting? – Retired Ninja May 24 '23 at 08:04
  • 2
    Side note: Proper indentation would improve readability tremendously, so maybe you might want to adjust? Tip: Use the auto-formatting tool provided by your IDE (you are using one, are you?) to do so... – Aconcagua May 24 '23 at 08:11
  • Your one character names are not a good choice, there's no relation in the name and the purpose they serve for. Better chose speaking names like e.g. `rows`, `rowCounts` or `numbersOfRows` or even `nRows` instead of `a`. – Aconcagua May 24 '23 at 08:13
  • You handle then entire matrix code within the loop, you do not need those arrays `a` and `b` anyway, just two ordinary `int`s *within* the loop body then... Assuming you have done so (leaving unlucky names `a` and `b`), then `int x[m][a][b]` produces a three-dimensional array – are you sure this is what you intended (the original code produces the equivalent)??? – Aconcagua May 24 '23 at 08:17
  • 1
    You might want to try a [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems?noredirect=1&lq=1) to see life what your code actually is doing... – Aconcagua May 24 '23 at 08:24
  • 1
    Just a recommendation: `printf("%6d", matrix[r][c])` would care for proper alignment of the matrix entries up to 5 digits and a minus sign (or 6 digit positive numbers) – otherwise your output gets pretty scattered if the numbers contain more than one digit. You might possibly be fine with less digits or even need more, depending on the inputs you expect, or you could even calculate dynamically – and then have `printf("%*d", digits, matrix[r][c])`! – Aconcagua May 24 '23 at 08:30
  • 1
    Oh, my... Took me a while, *but*: You are producing a 3D array with `int x[m][a][b]`, and then you access it with `x[m][...][...]` – but `x[m]` is *out of bounds*! You produce *undefined behaviour* and it's pretty likely that you are accidentally overwriting your arrays `a` and `b` or at least one of. – Aconcagua May 24 '23 at 08:43
  • What do you think does `int x[m][row[m]][column[m]];` do? Especially when `m=0` in the first iteration of the loop. – mch May 24 '23 at 08:45
  • `printf("|"); printf("\n");` – honestly you can have a simple `printf("|\n")`, that's more efficient, or `puts("|")` which adds a newline on its own or even (still more efficient) `putchar('|'); putchar('\n')`; – Aconcagua May 24 '23 at 08:56
  • thank you aconcagua and jabberwocky for you suggestion also i will keep in mind not to use caps Lock and use puts("|") for efficient code however i could not understand in which line are my code overwriting each other and code is going out of bounds, i googled and found out 3-d matrix starts with 0 hence i give m=0 for first matrix and kindly suggest ways to make this work. – vatsal May 24 '23 at 09:29

1 Answers1

0

The problem in your loop lies here:

int x[m][row[m]][column[m]];
// ...
scanf("%d", &x[m][<whatever>][<whatever>]);

This code first produces a three-dimensional array containing m matrices each with row[m] rows and column[m] columns and later on accesses this array out of bounds by x[m] – valid indices are in the range of [0; m-1], note especially: m not included! You don't actually don't even produce any matrices at all for m == 0 (zero sized arrays can be used in a struct to produce flexible array members...).

Accessing arrays out of bounds is undefined behaviour, so just anything might happen including your programme running as expected (on some lucky input), your programme crashing or (worst) showing unexpected behaviour as you experienced.

What happens under the hoods is that – as obviously operating on an architecture with top-down stack – the array row is placed at some high memory address, column placed in front of row (some lower memory address) and finally x on front of column. Then when accessing x out of bounds you access some memory address higher to the one of x, and guess, there are the arrays row and column. Thus by writing to x out of bounds you accidentally change the values in row and column or at least one of and thus change the loop limits, resulting in the behaviour you see (you might experiment with other matrix values and observe how the behaviour changes...).

Side note: The concrete value of m is irrelevant, assuming x is placed immediately in front of columns then the address of x is the address of b with m*sizeof(*x) subtracted, and x[m] then again adds m*sizeof(*x) to this address, thus x[m][0][0] always accesses column[0]...

How to solve: As long as you do the entire matrix processing within the loop then you can create the matrix as a simple two-dimensional array:

for(int m = 0; m < c; ++m)
{
    // in this case actually sufficient here as well,
    // as ordinary integers:
    int row; int column;
    // scan row and column
    int matrix[row][column];
    // now scan into matrix[r][c] with r and c iterating accordingly
}

If you want to maintain an array of matrices then you need to define this array before entering the loop! The problem that then arises: All array entries are required to be of equal size! With a single 3D array you'd need to first determine the sizes of all matrices and remember the the maximal dimenstions to use for all the matrices.

The alternative is allocating the matrices dynamically, however you need a way to properly handle them then.

I recommend using a dedicated struct for and mapping the 2D array of the matrix to a single one-dimenstional array, doing index calculations by hand, such as:

#include<stddef.h> // for size_t

struct Matrix
{
    size_t rows, columns;
    int* values;
    // or alternatively with flexible array member:
    int values[0];
};

int get(struct Matrix* matrix, size_t row, size_t column)
{
    return matrix->values[row * matrix->columns + column];
}

void set(struct Matrix* matrix, size_t row, size_t column, int value)
{
    matrix->values[row * matrix->columns + column] = value;
}

Finally you can allocate dynamically; either as

struct Matrix matrices[m] = { {0, 0, NULL} };

or with flexible array members as

struct Matrix* matrices[m] = { NULL };

Note that you need dynamic memory allocation anyway, either for the array referenced by the matrix by pointer or for the entire matrix struct in case of the flexible array member (I personally consider the latter approach a bit cleaner...):

Then allocation of the matrices within the loop occurs as follows:

size_t count;
scanf("%zu", &count);
for(size_t m = 0; m < count; ++m)
{
    size_t rows, columns;
    scanf("%zu", &rows);
    scanf("%zu", &columns);

    ///////////////////////////////////////////////////
    // pointer variant:

    matrices[m].values = malloc(rows * columns * sizeof(*matrices[m].values));
    if(!matrices[m].values)
    {
        // allocation failed!
        // TODO: appropriate error handling!
        // return or exit(-1) or ??? 
    }
    matrices[m].rows = rows;
    matrices[m].columns = columns;

    ///////////////////////////////////////////////////
    // flexible array member variant:

    matrices[m] = malloc
        (
            // base size
            sizeof(*matrices[m])
            // plus size of array
            + rows * columns * sizeof(*matrices[m]->values)
        );
    if(!matrices[m])
    { /* again: error handling! */ }
    matrices[m]->rows = rows;
    matrices[m]->columns = columns; 

    /////////////////////////////////////////////////// 

    // now scan the matrix entries
    int* values = matrices[m].values;  // pointer variant
    int* values = matrices[m]->values; // flexible array member; note that the
                                       // array decays to pointer automatically
    // looping over rows and columns
        scanf("%d", values++);
}

Finally: There's dynamically allocated memory, do not forget to free it again:

for(size_t m = 0; m < count; ++m)
{
    free(matrices[m].values); // array as pointer
    free(matrices[m]);        // flexible array member
}

Final note: All code entirely untested, if you find a bug please fix yourself...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • thanks thanks thanks aconcagua i have been struggling with this problem for a long time and i finally understood it . thanks again for your time and effort and writing in detail the solution to my problem. – vatsal May 24 '23 at 14:36