簡體   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