Problem: I need to create several 3D arrays with different shapes—for example, one of size 0×2×2, another of size 1×1×3, and so on—and manage them despite their varying dimensions.
Previous Approaches: I tried using a struct with a 2D array member (x) and storing it in e[1]. Inside a loop, I update the row and column sizes based on user input, but each iteration redefines x’s dimensions and overwrites the previous data. For example, after filling x[2][2], resizing to x[1][3] destroys the original x[2][2] values, so I can’t access them later. Kindly suggest ways I could store 3-d array with different size of row and column for each matrix.
Code:
int main()
{
int matrix;
printf("ENTER NUMBER OF MATRICES\n");
scanf("%d`", &matrix);
int row, column;
for (int m = 0; m < matrix; m++) {
printf("ENTER NUMBER OF ROWS IN %d MATRICE\n", m + 1);
scanf("%d", &row);
printf("ENTER NUMBER OF column IN %d MATICE\n", m + 1);
scanf("%d", &column);
struct x {
int f[row][column];
};
struct x k[m];
int g = 1;
printf("ENTER ALL ELEMENT LEFT TO RIGHT\n");
for (int j = 0; j < row; j++) {
for (int u = 0; u < column; u++) {
printf("%d)\n", g);
scanf("%d", &k[m].f[j][u]);
g = g + 1;
}
}
for (int s = 0; s < row; s++) {
printf("|");
for (int l = 0; l < column; l++) {
printf("%d", k[m].f[s][l]);
if (l < column - 1) {
printf(" ");
}
}
printf("|\n");
}
printf("%d", k[0].f[0][0]); // error here calling over written
value
}
return 0;
Expectation:
ENTER NUMBER OF MATRICES
2
ENTER NUMBER OF ROWS IN 1 MATRICE
2
ENTER NUMBER OF column IN 1 MATICE
2
ENTER ALL ELEMENT LEFT TO RIGHT
1)
1
2)
2
3)
3 4
4)
4
|1 2|
|3 4|
ENTER NUMBER OF ROWS IN 2 MATRICE
1
ENTER NUMBER OF column IN 2 MATICE
3
ENTER ALL ELEMENT LEFT TO RIGHT
1)
5
2)
6
3)
7
|5 6 7|
1 // error here in output
Since each matrix may be a different size, you should manage each matrix separately and record its dimensions separately. The code below shows how to use a structure type to do that.
Common C implementations support variable length arrays, so you use this to make addressing the matrix elements simpler. The program below shows how to use a pointer to a variable length array to point to the rows of a matrix. The memory address is recorded in the structure using void *
, because we cannot have a variably modified type in the structure, but a separate variable is declared where it is needed, and it is set to the start of memory for the matrix.
In the absence of using variable length arrays, you would have to address the elements using manual arithmetic calculations into a linear array.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Read the number of matrices.
int NMatrices;
printf("Enter the number of matrices: ");
if (1 != scanf("%d", &NMatrices))
{
fprintf(stderr, "Error, scanf for number of matrices failed.\n");
exit(EXIT_FAILURE);
}
if (NMatrices < 0)
{
fprintf(stderr, "Error, number of matrices is negative.\n");
exit(EXIT_FAILURE);
}
// Define a type to manage a matrix.
struct MatrixInformation
{
void *Memory; // Memory for the matrix.
int NRows, NColumns; // Number of rows and number of columns.
};
// Allocate memory to manage NMatrices matrices.
struct MatrixInformation *Matrices = malloc(NMatrices * sizeof *Matrices);
if (!Matrices)
{
fprintf(stderr, "Error, failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Read each matrix.
for (int m = 0; m < NMatrices; ++m)
{
// Read the number of rows and the number of columns of this matrix.
int NRows, NColumns;
printf("Enter the number of rows in matrix %d: ", m+1);
if (1 != scanf("%d", &NRows))
{
fprintf(stderr, "Error, scanf for number of rows failed.\n");
exit(EXIT_FAILURE);
}
if (NRows <= 0)
{
fprintf(stderr, "Error, number of rows is not positive.\n");
exit(EXIT_FAILURE);
}
printf("Enter the number of columns in matrix %d: ", m+1);
if (1 != scanf("%d", &NColumns))
{
fprintf(stderr, "Error, scanf for number of columns failed.\n");
exit(EXIT_FAILURE);
}
if (NColumns <= 0)
{
fprintf(stderr, "Error, number of columns is not positive.\n");
exit(EXIT_FAILURE);
}
// Create a temporary pointer for the matrix and allocate memory.
int (*Matrix)[NColumns] = malloc(NRows * sizeof *Matrix);
if (!Matrix)
{
fprintf(stderr, "Error, failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Save the numbers of rows and columns and the memory address.
Matrices[m].NRows = NRows;
Matrices[m].NColumns = NColumns;
Matrices[m].Memory = Matrix;
// Get the values for the matrix elements.
for (int r = 0; r < NRows; ++r)
for (int c = 0; c < NColumns; ++c)
{
printf("Enter the element [%d, %d]: ", r+1, c+1);
if (1 != scanf("%d", &Matrix[r][c]))
{
fprintf(stderr, "Error, scanf for element failed.\n");
exit(EXIT_FAILURE);
}
}
}
// Print each matrix.
for (int m = 0; m < NMatrices; ++m)
{
printf("Matrix %d:\n", m+1);
// Get the numbers of rows and columns and the memory address.
int NRows = Matrices[m].NRows;
int NColumns = Matrices[m].NColumns;
int (*Matrix)[NColumns] = Matrices[m].Memory;
// Print each row.
for (int r = 0; r < NRows; ++r)
{
// Start each row with a delimiter and no spaces.
printf("|%d", Matrix[r][0]);
// Print each element with two spaces for separation.
for (int c = 1; c < NColumns; ++c)
printf(" %d", Matrix[r][c]);
// Finish each row with a delimiter and a new-line character.
printf("|\n");
}
}
// Free the memory of each matrix.
for (int m = 0; m < NMatrices; ++m)
free(Matrices[m].Memory);
// Free the memory for the array of structures about the matrices.
free(Matrices);
}