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
constwhen a variable's value will not be changed. - The appropriate type for indices is
size_t, notint. - Close your file handles and free your allocated memory when you are done with them.
