Reputation: 148
I am trying to read arrays from multiple files, and the array size in each file is different. So what I do is, I try to count the number of lines in the file and then store that as the array size.
For example, I have two .txt files, File_1.txt
and File_2.txt
which contain the following data:
0.000 300.00
0.054 2623.3
1.000 300.00
0.000 300.00
0.054 2623.3
0.500 1500.0
1.000 300.00
respectively.
Here is the code that I use:
int main()
{
char filter[1024];
char filename[60];
FILE *fp;
double *T_SR, Z_SR;
for (int i = 1; i < 3; i++)
{
sprintf(filename, "File_%d.txt", i);
fp = fopen(filename, "r");
if (fp == NULL)
{
exit(1);
}
int count = 0;
for (int j = getc(fp); j != EOF; j = getc(fp))
{
if (j == '\n')
{
count = count + 1;
}
}
T_SR = (double *)malloc(count * sizeof(double));
Z_SR = (double *)malloc(count * sizeof(double));
for (int rows = 0; rows < count; rows++)
{
fscanf(fp, "%lf %lf", &Z_SR[rows], &T_SR[rows]);
printf("%lf %lf\n", Z_SR[rows], T_SR[rows]);
if (feof(fp))
{
break;
}
}
}
}
But instead of printing the given array as output, it prints this:
0.0000 0.0000
0.0000 0.0000
I checked the value of count
, it's good. Maybe the problem is simple, but I am not able to find it. Can someone please help?
Upvotes: 2
Views: 129
Reputation: 153517
I try to count the number of lines in the file and then store that as the array size.
Aside from the key rewind()
issue, avoid reading code one way to find line count and another to find the double
s. Far too easy to get a line count that does not match the "line count" of reading two double
s.
Use one approach to find both.
size_t read_SR(size_t count, double *Z_SR, double *T_SR, FILE *inf) {
char line[100];
rewind(inf);
size_t rows;
while (fgets(line, sizeof line, inf)) {
double Z, T;
if (sscanf(line, "%lf %lf", &Z, &T) != 2) return rows;
if (rows < count) {
if (Z_SR) Z_SR[rows] = Z;
if (T_SR) T_SR[rows] = T;
}
rows++;
}
return rows;
}
Usage
// First pass, find size
size_t count = read_SR(0, NULL, NULL, inf);
double *T_SR = malloc(sizeof *T_SR * count);
double *Z_SR = malloc(sizeof *Z_SR * count);
// 2nd pass, save data
read_SR(count, Z_SR, T_SR, inf);
Upvotes: 2
Reputation: 23802
After you ran the whole file with getc
the file indicator will be at the end of the file you must set it back to the beginning before you use fscanf
, you can use rewind
for that.
rewind(fp); //<--
for (int rows = 0; rows < count; rows++)
{
//...
}
Aside from that, other problems exist as Jaberwocky pointed out, among others, like a memory leak issue, and the fact that you don't close your files or check malloc
return, here's how your code could look like (with comments):
double *T_SR, *Z_SR; // fix the pointer issue
//...
char line[1024]; // make sure it's larger than the largest line in the file
while (fgets(line, sizeof line, fp)) // fixes the count issue
{
// doesn't count empty lines, if there are any
if (line[0] != '\n')
{
count++;
}
}
if(count > 0)
{
T_SR = malloc(count * sizeof *T_SR);
Z_SR = malloc(count * sizeof *Z_SR);
if(T_SR == NULL || Z_SR == NULL) // check memory allocation
{
perror("malloc");
return EXIT_FAILURE;
}
rewind(fp);
for(int rows = 0; fscanf(fp, "%lf%lf", &Z_SR[rows], &T_SR[rows]) == 2; rows++)
{
printf("%lf %lf\n", Z_SR[rows], T_SR[rows]);
}
free(T_SR); // free the memory, avoids memory leaks
free(Z_SR);
}
fclose(fp); // and close the file
//...
Upvotes: 3
Reputation: 50802
There are several bugs:
rewind
issue that has been addressed in anastaciu's anwer.double * T_SR, Z_SR
is wrong, it should be double * T_SR, *Z_SR
. I wonder actually if the code you posted is the code you compile.\n
, the count
variable will be 2 and you'll miss the last line.fscanf
returns the number of items read or EOF
. If you had check that, you might have found the problem in your code yourself.feof
check is done too late, if fscanf
encounters en EOF you still print the values that have not bee read due to the EOF condition.Upvotes: 3