Game Development Community

C++ Help (File routines)

by Jason Stevens · in Technical Issues · 05/23/2003 (8:27 am) · 6 replies

I was able to decipher enough information to get file writing to work from all the tutorials out there, but I am having trouble with the reading from a file. Tried a bunch of different tutorials, and still have no clue where to even begin. Here is my save file routine:

void GameApp::SaveChar()
{
	// Character Save Function
	ofstream fout;										
														
	fout.open(Plr.fname);							
														
	fout << "First Name:   " << Plr.fname			  << endl;
	fout << "Last Name:    " << Plr.lname			  << endl;
	fout << "Password:     " << Plr.pword			  << endl;
	fout << "Race:         " << Plr.race			  << endl;
	fout << "Age:          " << Plr.age				  << endl;
	fout << "BirthYear:    " << Plr.birthyear		  << endl;
	fout << "Gender:       " << Plr.gender			  << endl;
	fout << "Strength:     " << Plr.stat_strength	  << endl;
	fout << "Agility:      " << Plr.stat_agility	  << endl;
	fout << "Dexterity:    " << Plr.stat_dexterity	  << endl;
	fout << "Willpower:    " << Plr.stat_willpower	  << endl;
	fout << "Charisma:     " << Plr.stat_charisma     << endl;
	fout << "Endurance:	   " << Plr.stat_endurance	  << endl;
	fout << "Constitution: " << Plr.stat_constitution << endl;
	fout << "Wisdom:       " << Plr.stat_wisdom       << endl;
	fout << "Intelligence: " << Plr.stat_intelligence << endl;

	fout.close();										
}

I am looking for a LoadChar function (so I will be able to call the information with Plr.(variable), though a "load specific piece" function might be helpful for later things) (How to make it save the player file into another directory would be helpful as well. Saving the player file "Bob" in "..\player")

One other thing, I am not sure where to begin with Skills. (Skill structure? Skills stored in a file and loaded/searched through as needed/etc..?) I was thinking probably use a structure like my Plr structure, but then I didnt know how to store multiple types of info (say two "players" in the above example into the same file) and retrieve the info again. Any and all help appreciated.

#1
05/23/2003 (3:22 pm)
It's been a while since I've used C++ (and thus I can't remember the exact syntax), but try something like this:

void GameApp::LoadChar()
{
// Character Load Function
ifstream fin;

fin.open(Plr.fname);

fin >> Plr.fname;

//more stuff like that

fin.close();
}
#2
05/23/2003 (3:45 pm)
You probably don't want to use that format for machine-managed files. It's great for people-use, but it tends to get really hard to parse.

Simpler is just writing the bare values with spaces between them.

You might want to get a copy of the source code for a MUD and read through it; a great way to get familiar with I/O of all sorts, as well as good (and bad :) ways to represent data.
#3
05/24/2003 (2:30 am)
That format that Steve used will give you "First". You have to load the entire string, and somehow delete all but the last entry on that line (the actual Plr.fname). I believe it has something to do with ~. Remember old Mud code? Player files always ended the line with ~. Somehow there must be a way to search for a specific character and then get the word right in front of it. That way it bypases the stuff before it:

First Name: ActualName~ (First Name: would be skipped, and ActualName would be gotten because the code went to ~). My problem is, not sure how to make it go to ~. :P What I have done (for now) is just removed First Name: and had it drop each bit of new information on a new line. This is only a temporary solution as it severly limits what I am able to do with my player files. If the actual information is the only thing on the line, then the code Steve suggested will work.
#4
05/24/2003 (3:23 am)
For those interested. Here is working versions of a save and load function with specified directory and formatting:

void GameApp::SaveChar()
{
	// Character Save Function
	ofstream fout;	
	char savefile[32]; 

	sprintf( savefile, "player/%s", Plr.fname ); 

	fout.open(savefile);	
	
	fout << "First Name: " << Plr.fname	<< endl;
	fout << "Last Name: " << Plr.lname << endl;
	fout << "Password: " << Plr.pword << endl;
	fout << "Race: " << Plr.race << endl;
	fout << "Age: " << Plr.age << endl;
	fout << "BirthYear: " << Plr.birthyear << endl;
	fout << "Gender: " << Plr.gender << endl;
	fout << "Stats: " << Plr.stat_strength << " "
	     << Plr.stat_agility << " "
	     << Plr.stat_dexterity << " "
	     << Plr.stat_willpower << " "
	     << Plr.stat_charisma << " "
	     << Plr.stat_endurance << " "
	     << Plr.stat_constitution << " "
	     << Plr.stat_wisdom << " "
	     << Plr.stat_intelligence << endl;

	fout.close();										
}

And the LoadChar

void GameApp::LoadChar(char name[20])
{
	// Character Load Function
	ifstream fin;	
	char loadfile[32];
	
	sprintf( loadfile, "player/%s", name );

	fin.open(loadfile);

	if (fin.bad())
	{
		GameApp::CharGen();
		return;
	}
	
	fin.ignore(256,':');
	fin >> Plr.fname;
	fin.ignore(256,':');
	fin >> Plr.lname;
	fin.ignore(256,':');
	fin >> Plr.pword;
	fin.ignore(256,':');
	fin >> Plr.race;
	fin.ignore(256,':');
	fin >> Plr.age;
	fin.ignore(256,':');
	fin >> Plr.birthyear;
	fin.ignore(256,':');
	fin >> Plr.gender;
	fin.ignore(256,':');
	fin >> Plr.stat_strength
	    >> Plr.stat_agility
	    >> Plr.stat_dexterity
	    >> Plr.stat_willpower
	    >> Plr.stat_charisma
	    >> Plr.stat_endurance
	    >> Plr.stat_constitution
	    >> Plr.stat_wisdom
	    >> Plr.stat_intelligence;

	fin.close();
}
#5
05/24/2003 (7:11 am)
Why are you storing the text for the meaning of the values? For a single save file it is probably not a big waste of space but it is poor programming practice to waste space in this manner. There is no need to store the same descriptive data over and over.

If the reason is to make it more readable then I would argue that the statistics fields are the ones thtat should be documented. I am unlikely to make a mistake about what the persons name is, but I am very likely to forget the order of the stats in a month or so.

I would suggest that you define each field and then accept a value into that field. Next, trim leading and trailing spaces (If your version of C++ doesn't do it automatically) and store that result to your save file. Document the order of the fields outside of the saved file.

If you feel it is necessary to include the descriptions then they should be written out once at the beginning of the file then follow them with the data. Preface it with a number which is the number of fields in the record. Now you know how many descriptions you have to load, how many fields per record and using a simple multiply you know how many lines to read to get to any arbitary record.
#6
05/24/2003 (8:13 am)
I realize you wouldnt want it like this for larger games, but for this one, I am just trying to get the hang of the functions. (formatting included, so those are merely there to give me another obstacle to overcome). Storing just the plain values would probably be fine for multiplayer games, and other things.

This is my first actual project. So things are not going to be perfect. :P Thanks for the info though. Any suggestions on things I should learn before trying to do a 2d/3d project? I am still getting the hang of the file routines and some other things, but I am close to being able to move on to something else. (I want to get this game to at least a "playable" stage. Version 1.0 will be one room (at least) with a few skills, a basic combat system, and a monster to fight).