'Dynamic memory in c, change size of array

I have a doubt, how can i solve this?

I have a file with several matrices, and I need to use while a loop like this. I just know the order of the array when the file is read.

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

int MIN_ORDER = 32;
int M = 0;
int N = 0;
bool firstProcessing = true;
int pos=0;

typedef struct {
    int numberOfMatrices;
    int orders;
    int nextMatrixToProcessed;
    bool done;
} INFOSFILE;


int getMatrix(double buffer[N][N], INFOSFILE *infos, int *min_size) {
    FILE *f = fopen("src/128_32.bin", "rb+");

    if(f == 0) {
        perror("fopen");
        exit(1);
    }
    if (firstProcessing) {             
        fread(&M,sizeof(M),1,f);
        fread(&N,sizeof(N),1,f);
        pos = ftell(f);
        infos->nextMatrixToProcessed = 0;
        infos->numberOfMatrices = M;
        infos->orders = N;
        infos->done = false;
        firstProcessing = false;
    } else{
        if (infos->done) return 1;
    }
    *min_size = N;

    if (infos->nextMatrixToProcessed +1 == infos->numberOfMatrices ){
        infos->done = true;
    }

    if (firstProcessing == false) fseek(f, pos, SEEK_SET );  
    if (firstProcessing == true) firstProcessing = false;
    fread(buffer, sizeof(double[N * N]), 1, f);
    pos = ftell(f);
    fclose(f);
    return 0;
}

void processMatrix(double buffer[N][N], INFOSFILE *infos){
    printf("Matrix %d\n",infos->nextMatrixToProcessed);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            printf("%f\t", buffer[i][j]);
        }
        printf("\n");
    }
    printf("\n\n");
    infos->nextMatrixToProcessed++;

}

int main(int argc, char *argv[]) {
    setlocale(LC_CTYPE, "");

    double buffer[MIN_ORDER][MIN_ORDER];
    INFOSFILE infos;
    while (getMatrix( buffer, &infos, &MIN_ORDER) != 1) {
        processMatrix(buffer, &infos);
    }
    printf("\n%d",infos.nextMatrixToProcessed);
    printf("\n%i",infos.done);
    printf("\n%d",infos.numberOfMatrices);
    printf("\n%d",infos.orders);
    return 0;
}

I can't change the algorithm, only i can change the declarations.

The file has: Number of matrices Matrix order Matrix[1] Matrix[2] ...



Solution 1:[1]

  1. For a given input file with float/double values like : Three matrices of different sizes:
3
2 3 
1.0 2.0 3.0
4.0 5.0 6.0
4 4
1.0 2.0 3.0 3.5
4.0 5.0 6.0 6.5
1.2 2.2 3.5 6.5
9.5 5.5 5.4 6.4
2 2
123.211 353.54
5455.878 587.545
  1. You can dynamically realloc() memory needed as follows:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

static inline void
matrix_print (int rows, int cols, double dmat[rows][cols]) {
    for (int ri = 0; ri < rows; ++ri) {
        for (int ci = 0; ci < cols; ++ci)
            printf ("%6.2lf\t", dmat[ri][ci]);
        putchar ('\n');
    }
}

void /* rows & cols should precede dmat in argument list */
matrix_read (FILE* mFile, int rows, int cols, double dmat[rows][cols]) {
    for (int ri = 0; ri < rows; ++ri)
        for (int ci = 0; ci < cols; ++ci)
            if (1 != fscanf (mFile, " %lf", &dmat[ri][ci])) {
                printf ("ERROR reading matrix\n"); exit (5);
            }
}


int main() {
    FILE* mFile = fopen ("input.txt", "r");
    if (!mFile) {
        perror ("Opening File"); return 1;
    }
    int count;
    if (1 != fscanf (mFile, " %d", &count)) {
        printf ("ERROR: fscanf-count\n"); return 2;
    }

    double  (*dmat)[1] = malloc (sizeof(dmat[0][0]));
    while (count--) {
        int rows, cols;
        if (2 != fscanf (mFile, " %d %d", &rows, &cols)) {
            printf ("ERROR: fscanf-rows-cols\n"); return 3;
        }
        dmat = realloc (dmat, sizeof(double[rows][cols]));
        if (!dmat) {
            perror("mat-memory-alloc"); return 4;
        }
        matrix_read(mFile, rows, cols, dmat);
        // malloc_usable_size() is from GNU extensions
        printf ("\n\nMemory Alloc'd to double-dMat[%d][%d] : %zu\n", rows, cols, malloc_usable_size(dmat));
        matrix_print(rows, cols, dmat);
    }

    if (dmat) free (dmat);
    fclose (mFile);
    return 0;
}
  1. You can also use free() & malloc() combo, since realloc() is expensive trying to preserve existing data.
free (dmat);
dmat = malloc (sizeof(double[rows][cols]));
  1. You can also make use of Variabl-Length-Array if matrix data is small (less than a million entries for 8 MiB process-stack).
    while (count--) {
        int rows, cols;
        if (2 != fscanf (mFile, " %d %d", &rows, &cols)) {
            printf ("ERROR: fscanf-rows-cols\n"); return 3;
        }
        // resized at run-time : as rows & cols vary
        double dmat[rows][cols];
        
        matrix_read(mFile, rows, cols, dmat);
        printf ("\n\ndouble-dMat[%d][%d] :\n", rows, cols);
        matrix_print(rows, cols, dmat);
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1