[英]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.