I'm trying to read some data from a file then print it out but My code is only reading the first content and then gets stuck in an infinite loop (in the while loop). What am I doing wrong?
My output is just Student: Abby GPA: 3
I'm using Visual Studio 2012.
I am just following an example from my book.
//My data is Abbie 3.4 Oakley 3.5 Sylvia 3.6 Uwe 3.7 Ken 3.8 Aaron 3.9 Fabien 4
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
unsigned int GPA;//GPA
char student[10];//Student
FILE * cfPter;
//Check if file opened
if((cfPter = fopen("data.txt", "r")) ==NULL)
{
puts("File could not be opened");
}
//Read Contents
else
{
puts("Contents of file:\n");
fscanf(cfPter,"%s %f ", student, &GPA);
}
//While not at end Print the contents read
while(!feof(cfPter))
{
printf("Student: %s GPA: %f",student,GPA);
fscanf(cfPter, "%s %f", student, GPA);
//system("pause");
}
fclose(cfPter);
system("pause");
} //end main
You are getting there, but a couple of tweaks can make life easier. First, if your fopen
fails, either handle the failure by prompting for another file name, or simply return
(exit
) at that point. That way the rest of your code isn't wrapped inside an else
statement.
Next, I provided the link for why while (!feof(file))
is always wrong (when reading character data from a file). When you read input, validate you received input -- that is really all you need to do. Check the return for your fscanf
call.
With that in mind, you could do something similar to the following:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void) {
float GPA = 0.0; /* GPA */
char student[10] = ""; /* Student */
FILE *cfPter = NULL;
/* open file/validate file is open */
if (!(cfPter = fopen ("data.txt", "r"))) {
fprintf (stderr, "error: file open failed 'data.txt'.\n");
return 1;
}
/* Read Contents */
while (fscanf (cfPter, " %9s %f", student, &GPA) == 2)
printf ("Student: %-10s GPA: %.2f\n", student, GPA);
fclose (cfPter);
return 0; /* main is type 'int' and returns a value */
}
Example data.txt
$ cat data.txt
Abbie 3.4 Oakley 3.5 Sylvia 3.6 Uwe 3.7 Ken 3.8 Aaron 3.9 Fabien 4
Example Use/Output
$ ./bin/feofissue
Student: Abbie GPA: 3.40
Student: Oakley GPA: 3.50
Student: Sylvia GPA: 3.60
Student: Uwe GPA: 3.70
Student: Ken GPA: 3.80
Student: Aaron GPA: 3.90
Student: Fabien GPA: 4.00
(note while MS will let you use void main
from long ago, main
is defined as type int
and returns a value. )
Also to pause
, you generally #include <conio.h>
on windows and call getch();
to prevent the terminal window from closing. You can try it either way. Let me know if you have questions.
I'm working on this as well, and someone told me to try using strcmp() to read the file line by line until you found the line you were looking for? I'm working with that idea but haven't figured out how it would be able to read the GPA after that.
one plan to avoid reading different types of date in the fscanf is to always read char data into a local char array. then use sscanf to convert it to the data type you need. this allows you to add data checks between the fscanf and sscanf. this will avoid fscanf reading nothing (spinning wheels) and never getting to eof