您可以采取多种方法。这里的关键是你知道你将有 2 个整数(前两行各一个)代表要遵循的 rows 和 cols 的数据数量。然后您将在矩阵中读取rows 的cols 数量。您的第一个决定将是“我如何处理存储?” (动态分配,或者如果我对矩阵使用可变长度数组(VLA),数据是否足够小它不会StackOverflow?)
使用 VLA 消除了动态分配、跟踪和释放内存的需要,但您必须知道您不需要存储超出堆栈容量的double 值。以下假设您的值小于 100,000 左右使 VLA 成为有效选项。
首先,您将如何从文件中提取(读取)row 和 col 值?虽然fgets 是迄今为止进行面向行输入的首选方式,但实际上您可以在一次调用fprintf 中同时获得row 和col,另外还有一个好处是消耗col 值之后的所有剩余空格直到矩阵的第一个值。例如,以下将起作用:
/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}
(注意:space 在"%d %d " 中最后一个转换说明符之后)
有了row 和col 值,您现在可以调整缓冲区的大小,以使用fgets 读取文件中剩余的每一行。将每一行读入缓冲区后,将使用strtod 从缓冲区解析每列值,并根据col 值验证解析的值的数量,以确保填充矩阵的完整行。行缓冲区是一个 VLA,每个要读取的 col 值的大小也是 32-chars (50% 应该绰绰有余)。使用 VLA 调整缓冲区和矩阵的大小可以按如下方式完成:
bufsz = col * 32; /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */
接下来就是简单地用fgets读取每一行,然后用一个指针来测试当前字符是否是[+-0-9]之一。如果是,则执行并验证到double 的转换,并且指针前进到转换中结束字符之后的下一个字符(由strtod 本身提供)。
如果当前角色不是您感兴趣的角色,则无需对其执行任何操作并获取下一个角色(这是跳过','s 的简单方法)
在一行中的所有值都转换后,将成功转换的次数与col 进行比较,以确保矩阵中的一整行被填充,如果没有处理错误。然后只需读取下一行并重复直到row 行数已被读取和转换。您可以通过以下方式完成此操作:
/* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}
在您阅读row 行值得col 值后,您可以根据需要使用您的矩阵。以下只是将以上内容放在一个简短的示例中,用于读取和输出您提供的示例数据:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main (int argc, char **argv) {
int bufsz, col, row, ridx = 0; /* buffer size, col, row, row index */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}
bufsz = col * 32; /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */
/* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
if (ridx != row) { /* validate that row rows read from file */
fprintf (stderr, "error: file has only row '%d' rows.\n", ridx);
return 1;
}
for (int i = 0; i < row; i++) { /* output the matrix */
for (int j = 0; j < col; j++)
printf (" %9.2f", mtrx[i][j]);
putchar ('\n');
}
return 0;
}
使用/输出示例
$ ./bin/readmtrx dat/matrix.txt
3.00 1.00 1180.00 1955.00 221900.00
3.00 2.25 2570.00 1951.00 538000.00
2.00 1.00 770.00 1933.00 180000.00
查看一下,如果您还有其他问题,请告诉我。如果您没有编译器提供的 VLA 扩展,动态内存分配是您的另一个选择,如另一个答案中所述。