如何在C语言中读取文本文件中的复数矩阵?
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); // 以下写法也无效 // 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); 输出全为0 printf("%6.1e%+7.1ej ", zreal, zimag); } printf("\n"); } fclose(ifile); free(matrix); return(0); }
我还尝试过用fgetc循环定位到(后再执行fscanf,但该方法逻辑复杂,调试困难,至今未成功。
补充:采用列主序是为了后续对接BLAS/LAPACK库,与当前问题无关。
解决方案
1. 修正fscanf格式字符串
原代码的核心问题是格式字符串不匹配:
- 复数虚部前有
+号,格式字符串需要包含%+le来匹配带符号的虚部数值 - 每个复数前存在空格,格式字符串开头加空格可让
fscanf自动跳过所有空白字符(空格、换行、制表符等)
修正后的读取语句:
info = fscanf(ifile, " (%le%+lej)", &zreal, &zimag);
完整修正代码:
#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)); if (!matrix) { fprintf(stderr, "Memory allocation failed\n"); exit(EXIT_FAILURE); } FILE * ifile = fopen(fname, "r"); if (!ifile) { fprintf(stderr, "Failed to open file\n"); free(matrix); exit(EXIT_FAILURE); } int i, j, info; double zreal, zimag; for(i = 0; i < m; i++) { for(j = 0; j < n; j++) { // 修正格式字符串:开头空格跳过空白,%+le匹配带符号的虚部 info = fscanf(ifile, " (%le%+lej)", &zreal, &zimag); if(info != 2) { fprintf(stderr, "Wrong input format at row %d, column %d, info = %d\n", i+1, j+1, info); fclose(ifile); free(matrix); exit(EXIT_FAILURE); } *(matrix + i + j*m) = zreal + I*zimag; printf("%6.1e%+7.1ej ", zreal, zimag); } printf("\n"); } fclose(ifile); free(matrix); return(0); }
2. 逐行读取+sscanf(更易调试)
如果需要更方便调试,可以先逐行读取文件内容到缓冲区,再用sscanf解析每行的复数。这种方式可以直观查看每行的输入内容,便于定位格式错误。
示例代码:
#include <stdio.h> #include <stdlib.h> #include <complex.h> #include <string.h> #define BUFFER_SIZE 1024 int main(void) { char fname[] = "test_matrix.dat"; int m = 3; int n = 4; complex double * matrix = calloc(m * n, sizeof(complex double)); if (!matrix) { fprintf(stderr, "Memory allocation failed\n"); exit(EXIT_FAILURE); } FILE * ifile = fopen(fname, "r"); if (!ifile) { fprintf(stderr, "Failed to open file\n"); free(matrix); exit(EXIT_FAILURE); } char buffer[BUFFER_SIZE]; int i, j; double zreal, zimag; for(i = 0; i < m; i++) { // 读取整行到缓冲区 if (!fgets(buffer, BUFFER_SIZE, ifile)) { fprintf(stderr, "Failed to read row %d\n", i+1); fclose(ifile); free(matrix); exit(EXIT_FAILURE); } // 移除换行符(如果存在) buffer[strcspn(buffer, "\n")] = '\0'; char *ptr = buffer; int read_count = 0; for(j = 0; j < n; j++) { // 从当前指针位置解析复数 int info = sscanf(ptr, " (%le%+lej)%n", &zreal, &zimag, &read_count); if(info != 2) { fprintf(stderr, "Wrong input format at row %d, column %d\n", i+1, j+1); fprintf(stderr, "Current line content: %s\n", buffer); fclose(ifile); free(matrix); exit(EXIT_FAILURE); } *(matrix + i + j*m) = zreal + I*zimag; printf("%6.1e%+7.1ej ", zreal, zimag); // 移动指针到下一个复数的起始位置 ptr += read_count; } printf("\n"); } fclose(ifile); free(matrix); return(0); }
该方案的优势:
- 可以直接打印出错行的内容,快速定位格式问题
- 不受跨换行的空白字符影响,解析逻辑更清晰
内容的提问来源于stack exchange,提问作者adch99
相关产品推荐
相关产品推荐

