[英]Reading Complex Matrix From Text File
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)
.我在尝试从 C 中的文本文件中读取复杂矩阵时遇到了很多麻烦。文本文件的格式为(%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 fscanf
s, 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.我也尝试过不在fscanf
中放置额外的格式化内容,而是尝试循环fgetc
直到我阅读(
然后执行两个fscanf
s,但它很快变得太复杂且难以调试,仍然无法得到它工作。因此,我们将不胜感激。
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.编辑:这与问题无关,但只是为了澄清我正在使用列主要格式,因为它必须在以后与 blas/lapack 一起使用。
fscanf
format is not correct: fscanf
格式不正确:
info = fscanf(ifile, " (%le+%lej)", &zreal, &zimag);
Since you requested it, I'd like to add to Fryz 's answer by providing a complete working example:既然您提出了要求,我想通过提供一个完整的工作示例来补充Fryz的回答:
#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: 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:需要注意的几点:
const
when a variable's value will not be changed.当变量的值不会改变时使用const
。size_t
, not int
.索引的适当类型是size_t
,而不是int
。The following code works successfully on my computer with the input below:以下代码在我的计算机上成功运行,输入如下:
#include <stdio.h>
int main()
{
double x, y;
int res;
while ((res = fscanf(stdin, "(%lg%lgj)", &x, &y)) == 2) {
printf("(%g, %g)", x, y);
}
printf("res == %d\n", res);
}
and the following input:和以下输入:
$ a.out
(3-5j)(2-8j)(-6+3j) <-- input
(3, -5)(2, -8)(-6, 3)res == 0 <-- output
$ _
As you probably guess, as soon as I press the return key, the input does not match, and I get three valid complex numbers read, and after that nothing is matched ( fscanf()
gets a \n
char, and reads nothing, returning 0 to the while loop. I printed the result of the function to see why it is failing. Between the inputs you should handle the whitespace yourself (to distinguish also when you scan a \n
) is my suggestion.正如您可能猜到的那样,当我按下回车键时,输入不匹配,我读取了三个有效的复数,之后没有任何匹配( fscanf()
得到一个\n
字符,并且没有读取任何内容,返回0 到 while 循环。我打印了 function 的结果以查看它失败的原因。我的建议是在输入之间你应该自己处理空格(以便在扫描\n
时也能区分)。
a better format would be to scanf two numbers for the matrix dimensions, then rows*cols
pairs of numbers, for the matrix contents, all of them separated by any kind of whitespace.更好的格式是为矩阵维度扫描两个数字,然后为矩阵内容rows*cols
对数字,所有这些都由任何类型的空格分隔。 Eg例如
2 2
1 0 0 0
0 0 1 0
that will result in identity matrix read from the input file.这将导致从输入文件中读取单位矩阵。
For a more elaborate reader, you will need to get help from flex(1)
and/or bison(1)
tools, that allows you to handle whitespace and even comments or nested parenthesis:,.对于更精细的阅读器,您将需要从flex(1)
和/或bison(1)
工具中获得帮助,这些工具允许您处理空格甚至注释或嵌套括号:,。 :) Those tools were written to help you in the full parsing of elaborate languages, like C or pascal. :) 这些工具的编写是为了帮助您全面解析复杂的语言,例如 C 或 pascal。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.