问题
I'm trying to read from a file and print out what's in the file. Data in file is something like the following and consist of 100 rows and 10 columns.
-1,0.53,1,1,1,0,0.8,1,0.5,0
Here is what I have tried:
#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFINPUT 100 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.
int main(){
int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
FILE *dataFileptr;
dataFileptr = fopen("group5_8.txt", "r");
if (dataFileptr == NULL){
perror("Error");
return 1;
}
for(int i = 0; i < NUMBEROFINPUT; ++i){
for(int j = 0; j < NUMBEROFCOLUMN; ++j){
fscanf(dataFileptr, " %f", &dataFileInput[i][j]);
printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);
}
}
}
However, I'm only getting 0.00
when I print out the result. I'm still rather new to C programming. What am I doing wrong?
回答1:
You should change the following line:
int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
as follows:
float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
Alternatively, you can declare the array as double
and read using %lf
I also had to skip the commas as follows:
#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFINPUT 100 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.
int main(){
float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
FILE *dataFileptr;
dataFileptr = fopen("group5_8.txt", "r");
if (dataFileptr == NULL){
perror("Error");
return 1;
}
for(int i = 0; i < NUMBEROFINPUT; ++i){
for(int j = 0; j < NUMBEROFCOLUMN; ++j){
fscanf(dataFileptr, "%f", &dataFileInput[i][j]);
fgetc(dataFileptr);
printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);
}
}
fclose(dataFileptr);
}
Note the call to fgetc
.
For the sake of completion, I would like you to note that the reading is successful even when using an int* array. The printing fails because the data is interpreted as an int* and then converted to a float. To interpret the bytes stored in the int* array element, first cast the address of the element to a pointer to float, then get the value of the float stored at this address. Same code except for the print statement.
#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFINPUT 100 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.
int main(){
int *dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
FILE *dataFileptr;
dataFileptr = fopen("group5_8.txt", "r");
if (dataFileptr == NULL){
perror("Error");
return 1;
}
for(int i = 0; i < NUMBEROFINPUT; ++i){
for(int j = 0; j < NUMBEROFCOLUMN; ++j){
fscanf(dataFileptr, "%f", &dataFileInput[i][j]);
fgetc(dataFileptr);
printf("a[%d][%d] = %.2f\n", i+1,j+1, *((float *) &dataFileInput[i][j]));
}
}
fclose(dataFileptr);
}
回答2:
You can follow another approach also using getline
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBEROFINPUT 2 //100 inputs.
#define NUMBEROFCOLUMN 10 //10 rows.
int main(){
int i, j;
float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
FILE *dataFileptr;
char* aline = NULL;
size_t size = 0;
dataFileptr = fopen("group5_8.txt", "r");
if (dataFileptr == NULL){
perror("Error");
return 1;
}
while(getline(&aline, &size, dataFileptr) != -1)
{
line[strcspn(aline, "\n")] = 0;
char * sep = strtok(aline, ",");
printf("%s\n", sep);
while((sep = strtok(NULL, ",")) != NULL)
{
printf("%s\n", sep);
}
}
return 0;
}
回答3:
Declaring a 2D array and then looping to fill each elements from a file is a horribly fragile way to write an input routine. What happens if there is one float too few? (You invoke Undefined Behavior and all bets are off)
A good approach is a line-oriented approach where you read a row of floats at a time, and then, parse the needed floats from each line with either strtok()
(or if empty fields are possible, strsep()
), or you can use a pair of pointers and strtof()
to work down the line, or with a known fixed number of floats per-line, sscanf()
will do. All allow the validation of each float read.
Can you read one float at a time with fscanf()
? Sure, you just need to keep separate counters and when a row worth of floats are read, reset your column count and increment the row count. Repeat until your run out of rows, or you file ends. Whichever happens first. One other caveat in reading one float
at-a-time is you need some way to validate each row has the correct number of floats. You can do that by setting a separate variable to contain the number of columns in the first row, and then compare the number in each successive row with the first row count.
You could do that as follows:
char c;
int rows = 0, col = 0, cols = 0, rtn;
float dataFileInput[NUMBEROFINPUT][NUMBEROFCOLUMN];
...
while (rows < NUMBEROFINPUT) { /* while less than NUMBEROFINPUT rows */
/* read float saving character that follows and the return */
rtn = fscanf (dataFileptr, "%f%c", &dataFileInput[rows][col], &c);
if (rtn < 1) /* if nothing read or EOF, break */
break;
else if (rtn == 1 || c == '\n') { /* if only float read or next is \n */
col++; /* increment no of col */
rows++; /* increment no. of rows */
if (cols && col != cols) { /* if cols set validate cols no. in col */
fprintf (stderr, "error: unequal number of columns, row: %d\n", rows);
return 1;
}
if (!cols) /* if first row, set no. of cols */
cols = col;
col = 0; /* reset col for next row */
}
else /* both values read and char not '\n' */
col++; /* increment col count */
}
for (int i = 0; i < rows; ++i) /* output results */
for (int j = 0; j < cols; ++j)
printf("a[%d][%d] = %.2f\n", i+1,j+1, dataFileInput[i][j]);
By using the col
and rows
indexes above, you are keeping track of the state of your read. By returning if (cols && col != cols)
, after cols
is set by the first row number of columns, you force all subsequent rows to contain that number of values ensuring your 2D array is completely filled.
Example Use/Output
Seting dataFileptr
to stdin
and reading your example input with stdin
would result in:
$ ./bin/read2Dcsv <<< -1,0.53,1,1,1,0,0.8,1,0.5,0
a[1][1] = -1.00
a[1][2] = 0.53
a[1][3] = 1.00
a[1][4] = 1.00
a[1][5] = 1.00
a[1][6] = 0.00
a[1][7] = 0.80
a[1][8] = 1.00
a[1][9] = 0.50
a[1][10] = 0.00
There are many ways to do this. A line-oriented approach provides the most flexible and robust approach, but you can make a float
at a time approach reasonably flexible as well. Let me know if you have any further questions.
来源:https://stackoverflow.com/questions/64917718/how-to-read-data-from-file-into-two-dimension-array-in-c