[英]Reading text file into a matrix in C
我有一个包含 200 x 150 数据的文本文件(每个数字都用空格分隔)。 我正在尝试将这些数字存储到矩阵中。 我的代码是这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int i,j, matrix[200][150];
void getMatrix(){
FILE *file;
file = fopen("PICTURE.txt", "r");
char *line, *number;
j = 0;
while(!feof(file)){
i = 0;
fscanf(file, "%s", line);
number = strtok(NULL, " ");
while(number!= NULL){
matrix[i][j] = atoi(number);
}
printf("\n");
j++;
}
}
void printMatrix(){
int a, b;
for(a=0; a<i; a++){
for(b=0; b<j; b++){
printf("%d", matrix[a][b]);
}
printf("\n");
}
}
int main(){
getMatrix();
printMatrix();
}
它实际上什么也没有打印出来。 我不明白为什么。 我该如何修复我的代码,或者您有任何其他重写它的建议?
很多问题:
永远不要使用while(!feof(file)){
。 而是检查fscanf(file, ...)
的返回值
不要使用没有宽度限制"%s"
。
不要在没有先初始化/分配它的情况下使用传递line
到 function。
i
从来没有增加过。
fclose(file)
完成后。
检查fopen(...);
GTG,也许以后会更多。
如果您有一个文件,其中包含 200x150 integer 值(在 200 行上,或在一行上的所有值),那么只需使用fscanf()
循环读取并存储 integer 一次即可。 您必须验证每次读取并提供一种方法来通过 function 返回(或通过函数内更新的指针)传达 function 内的任何故障
首先,不要在代码中使用MagicNumbers ,也不要硬编码文件名。 相反,# #define
您需要的常量(或使用全局enum
)并在调用 function 中打开(并验证文件已打开以供读取)后将打开的FILE*
指针作为参数传递给您的读取函数。 (如果文件打开失败——没有理由开始调用读取函数)
在您的情况下,您只有两个需要的常量:
#define ROWS 200 /* if you need a constant, #define on (or more) */
#define COLS 150
除非绝对必要,否则不要使用全局变量(当您开始学习 C 时,几乎没有需要全局变量的情况)。 将矩阵(二维数组)作为参数传递给您的读取函数,它可以写成:
/* fill m[ROWS][COLS] with values read from fp.
* returns 1 on success, 0 otherwise.
*/
int getmatrix (int (*m)[COLS], FILE *fp)
{
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (fscanf (fp, "%d", &m[row][col]) != 1) {
fprintf (stderr, "error reading m[%d][%d]\n", row, col);
return 0;
}
}
}
return 1;
}
(注意: function 的返回类型如何为int
,其中成功返回1
(true),失败返回0
(false)。另请注意,如果无法读取 200x150 值,则返回失败)
将要读取的文件名作为第一个参数传递给程序(这就是 main main()
的int argc, char **argv
参数的用途)。 或者,您可以提示用户并读取文件名作为输入。 如果没有输入文件名,您可以提供一个固定的文件名作为默认值( stdin
用作下面的默认值),否则不要硬编码文件名。 您不必为了读取不同的文件名而重新编译程序。
通过这些改进,您的main()
可能是:
int main (int argc, char **argv) {
int matrix[ROWS][COLS] = {{0}}; /* do not use global variables */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading in caller */
perror ("file open failed");
return 1;
}
if (!getmatrix (matrix, fp)) { /* pass array and open FILE*, validate */
return 1;
}
fclose (fp);
prnmatrix (matrix); /* output results */
}
完整的程序是:
#include <stdio.h>
#define ROWS 200 /* if you need a constant, #define on (or more) */
#define COLS 150
/* fill m[ROWS][COLS] with values read from fp.
* returns 1 on success, 0 otherwise.
*/
int getmatrix (int (*m)[COLS], FILE *fp)
{
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (fscanf (fp, "%d", &m[row][col]) != 1) {
fprintf (stderr, "error reading m[%d][%d]\n", row, col);
return 0;
}
}
}
return 1;
}
void prnmatrix (int (*m)[COLS])
{
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
printf (col ? " %4d" : "%4d", m[row][col]);
}
putchar ('\n');
}
}
int main (int argc, char **argv) {
int matrix[ROWS][COLS] = {{0}}; /* do not use global variables */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading in caller */
perror ("file open failed");
return 1;
}
if (!getmatrix (matrix, fp)) { /* pass array and open FILE*, validate */
return 1;
}
fclose (fp);
prnmatrix (matrix); /* output results */
}
示例使用/输出
生成小于 10000 的 200 x 150 个随机值并将其写入dat/int-200x150.txt
,您可以将程序运行为:
$ ./bin/read2darrint dat/int-200x150.txt
9240 5939 3063 5789 7401 7869 4363 3321 7788 1008 7850 ...
2760 5263 5338 6390 8146 155 324 916 4489 3718 1616 ...
...
其中 output 是 200 行,每行 150 个数字。
有很多方法可以做到这一点。 一种(更好的)方法是循环读取每个 integer 值作为字符串,并使用strtol()
将每个字符串转换为 integer 值。 我说“更好”的意思是strtol()
在转换失败的情况下提供更好的错误报告,而不是可以从fscanf()
获得的简单通过/失败。
使用strtol()
循环之前的读取将使用fgets()
进入足够大的缓冲区。 这样,如果发生匹配失败,则错误只会影响该数据行,并且输入 stream 未读中不会留下任何违规数据(匹配失败和fscanf()
将发生这种情况。
也就是说,对于一个格式正确、以空格分隔的文件充满数据,直接使用fscanf()
并没有错,只是要注意有更强大的方法来进行读取和转换。
如果您还有其他问题,请仔细查看并告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.