这是我从文件中读取矩阵的功能。在第一行的文本文件中,{2}是n
,3是m
,接下来的两行是矩阵。
我没有错误,但我的计划"停止工作"而且我不知道为什么。谢谢!
主要是我:readmatrix(n,m,a, "text.txt");
int readmatrix(int* n,int *m, int a[*n][*m], char* filename){
FILE *pf;
int i,j;
pf = fopen (filename, "rt");
if (pf == NULL)
return 0;
fscanf (pf, "%d",n);
for (i=0;i<*n;i++)
{
for(j=0;j<*m;j++)
fscanf (pf, "%d", &a[i][j]);
}
fclose (pf);
return 1;
}
答案 0 :(得分:2)
如果您的编译器支持VLA或您使用的是C99,那么您可以这样做:
#include <stdio.h>
int readmatrix(size_t rows, size_t cols, int (*a)[cols], const char* filename)
{
FILE *pf;
pf = fopen (filename, "r");
if (pf == NULL)
return 0;
for(size_t i = 0; i < rows; ++i)
{
for(size_t j = 0; j < cols; ++j)
fscanf(pf, "%d", a[i] + j);
}
fclose (pf);
return 1;
}
int main(void)
{
int matrix[2][3];
readmatrix(2, 3, matrix, "file.dat");
for(size_t i = 0; i < 2; ++i)
{
for(size_t j = 0; j < 3; ++j)
printf("%-3d ", matrix[i][j]);
puts("");
}
return 0;
}
file.dat
看起来像这样:
1 2 3
4 5 6
我的程序输出
$ ./a
1 2 3
4 5 6
请注意,这是一个基本示例,您应该始终检查返回值
fscanf
。如果file.dat
只有一行,那么你会遇到麻烦。也
文件中没有数字,你也会得到未定义的值
基质
我建议用fgets
读取整行,然后使用解析行
sscanf
或其他一些功能,如strtok
,那么它会更容易做出反应
到输入文件中的错误。
修改强>
更健壮的方式来读取这样的文件将是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int **readmatrix(size_t *rows, size_t *cols, const char *filename)
{
if(rows == NULL || cols == NULL || filename == NULL)
return NULL;
*rows = 0;
*cols = 0;
FILE *fp = fopen(filename, "r");
if(fp == NULL)
{
fprintf(stderr, "could not open %s: %s\n", filename, strerror(errno));
return NULL;
}
int **matrix = NULL, **tmp;
char line[1024];
while(fgets(line, sizeof line, fp))
{
if(*cols == 0)
{
// determine the size of the columns based on
// the first row
char *scan = line;
int dummy;
int offset = 0;
while(sscanf(scan, "%d%n", &dummy, &offset) == 1)
{
scan += offset;
(*cols)++;
}
}
tmp = realloc(matrix, (*rows + 1) * sizeof *matrix);
if(tmp == NULL)
{
fclose(fp);
return matrix; // return all you've parsed so far
}
matrix = tmp;
matrix[*rows] = calloc(*cols, sizeof *matrix[*rows]);
if(matrix[*rows] == NULL)
{
fclose(fp);
if(*rows == 0) // failed in the first row, free everything
{
fclose(fp);
free(matrix);
return NULL;
}
return matrix; // return all you've parsed so far
}
int offset = 0;
char *scan = line;
for(size_t j = 0; j < *cols; ++j)
{
if(sscanf(scan, "%d%n", matrix[*rows] + j, &offset) == 1)
scan += offset;
else
matrix[*rows][j] = 0; // could not read, set cell to 0
}
// incrementing rows
(*rows)++;
}
fclose(fp);
return matrix;
}
int main(void)
{
size_t cols, rows;
int **matrix = readmatrix(&rows, &cols, "file.dat");
if(matrix == NULL)
{
fprintf(stderr, "could not read matrix\n");
return 1;
}
for(size_t i = 0; i < rows; ++i)
{
for(size_t j = 0; j < cols; ++j)
printf("%-3d ", matrix[i][j]);
puts("");
}
// freeing memory
for(size_t i = 0; i < rows; ++i)
free(matrix[i]);
free(matrix);
return 0;
}
现在file.dat
看起来像这样:
1 2 3 4
4 5 6 5
9 8 8 7
5 5 5 5
1 1 1 1
输出
1 2 3 4
4 5 6 5
9 8 8 7
5 5 5 5
1 1 1 1
在此示例中,我仅计算第一列的列数 将该数字用于所有其他列。如果输入文件的行数少于 第一行的列,然后缺少的值存储为0.如果它有行 将修剪比列更多的列。
我计算这样的行数:
while(sscanf(scan, "%d%n", &dummy, &offset) == 1)
{
scan += offset;
(*cols)++;
}
首先我声明指针scan
指向line
,以便我可以修改。{1}}
指针不会丢失原始行。 %n
中的sscanf
不计算在内
成功转换的次数,这将返回scan
的位置
它停止了阅读。我用它来循环sscanf
。我明确地检查了一下
sscanf
返回1,如果是这种情况,我会增加列数和
我更新scan
以更新到sscanf
停止阅读的位置。这个
允许我继续扫描,直到到达行尾。我用了一个
类似的技术来解析所有整数。