Reputation: 819
I've got a file which I need to store in a 2-D array so I can perform matrix operations on it. All I know is that the doubles will be separated by spaces and line breaks, e.g:
2.04 3.0 4.0
5.0 6.1 7.0
8.0 9.03 10.0
I won't know how many numbers there will be, so I need a scalable parsing function. So far I have:
int main(int argc, char* argv[])
{
FILE *fp;
char ch;
fp = fopen("matrix.dat","r");
if ( fp == NULL )
{
puts ( "Cannot open source file");
}
/*count the number of lines*/
int lines=1;
char c;
while((c = fgetc(fp)) != EOF)
{
if(c == '\n')
lines++;
}
printf("lines= %i\n",lines);
/*reopen the file to reset the pointer*/
fclose(fp);
fp = fopen("matrix.dat","r");
double m[lines][lines];
/*Load file into array*/
int i,j;
for(i=0;i<lines;i++)
{
for(j=0;j<lines;j++)
{
fscanf( fp, "%lf", &(m[i][j]));
}
fscanf(fp, "\n", NULL);
}
/*print out stored matrix*/
for(i=0;i<lines;i++)
{
for(j=0;j<lines;j++)
{
printf("%lf ",m[i][j]);
}
printf("\n");
}
}
My issues with this method are
It makes the assumption that the number of rows equals the number of doubles per line, which may not be true.**
Any missing doubles in the file will cause the program to load the wrong matrix into memory (remaining values offset by 1).
I'm currently loading the file into memory twice to count the lines.
Is there a more sensible way to input this data into a 2D array? I need to ensure that the input matrix is square and that my program can handle a square matrix of any order. I'm quite new to C, so examples and naming functions will be much appreciated :) (Apologies for the dodgy indenting)
** Sorry for being so vague, I wanted some error handling, i.e making sure the input is not accepted unless there are exactly nxn doubles.
Upvotes: 3
Views: 7663
Reputation: 1637
Like Nicolas, I'm curious what you mean by point (1)...if the matrix is square, then won't the number of rows always equal the number of doubles per line? If not, then I suppose you could look through the file for the row with the most values.
Here's your code modified to do that:
/* count the number of lines */
int lines = 1;
int maxValues = 0;
int count = 0;
char junk;
while((junk == fgetc(fp)) != EOF) {
if(junk == '\n') {
lines++
if(maxValues <= count) {
maxValues = ++count;
}
count = 0;
}
else if(junk == 0x20) {
count++;
}
}
To address point (2), maybe try this modification:
/* load file into array */
int i, j;
for(i = 0; i < lines; i++) {
j = 0;
do {
fscanf(fp, "%lf", &(m[i][j]));
j++;
} while((junk = fgetc(fp)) != '\n');
}
Finally for point (3), I'm pretty sure you can use rewind(fp);
to reset the pointer to the beginning of the file.
Upvotes: 4
Reputation: 108978
fgets
n
n * n
n - 1
lines of n
values eachVoila!
Upvotes: 0