C语言动态分配实现文件矩阵读取:程序冻结问题排查
解决文件读取时程序冻结的问题
我看了你的代码,程序在读取文件阶段冻结的核心原因是统计矩阵行列数的循环逻辑错误,导致死循环,另外还有几个内存分配和文件操作的小问题,下面逐一拆解并修正:
主要错误点分析
1. 死循环的根源:错误的循环条件
你统计行数和列数的第一个for循环里,把赋值操作写成了比较操作:
for (lines = fgetc (ptrOut); lines != EOF; lines == fgetc (ptrOut))
这里的lines == fgetc(ptrOut)是判断是否相等,不是给lines赋值,所以lines永远不会更新,只要初始读取的不是EOF,就会一直循环下去,直接导致程序冻结。
2. 行列统计逻辑完全颠倒
你原本的逻辑是想用换行符统计列数、用空格/制表符统计行数,这完全搞反了:
- 换行符
\n的数量应该对应矩阵的行数(每行结束一个换行) - 每行的元素数(通过制表符/空格分隔)对应列数
3. 文件指针未重置
在统计完行列数后,文件指针已经走到了文件末尾,如果不重置到开头,后续读取数据会直接读到EOF,无法获取矩阵值。
4. 内存分配错误
创建matrixOut时,你错误地用列数c来分配行指针:
matrixOut = (double **) malloc (c * sizeof (double *));
应该用行数r来分配,否则会导致内存越界。
5. 多余的内存释放
在统计行列后你提前释放了matrixOut,后面又重新分配,这属于冗余操作,而且容易引发错误。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define STRING_MAX 50 void printDiagonal(double **m, int r, int c); int main(int argc, char *argv[]) { FILE *ptrIn; FILE *ptrOut; char inFileName[STRING_MAX]; char outFileName[STRING_MAX]; int row; int col; int r; int c; int i, j; double matrixVals; double **matrixIn; double **matrixOut; // 第一步:创建矩阵并写入文件 printf("\nEnter a file name >> "); scanf("%s", inFileName); // 以写入模式打开文件(如果文件不存在则创建,存在则清空) ptrIn = fopen(inFileName, "w"); if (ptrIn == NULL) { printf("\nFailed to open output file!\n"); exit(1); } printf("\nEnter the row and column sizes >> "); scanf("%d %d", &row, &col); printf("\nRows >> %d\nCols >> %d\n\n", row, col); // 动态分配矩阵内存 matrixIn = (double **)malloc(row * sizeof(double *)); if (matrixIn == NULL) { printf("\nSORRY, NOT ENOUGH MEMORY!\n\n"); fclose(ptrIn); exit(0); } for (i = 0; i < row; i++) { matrixIn[i] = (double *)malloc(col * sizeof(double)); if (matrixIn[i] == NULL) { printf("\nSORRY, NOT ENOUGH MEMORY!\n\n"); // 释放已分配的内存 for (int k = 0; k < i; k++) free(matrixIn[k]); free(matrixIn); fclose(ptrIn); exit(0); } } // 输入矩阵值 printf("\nEnter the values into the matrix >> \n\n"); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf("\n\nEnter [%d][%d] of [%d][%d] >> ", (i + 1), (j + 1), row, col); scanf("%lf", &matrixIn[i][j]); } } // 打印矩阵并写入文件 printf("\nElements in the matrix >> \n\n"); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf("%.3lf\t", matrixIn[i][j]); fprintf(ptrIn, "%.3lf\t", matrixIn[i][j]); } printf("\n"); fprintf(ptrIn, "\n"); } printf("\n"); fprintf(ptrIn, "\n"); // 释放内存并关闭文件 for (i = 0; i < row; i++) free(matrixIn[i]); free(matrixIn); fclose(ptrIn); printf("\n-----------------------------------------------------------------------------------------------------------------\n\n"); // 第二步:读取文件中的矩阵 FILE_NAME: printf("\nEnter the name of file to access >> "); scanf("%s", outFileName); printf("\nThe name of the file is >> %s\n\n", outFileName); // 以只读模式打开文件 ptrOut = fopen(outFileName, "r"); if (ptrOut == NULL) { printf("\nSORRY, THE FILE DOES NOT EXIST. PLEASE ENTER A VALID FILE NAME.\n\n"); goto FILE_NAME; } // 统计行数和列数 char ch; r = 0; c = 0; int first_line = 1; // 先统计行数和第一行的列数 while ((ch = fgetc(ptrOut)) != EOF) { if (ch == '\n') { r++; first_line = 1; // 下一行是新行 } else if ((ch == '\t' || ch == ' ') && !first_line) { // 跳过开头的空格/制表符,统计元素分隔符 c++; } else if (ch != '\t' && ch != ' ') { first_line = 0; // 遇到第一个有效字符,开始统计列数 } } // 最后一行如果没有换行符,行数加1 fseek(ptrOut, -1, SEEK_END); ch = fgetc(ptrOut); if (ch != '\n') r++; // 列数是分隔符数量+1 c += 1; printf("\nNumber of rows >> %d\n\nNumber of columns >> %d\n\n", r, c); // 动态分配矩阵内存 matrixOut = (double **)malloc(r * sizeof(double *)); if (matrixOut == NULL) { printf("\nSorry, not enough memory!\n\n"); fclose(ptrOut); exit(0); } for (i = 0; i < r; i++) { matrixOut[i] = (double *)malloc(c * sizeof(double)); if (matrixOut[i] == NULL) { printf("\nSorry, not enough memory!\n\n"); for (int k = 0; k < i; k++) free(matrixOut[k]); free(matrixOut); fclose(ptrOut); exit(0); } } // 重置文件指针到开头 rewind(ptrOut); // 读取矩阵值并打印 printf("\nMatrix from File %s of dimensions %d X %d >>\n\n", outFileName, r, c); for (i = 0; i < r; i++) { for (j = 0; j < c; j++) { fscanf(ptrOut, "%lf", &matrixVals); matrixOut[i][j] = matrixVals; printf("%.3lf\t", matrixOut[i][j]); } printf("\n"); // 跳过换行符(如果有的话) fscanf(ptrOut, "\n"); } printf("\n"); // 释放内存并关闭文件 for (i = 0; i < r; i++) free(matrixOut[i]); free(matrixOut); fclose(ptrOut); return 0; } // 实现printDiagonal函数(原代码未实现,这里补充空实现避免编译错误) void printDiagonal(double **m, int r, int c) { // 可以在这里添加对角线打印逻辑 }
关键修正说明
- 修复死循环:把统计行列的循环条件中的
==改为=,同时重新梳理了行列统计的逻辑,正确通过换行符统计行数、分隔符统计列数。 - 重置文件指针:用
rewind(ptrOut)把指针重置到文件开头,确保后续能正确读取数据。 - 修正内存分配:创建
matrixOut时用行数r分配行指针,避免内存越界。 - 完善错误处理:在内存分配失败时,释放已分配的内存再退出,避免内存泄漏;添加文件打开失败的判断。
- 移除冗余操作:删除了统计行列后多余的内存释放步骤。
内容的提问来源于stack exchange,提问作者Hadrian Hu
相关产品推荐
相关产品推荐

