我在试图从c文本文件中读取复杂矩阵时遇到了很多麻烦。该文本文件的格式为(%le%+lej)
。使用的测试矩阵为:
(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)
我花了将近两天的时间试图让这个工作。所以我想一个简单,容易调试的解决方案,如果这样的事情存在。
我的简化尝试:
#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 = %dn", 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);
}
我也试着不把额外的格式化的东西在fscanf
,相反,我试着循环fgetc
,直到我读(
,然后做两个fscanf
s,但它很快变得过于复杂和难以调试,仍然没有能够得到那工作。因此,任何帮助都将不胜感激。
fscanf
格式不正确:
info = fscanf(ifile, " (%le+%lej)", &zreal, &zimag);
既然你要求,我想通过提供一个完整的工作示例来补充Fryz的答案:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.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 errorn");
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 formatn", i, j);
continue;
}
matrix[i*ncols+j] = zreal + I * zimag;
printf("(%.18le+%1.18lej) ", zreal, zimag);
}
printf("n");
}
free(matrix);
fclose(file);
}
输出:
(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)
注意事项:
- 总是检查C标准库函数的返回值。
- 当一个变量的值不会被改变时,使用
const
。 - 索引的合适类型是
size_t
,而不是int
。 - 关闭你的文件句柄,当你用完它们时释放你分配的内存。
以下代码在我的计算机上运行成功,输入如下:
#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 == %dn", res);
}
和以下输入:
$ a.out
(3-5j)(2-8j)(-6+3j) <-- input
(3, -5)(2, -8)(-6, 3)res == 0 <-- output
$ _
正如您可能猜到的那样,只要我按下返回键,输入不匹配,并且我读取三个有效的复数,之后没有任何匹配(fscanf()
获得n
字符,并且不读取任何内容,向while循环返回0。我打印了函数的结果,看看为什么它失败了。在输入之间,您应该自己处理空白(当您扫描n
时也要区分)是我的建议。
一种更好的格式是扫描两个数字来表示矩阵维度,然后扫描rows*cols
对数字来表示矩阵内容,它们之间用任何形式的空格分隔。例如
2 2
1 0 0 0
0 0 1 0
将导致从输入文件中读取单位矩阵。
对于更复杂的阅读器,您需要从flex(1)
和/或bison(1)
工具中获得帮助,这些工具允许您处理空白,甚至注释或嵌套括号!!:)编写这些工具是为了帮助您对复杂语言(如C或pascal)进行全面解析。