Reading from file problems

Started by
8 comments, last by Bregma 17 years ago
Hi, i been having problems lately with my reading of a specific file, i am unable to pretty much. I have in my main an array of 12 of a 'struct' of team. but the user can use upto 12, in the actual program so in practice may want 4 teams to fill up a league. thats were the problems come in, i can write the fill fine. but on reading it would freeze up, i think it wants 12 entries into it. altho the function itself, isnt programmed like that. please look and comment please.

team Read(team MyTeams[], int numTeams) {
	FILE * pFile;
	char temp;
	int i = 0; int j = 0;

	pFile = fopen ("league.txt", "r+");
	for(i = 0; i < numTeams; i++) { 
		//j is the characters to fill individually.
		for(j = 0; j <= 19; j++) {
			fscanf(pFile, "%c", &temp);
			if(temp == '\r' || temp == '\n') {j--; continue;}
			if(temp == '.') {
				MyTeams.name[j] = 0; // finishes name
				break;
			}
			else {  MyTeams.name[j] = temp; }
		}
		fscanf (pFile, "%i", &MyTeams.Played);
		fscanf (pFile, "%i", &MyTeams.Win);
		fscanf (pFile, "%i", &MyTeams.Draw);
		fscanf (pFile, "%i", &MyTeams.Loss);
		fscanf (pFile, "%i", &MyTeams.GoalsFor);
		fscanf (pFile, "%i", &MyTeams.GoalsAgainst);
		MyTeams.GoalDiff = (MyTeams.GoalsFor - MyTeams.GoalsAgainst);
		fscanf (pFile, "%i", &MyTeams.Points);
	}
	fclose (pFile);
	table(MyTeams, numTeams);
	return MyTeams[0];
}

Advertisement
I may need to look at what your reading in to tell you for sure, but to me it looks like your putting it into a never ending loop by this line of code.

if(temp == '\r' || temp == '\n') {j--; continue;}

j gets decremented and then continues to the for loop where it immediately gets incremented only to get decremented again.

Well its a hunch anyway.

Adam
Adamhttp://www.allgamedevelopment.com
That code is ungodly. It is very poorly written, and has unclear comments.

The first mistake is writing to and from text files. To do that, you need to translate from data to text, and back again. You said you had a list of 12 structs, why not just write the whole struct to a binary file?

Read this very helpful tutorial, and pay attention to when he writes and reads structs:
http://www.gamedev.net/reference/articles/article1127.asp

The second mistake is the poorly thought out logic of the function. Spend more time clarifying exactly what you are trying to do before doing it. Thirdly, and this one fits with the second, the code formatting makes it even harder to read.

If, for some reason, you need to use plain text files, please look into the strtok function:

http://www.cplusplus.com/reference/clibrary/cstring/strtok.html

It will make your life (and code) much easier. Hope this helped.
Sure is a big 'ol world.
ok thanks for help.

cleaned up my code abit, now i can't see what is wrong with it.

the file it saves to basically is

[name]
[played]
[win]
etc
to
[total points]

latest code is :

void Read(team MyTeams[], int numTeams) {	FILE * pFile;	char temp;	int i = 0; int j = 0;	pFile = fopen ("league.txt", "r+");	//numTeams bigger than i.  i = team.  numTeams = amount of teams want from league.	for(i = 0; i <= numTeams; i++) { 		//j is the characters to fill individually.  20 characters in the team's name, so goes		//around 20 times, filling each and every character.		for(j = 0; j <= 19; j++) {			//gets a character from file.			fscanf(pFile, "%c", &temp);			if(temp == '\r' || temp == '\n' || temp == '\0') { j=20; } //j--; continue;}			//if(temp == '.') {			//	MyTeams.name[j] = 0; // finishes name			//	break;			//}			//if(temp == '\n' || temp == '\0') { break; }			else {  MyTeams.name[j] = temp; }		}		fscanf (pFile, "%i", &MyTeams.Played);		fscanf (pFile, "%i", &MyTeams.Win);		fscanf (pFile, "%i", &MyTeams.Draw);		fscanf (pFile, "%i", &MyTeams.Loss);		fscanf (pFile, "%i", &MyTeams.GoalsFor);		fscanf (pFile, "%i", &MyTeams.GoalsAgainst);		MyTeams.GoalDiff = (MyTeams.GoalsFor - MyTeams.GoalsAgainst);		fscanf (pFile, "%i", &MyTeams.Points);	}	fclose (pFile);	table(MyTeams, numTeams);	//return MyTeams[0];}


now can someone instruct and teach me whats wrong with the above. i personnally believe should be working just looks right to me.

it compiles. runs but values in the program are like -453232 etc, im guessing for some reason, it's not searching the data properly but how comes ??
You have to step through the logic. You seemed to have ignored my advice about binary structs and strtok, so I guess I'll explain what is wrong with the logic.

Lets step through the code for the file with the name, "braves", and all stats at 0:



- Opens the file
- numTeams is 1, only the braves are in the file
- the for j loop goes the first time, getting the letter B into temp, the first to ifs fail
- mystems[0].name[0] = 'B'
- The loop does that 5 more times
- The fscanf reads in a newline character
- (j is 6), j is set to 20
- The loop breaks out (the name never recives a delimeter '\0')
- It reads in a bunch of ints.

Because I do not know what the actual file looks like, I can't say what else could be causing a problem. Do you have the [ and ] around each item? Let me paraphrase the tutorial I linked already:

//substitute your team structstruct OBJECT{   int number;   char letter;} obj;//set the values inside of the programobj.number = 15;obj.letter = ‘M’;//with file out, write the object outfout.write((char *)(&obj), sizeof(obj));


The line (char *)(&obj) may be confusing, but don't worry about the specifics. Do you understand how this is much easier then parsing text? Here is how simple your load function will be if you write out to a binary file:

for(int i = 0; i < numTeams; i++){    fin.read((char *)(&tempTeam), sizeof(TEAM));    myTeams = tempTeam;}
Sure is a big 'ol world.
i apprecaited your help, but specification states must write out to .txt file, but appreciate you took the time, and your way i understoof just that can't really use, altho its clear would be alot easier :/

do you reckon its because doesnt receive a '\0'?
the file doesnt have any [] brackets round literally looks like

Newcastle Utd
0
0
0
0
0
0
0
0
//next team

doing head in, as i personally believe not much is wrong. What happens is does the first time PERFECTLY just rest have dodgy characters. so think it doesnt want to read the team names anymore after the first loop. as has weird characters :(
Instead of reading the name character by character, just use fgets. It reads in a string until it hits a newline of end of file.

http://www.cplusplus.com/reference/clibrary/cstdio/fgets.html

char * fgets ( char * str, int num, FILE * stream );


So just nix the j loop and use this function. Hope that helped.
Sure is a big 'ol world.
thanks defo helped. still not properly right.. new code looks like :

void Read(team MyTeams[], int numTeams) {	FILE * pFile;	char temp[20];	int i = 0; int j = 0;	pFile = fopen ("league.txt", "r+");	//numTeams bigger than i.  i = team.  numTeams = amount of teams want from league.	for(i = 0; i < numTeams; i++) { 		fgets(MyTeams.name, 21, pFile);		printf("%s \n", &MyTeams.name);		fscanf (pFile, "%i", &MyTeams.Played);		fscanf (pFile, "%i", &MyTeams.Win);		fscanf (pFile, "%i", &MyTeams.Draw);		fscanf (pFile, "%i", &MyTeams.Loss);		fscanf (pFile, "%i", &MyTeams.GoalsFor);		fscanf (pFile, "%i", &MyTeams.GoalsAgainst);		fscanf (pFile, "%i", &MyTeams.GoalDiff);		fscanf (pFile, "%i", &MyTeams.Points);	}	fclose (pFile);}


as you can see above i print the team name after fgets, ok, well when i run the program has the name of every single team i want. so result ! BUT has 3 lines seperating them which really shouldnt happen :S

the output when try output table looks like


P W D L F A GD T
a
0 0 0 0 0 0 0 0

1999309359 4 0 -1036575779 -1 36 1244420 1244988
b
0 0 0 0 0 0 0 0

7667820 7471205 6029427 6357060 6619245 6029361 7536725 6619244

any ideas please, cant see for life of me whats up .. :S
You're really just going to have to debug the program, step through it, and see where it is going wrong. I can only say so much because I don't have to full program, and really have no interest in debugging it if I did. Just set a break point and figure out what is going wrong.

The only thing I can see, it what is %i for? Use %d for integers.
Sure is a big 'ol world.
Quote:Original post by Foot Soldier
The first mistake is writing to and from text files. To do that, you need to translate from data to text, and back again. You said you had a list of 12 structs, why not just write the whole struct to a binary file?


I would say the use of text files was the first thing he did correctly. It has been my experience over my decades as a professional programmer that unless you have very good reason and enough experience, all data should be stored or transmitted as text. It makes debugging and portability many orders of magnitude easier.

The C-language facilities for reading and writing data from or to a text stream are well documented and relatively simple to use. The original post, in fact, looks like an attempt at the solution to a pedagogical exercise in learning to use those facilities.

As to the original post: try reading each line in to a buffer so it can be printed out for visual inspection, then using sscanf() to parse that buffer instead fscanf().

--smw

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement