繁体   English   中英

从文本文件中读取复杂矩阵

[英]Reading Complex Matrix From Text File

我在尝试从 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 = %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);
}

我也尝试过不在fscanf中放置额外的格式化内容,而是尝试循环fgetc直到我阅读(然后执行两个fscanf s,但它很快变得太复杂且难以调试,仍然无法得到它工作。因此,我们将不胜感激。

编辑:这与问题无关,但只是为了澄清我正在使用列主要格式,因为它必须在以后与 blas/lapack 一起使用。

fscanf格式不正确:

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

既然您提出了要求,我想通过提供一个完整的工作示例来补充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:

(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
  • 完成后关闭文件句柄并释放分配的 memory。

以下代码在我的计算机上成功运行,输入如下:

#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);
}

和以下输入:

$ a.out
(3-5j)(2-8j)(-6+3j)                    <-- input
(3, -5)(2, -8)(-6, 3)res == 0          <-- output
$ _

正如您可能猜到的那样,当我按下回车键时,输入不匹配,我读取了三个有效的复数,之后没有任何匹配( fscanf()得到一个\n字符,并且没有读取任何内容,返回0 到 while 循环。我打印了 function 的结果以查看它失败的原因。我的建议是在输入之间你应该自己处理空格(以便在扫描\n时也能区分)。

更好的格式是为矩阵维度扫描两个数字,然后为矩阵内容rows*cols对数字,所有这些都由任何类型的空格分隔。 例如

2 2
1 0 0 0
0 0 1 0

这将导致从输入文件中读取单位矩阵。

对于更精细的阅读器,您将需要从flex(1)和/或bison(1)工具中获得帮助,这些工具允许您处理空格甚至注释或嵌套括号:,。 :) 这些工具的编写是为了帮助您全面解析复杂的语言,例如 C 或 pascal。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM