Using fstream to read & display data in a struct...

Started by
5 comments, last by cdxrd 17 years, 11 months ago
Alright, been perusing through some books tonite since I have decided to store some of my preferences and high scores and all in a file in the game directory. Ive got some code I managed to come up with that properly saves the data and can read it back in, but maybe im just not displaying the info right... Heres the code:

#include <fstream>
#include <string>
#include <iostream>

using namespace std;

int myexit = 0;
int menu();
int numElements = 6;
void writefile();
void readfile();

struct pref
{
	string setting;
	int value;
};

ostream& operator << (ostream& str_out, pref& d)
{
	str_out << d.setting << endl;
	str_out << d.value << endl;
	return(str_out);
};

istream& operator >> (istream& str_in, pref& d)
{
	str_in >> d.setting;
	str_in >> d.value;
	return (str_in);
}

int main()
{
	while (myexit < 3)
	{
		int choice = menu();
		if(choice == 3)
		{
			myexit = 3;
		}
		if(choice == 1)
		{
			writefile();
		}
		if(choice == 2)
		{
			readfile();
		}
	}
	return (0);
}

int menu()
{
	int x;
	cout << endl << "Please Select" << endl << "_____________" << endl 
        << endl << "1) Write File" << endl << "2) Read File" << endl 
        << "3) Quit" << endl << endl << "? : ";
	cin >> x;
	return (x);
}


void writefile()
{
	struct pref preferences[6] = 
	{
		{"VideoMode",1},
		{"MusicVolume",1},
		{"EffectVolume",1},
		{"TopScore1",25},
		{"TopScore2",20},
		{"TopScore3",10}
	};
	int x;
	char filename[20] = "prefs.dat";
	int mode = (ios::out | ios::binary);

	fstream fout(filename, mode);
	for (x = 0; x < numElements; x++)
	{
		fout << preferences[x];
	}
	fout.close();

	cout << "Data written to file..." << endl;
}

void readfile()
{
	char filename[20] = "prefs.dat";
	struct pref preferences;
	int mode = (ios::in | ios::binary);

	fstream fin(filename, mode);
	if(!fin)
		cerr << "unable to open file!";

	cout << endl;
	while (fin >> preferences)
	{
		cout << preferences;
	}
	cout << endl << endl << "____________________________________" << endl << endl;

	int x;
	for (x = 0; x < numElements; x++)
	{
		cout << "Setting : ";
		cout << preferences.setting;
		cout << " -=- ";
		cout << preferences.value;
		cout << endl;
	}

	cout << endl;

	fin.close();
}


Now, It saves it properly and it even loads and displays it as it loads properly. But what I need is to be able to display the contents of the struct itself, basically walking through it one element at a time and displaying the setting and the value. Obviously Im doing something wrong, but what?

Squiggly Frog - My little project place on the web. Updated as I see fit. =)

Advertisement
Can you give an example of the way you wanted it to be displayed?
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Its stored in the prefs.dat file like this:

VideoMode
1
MusicVolume
1
EffectVolume
1
TopScore1
25
TopScore2
20
TopScore3
10

And this is the way I would prefer to be able to display it:

VideoMode -=- 1
MusicVolume -=- 1
EffectVolume -=- 1
TopScore1 -=- 25
TopScore2 -=- 20
TopScore3 -=- 10

Mind you this is just for my testing and understanding of it. I wont need to display it in the game itself, I will just need to be able to read in and set different values based on whats stored. That part I will work on later.. =) My first game shall have saveable preferences, high scores, the whole 9 yards.. lol.. the gameplay is pretty much already done and works, just adding in options and credits, menu, title screen etc now, and this is the next step.

Squiggly Frog - My little project place on the web. Updated as I see fit. =)

So, something like

std::ostream& operator<<(std::ostream& os, const pref& p){   os << p.setting << " -=- " << p.value << std::endl;   return os;}std::istream& operator>>(std::istream& is, pref& p){   is >> p.setting;   is.ignore(5);    // skips over " -=- "   is >> p.value;   return is;}


Also note the existence of the std::ws manipulator that will skip over leading whitespace, which is sometime useful to do explicitely.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I think the way its saved will work fine, I probably should have reworded it better maybe. Once its saved and then loaded back in (I assume the code I posted is loading it correctly into that struct), how can I walk the items in the struct one by one and display them on the screen so that I can see each was loaded properly?

Squiggly Frog - My little project place on the web. Updated as I see fit. =)

How about doing it in the while loop?
void readfile(){	char filename[20] = "prefs.dat";	struct pref preferences;	int mode = (ios::in | ios::binary);	fstream fin(filename, mode);	if(!fin)		cerr << "unable to open file!";	cout << endl;	while (fin >> preferences)	{		cout << preferences;                cout << "Setting : ";		cout << preferences.setting;		cout << " -=- ";		cout << preferences.value;		cout << endl;	}	cout << endl << endl << "____________________________________" << endl << endl;	fin.close();}


As far as I can see you are not saving your pref structs.
You read one at a time into the preferences variable.
When the while loop is done, all you have is the last pref struct read from the file in the preferences variable.

If you want to write it after reading it all from file, Id sugges saving them in a vector:
void readfile(){	char filename[20] = "prefs.dat";	struct pref preferences;        vector<pref> vec_prefs;	int mode = (ios::in | ios::binary);	fstream fin(filename, mode);	if(!fin)		cerr << "unable to open file!";	cout << endl;	while (fin >> preferences)	{                vec_prefs.push_back(preferences);	}	cout << endl << endl << "____________________________________" << endl << endl;	fin.close();        for(int i=0; i<vec_prefs.size(); i++)        {                // Use the << operator you wrote earlier to print the settings                cout << vec_prefs;                                // Extract and print the settings manually                cout << "Setting : ";		cout << vec_prefs.setting;		cout << " -=- ";		cout << vec_prefs.value;		cout << endl;         }}
Thanks much for the help! I think this is what I was looking for. I had already started throwing out the readfile() code I had and was rewriting it to store it into an array. But I think a vector would work much better for this. I should have thought about that solution already since I'm using what I learned of vectors in my game right now.. Thanx for all the help!

Squiggly Frog - My little project place on the web. Updated as I see fit. =)

This topic is closed to new replies.

Advertisement