Archived

This topic is now archived and is closed to further replies.

Zorbfish

Parsing Files

Recommended Posts

I wrote this up quick just to see how I would have to parse my data. Now I''m trying to clean up this code and make it much more managed. What would you suggest??? Right now I was thinking about creating a class with database-like behavior that holds all the known params of each type. Then I could just pass the type name and load accordingly.
  
void Map::Load(string file)
{
	
	ifstream	input;
	string		type_name, param_name, eat;
	int		room_id;
	int		exit_ids[4];
	string		room_name;
	string		room_description;
	string		exit_names[4];
	Room		new_room;


	input.open(file.c_str());

	if(input.fail())
		cout << "No file";
	else
	{
		input >> type_name;

		while(!input.eof() && !input.fail())
		{

		///////////////////////////////////////////////

		// type - ROOM

		///////////////////////////////////////////////

			if(type_name == "room")
			{
				input >> eat;	// eat bracket

				input >> param_name;

				while(param_name != "}")
				{
					/////////////////////////////////////

					// param - ID

					/////////////////////////////////////

					if(param_name == "id")
					{
						input >> eat;
						input >> room_id;
					}
					/////////////////////////////////////

					// param - NAME

					/////////////////////////////////////

					if(param_name == "name")
					{
						input >> eat;
						input.ignore(1);
						getline(input, room_name, ''\n'');
					}
					/////////////////////////////////////

					// param - DESCRIPTION

					/////////////////////////////////////

					if(param_name == "description")
					{
						input >> eat;
						input.ignore(1);
						getline(input, room_description, ''\n'');
					}
					/////////////////////////////////////

					// param - NORTH

					/////////////////////////////////////

					if(param_name == "north")
					{
						input >> eat;
						input.ignore(1);
						getline(input, exit_names[North], '','');
						input >> exit_ids[North];
					}
					/////////////////////////////////////

					// param - SOUTH

					/////////////////////////////////////

					if(param_name == "south")
					{
						input >> eat;
						input.ignore(1);
						getline(input, exit_names[South], '','');
						input >> exit_ids[South];
					}
					
					input >> param_name;
				}

				input >> type_name;
			}

		}
}
}
  

Share this post


Link to post
Share on other sites
??? I know its file io, what I was asking is there a way to design my code to make it more organized as in its current state, IMO, its rather disorganized. :/

btw here''s a sample of how I setup my file

room
{
id = 1
name = House1
description = You entered a small house you catch a glance at an old man rocking in a chair
north = Stairs, 2
south = Outside, 3
}

Share this post


Link to post
Share on other sites
Simplest way is using the STL map class.

  
class Object
{
public:
void Load(ifstream & file);
map<string,string> mData;
};

void Object::Load(ifstream & file)
{
while (!file.eof())
{
char tmp[256];
file.getline(tmp,255);
string str = tmp;
if (str.empty())
continue;
else
{
//break up the string here into words - ask if u need help with this

mData[word1] = word2;
}
}
}

This is a pretty simple (read incomplete) example, but I''ve found this method to be by far the most flexible in file I/O (especially for text-based games).

Hope it helps

Share this post


Link to post
Share on other sites

  
vector<string> Breakup(string str, char sep)
{
vector<string> ret;
if (str.empty())
return ret;

string word = "";
bool quote = false;

for (int i = 0; i < str.length(); ++i)
{
if (str[i] == ''"
'')
quote = !quote;
if (str[i] == sep && !quote)
{
if (!word.empty()) ret.push_back(word);
word = "";
} else
{
word += str[i];
}
}

if (!word.empty())
ret.push_back(word);

return ret;
}

class Object
{
public:
void Load(ifstream & file);
map<string,string> mData;
};

void Object::Load(ifstream & file)
{
while (!file.eof())
{
char tmp[256];
file.getline(tmp,255);
string str = tmp;
if (str.empty())
continue;
else if (str == "
{")
continue;
else if (str == "
}")
break;
else
{
vector<string> word = Breakup(str,'' '');
mData[word[0]] = word[2]; //word[1] is the = sign

}
}
}

class World
{
public:
void Load(ifstream & file);
list<Object> lObjects;
};

void World::Load(ifstream & file)
{
while (!file.eof())
{
char tmp[256];
file.getline(tmp,255);
string str = tmp;
if (str.empty())
continue;
else if (str == "
object")
{
Object o;
o.Load(file);
lObjects.push_back(o);
}
}
}

Slightly more complete example - let me know if u don''t understand anything (very likely considering the way I code ).

Share this post


Link to post
Share on other sites
I see, thanks admiral that''s a great design. And just to clarify because I haven''t used maps that much.

mData[word[0]] = word[2]; //word[1] is the = sign

This is essentially telling the map to lookup the param stored in it and assign the value, correct? Where the string was broken into 3 pieces:

0 - Parameter name
1 - seperator
2 - Value

Share this post


Link to post
Share on other sites