我有一個包含 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();
}
它實際上什么也沒有列印出來。我不明白為什么。我該如何修復我的代碼,或者您有任何其他重寫它的建議?
uj5u.com熱心網友回復:
如果您有一個具有 200x150 整數值的檔案(在 200 行上,或在一行上的所有值),那么只需回圈fscanf()讀取并一次存盤一個整數即可。您必須驗證每次讀取并提供一種通過函式回傳(或通過函式內更新的指標)在函式內傳達任何故障的方法
首先,不要在代碼中使用MagicNumbers,也不要硬編碼檔案名。相反,#define您需要的常量(或使用 global enum)并FILE*在呼叫函式中打開(并驗證檔案已打開以供讀取)后將open指標作為引數傳遞給您的讀取函式。(如果檔案打開失敗——沒有理由開始呼叫讀取函式)
在您的情況下,您只有兩個需要的常量:
#define ROWS 200 /* if you need a constant, #define one (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;
}
(注:該函式的回傳型別是如何int在那里1(真)回傳成功和0(假)失敗則回傳還要注意的是,如果200x150值是無法被讀取,則回傳失敗)
將要讀取的檔案名作為第一個引數傳遞給程式(這就是要使用的int argc, char **argv引數main())。或者,您可以提示用戶并讀取檔案名作為輸入。如果沒有輸入檔案名(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 one (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 ? " M" : "M", 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 ...
...
輸出是 200 行,每行 150 個數字。
There are many ways to do this. One (better) way would be to loop reading each line of integer values as a string with fgets() and converting each set of ASCII digits into an integer value with strtol(). I say "better" in a sense that strtol() provides far better error reporting in the case of a failed conversion that the simple pass/fail that can be obtained from fscanf().
The read before looping with strtol() would be with fgets() into a sufficiently sized buffer. That way if a matching-failure occurs, the error only impacts that line of data and no offending data is left in your input stream unread (as will occur with a matching-failure and fscanf().
That said, with a properly formatted space-separated file full of data, there is nothing wrong with using fscanf() directly, just be aware there are more robust ways to do the read and conversion.
To use strtol(), to work through each line of values, you simply use a pointer to the beginning of each set of digits calling strtol() which then updates the endptr to one past the last digit converted allowing you to work your way though each number by updating the pointer (nptr) to endptr after each validated conversion. See man 3 strtol. You could updated the code above with:
...
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
...
#define MAXC 2048 /* (150 int space) max of 1800 chars per-line */
and finally change your function to use strtol(), e.g.
/* fill m[ROWS][COLS] with values read from fp.
* returns 1 on success, 0 otherwise.
*/
int getmatrix (int (*m)[COLS], FILE *fp)
{
char buf[MAXC]; /* buffer to hold each line */
for (int row = 0; row < ROWS; row ) {
char *nptr = buf, *endptr = nptr; /* nptr and endptr for strtol */
if (!fgets (buf, MAXC, fp)) { /* read line of input */
fprintf (stderr, "error: failed to read line %d\n", row);
return 0;
}
for (int col = 0; col < COLS; col ) {
errno = 0; /* reset errno */
long tmp = strtol (nptr, &endptr, 10); /* convert w/strtol */
if (nptr == endptr) { /* no ASCII digits coverted to a number */
fputs ("error: no digits converted.\n", stderr);
return 0;
}
else if (errno) { /* error in converstion, under/overflow */
fputs ("error: under/overflow occurred in conversion.\n", stderr);
return 0;
}
/* conversion outside range of int */
else if (tmp < INT_MIN || INT_MAX < tmp) {
fputs ("error: conversion out of range of integer.\n", stderr);
return 0;
}
m[row][col] = tmp; /* assign tmp to m[row][col] */
nptr = endptr; /* update nptr to endptr */
}
}
return 1;
}
If an error occurs, you will know exactly what caused the failure. Look things over and let me know if you have further questions.
uj5u.com熱心網友回復:
很多問題:
永遠不要使用
while(!feof(file)){. 而是檢查的回傳值fscanf(file, ...)不要在沒有
"%s"寬度限制的情況下使用。不要
line在沒有先初始化/分配它的情況下使用傳遞給函式。i從未增加。fclose(file)完成后。檢查成功
fopen(...);
GTG,也許以后會更多。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/406076.html
標籤:
上一篇:動態記憶體分配和多執行緒
