Home > Software design >  Reading Complex Matrix From Text File
Reading Complex Matrix From Text File

Time:12-27

I am having a lot of trouble trying to read a complex matrix from a text file in C. The format of the text file is of the form (%le% lej). The test matrix used is:

 (0.000000000000000000e 00 0.000000000000000000e 00j)  (0.000000000000000000e 00 1.000000000000000056e-01j)  (0.000000000000000000e 00 2.000000000000000111e-01j)  (0.000000000000000000e 00 3.000000000000000444e-01j)
 (1.100000000000000089e 00 0.000000000000000000e 00j)  (1.100000000000000089e 00 1.000000000000000056e-01j)  (1.100000000000000089e 00 2.000000000000000111e-01j)  (1.100000000000000089e 00 3.000000000000000444e-01j)
 (2.200000000000000178e 00 0.000000000000000000e 00j)  (2.200000000000000178e 00 1.000000000000000056e-01j)  (2.200000000000000178e 00 2.000000000000000111e-01j)  (2.200000000000000178e 00 3.000000000000000444e-01j)

I have spent nearly two days just trying to get this working. So I would like a simple and easy to debug solution if such a thing exists.

My simplified attempt:

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

int main(void)
{
    char fname[] = "test_matrix.dat";
    int m = 3;
    int n = 4;
    complex double * matrix = calloc(m * n, sizeof(complex double));
    FILE * ifile = fopen(fname, "r");
    int i, j, info;
    double zreal, zimag;
    for(i = 0; i < m; i  )
    {
        for(j = 0; j < n; j  )
        {
            info = fscanf(ifile, "(%le%lej)", &zreal, &zimag);
            // The following doesn't work either.
            // info = fscanf(ifile, "(%le", &zreal);
            // info  = fscanf(ifile, "%lej)", &zimag);
            if(info != 2)
            {
                fclose(ifile);
                fprintf(stderr, "Wrong input format, info = %d\n", info);
                exit(EXIT_FAILURE);
            }
            *(matrix   i   j*m) = zreal   I*zimag;
            // printf("%d ", info); This gives all zeroes
            printf("%6.1e% 7.1ej ", zreal, zimag);
        }
        printf("\n");
    }
    fclose(ifile);
    free(matrix);
    return(0);
}

I have also tried not putting the extra formatting things in the fscanf, instead I tried looping fgetc till I read ( and then doing two fscanfs, but it quickly became too complicated and hard to debug, still haven't been able to get that working. So any assistance will be appreciated.

EDIT: This is irrelevant to the problem, but just to clarify I am using column major format because it has to be used with blas/lapack later on.

CodePudding user response:

fscanf format is not correct :

info = fscanf(ifile, " (%le %lej)", &zreal, &zimag);

CodePudding user response:

Since you requested it, I'd like to add to Fryz's answer by providing a complete working example:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <complex.h>

int main(void)
{
    const char *filename = "test_matrix.dat";
    FILE *file = fopen(filename, "r");
    if (!file) {
        perror("Could not open file");
        return 1;
    }

    const size_t nrows = 3;
    const size_t ncols = 4;

    complex double *matrix = malloc(nrows * ncols * sizeof(*matrix));
    if (!matrix) {
        printf("Internal error\n");
        fclose(file);
        return 1;
    }

    double zreal, zimag;
    for (size_t i = 0; i < nrows;   i) {
        for (size_t j = 0; j < ncols;   j) {
            if (fscanf(file, " (%le %lej)", &zreal, &zimag) != 2) {
                printf("%zu::%zu: Wrong format\n", i, j);
                continue;
            }

            matrix[i j*ncols] = zreal   I * zimag;
            printf("(%.18le %1.18lej) ", zreal, zimag);
        }
        printf("\n");
    }

    free(matrix);
    fclose(file);
}

Output:

(0.000000000000000000e 00 0.000000000000000000e 00j) (0.000000000000000000e 00 1.000000000000000056e-01j) (0.000000000000000000e 00 2.000000000000000111e-01j) (0.000000000000000000e 00 3.000000000000000444e-01j)
(1.100000000000000089e 00 0.000000000000000000e 00j) (1.100000000000000089e 00 1.000000000000000056e-01j) (1.100000000000000089e 00 2.000000000000000111e-01j) (1.100000000000000089e 00 3.000000000000000444e-01j)
(2.200000000000000178e 00 0.000000000000000000e 00j) (2.200000000000000178e 00 1.000000000000000056e-01j) (2.200000000000000178e 00 2.000000000000000111e-01j) (2.200000000000000178e 00 3.000000000000000444e-01j)

Few things to note:

  • Always check the return value of C standard library functions.
  • Use const when a variable's value will not be changed.
  • The appropriate type for indices is size_t, not int.
  • Close your file handles and free your allocated memory when you are done with them.
  •  Tags:  
  • c
  • Related