This topic is 4261 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello everyone, Today I've been working on a loading routine for my game. Since this is just a basic 2d scroller I decided to use text files to hold the settings. I can open the text file just fine and read the characters from it but I am having trouble splitting the strings into usable data. My setting text file looks as follows:
NAME=Megaman
TYPE=PLAYER
X_POSITION=400
Y_POSITION=400
HEIGHT=100
WIDTH=100
TEXTURE=MegamanFit.bmp,14,14,5
RUN=0,10,1,20


Now as I said, I am having trouble splitting the strings into usuable segments. The way I read my data looks as follows:
	ifstream myfile ("example.txt");

if(myfile.is_open()) {

while (!myfile.eof()) {

myfile >> temp;

//process command data using temp here, etc etc

}

}


Now this reads the strings in a char format which I am sure you guys may not agree with. Everywhere I look everyone says to use a string data type and my problem with that is I can not get the c_str() method of the string data type to convert to a regular char * to work with my methods already in use. I would honestly prefer to use the string data type because it is a lot easier to work with when splitting string. When I do try to use it I get "cannot convert parameter 1 from 'const char *' to 'char *'." Any help would be awesome on how to either split chars effectively or get string data types to convert correctly to chars. Oh, also, Ive been splitting chars using the strtok() method but it seems to be more trouble than it's worth so I'm hoping to ditch that method if I get a resolution to the other.

##### Share on other sites
I hope I'm not alone on this, but C++ I/O sucks. I would consider using C functions.

fscanf(...) - works just like printf (more like fprintf). You tell the function which file you are reading from, then you give it a printf-style format string (char*). Then you tell it where to read in the variables by passing pointers to each variable.

Lets say you have this text file:
Megaman
PLAYER
400
400

char buffer1[256], buffer2[256];
float x, y;
fscanf(file, "%s %s %f %f", buffer1, buffer2, &x, &y);

Then convert buffer2 to whatever enumerated type you want. fscanf works great with predefined types, but will not work with enumerations, classes, etc. One thing that I like is all white space is the same. The "%s %s..." will read the first string "Megaman", then it will skip over any combination of spaces, tabs, or newlines before reading the 2nd string.

Now I am in no way suggesting you compile your projects in C. Just use its functions and as long as you don't horribly mix-and-match C with C++, everything will work out fine.

##### Share on other sites
I am by no means a C/C++ expert, but I think I am starting to develop that same opinion. Ive almost got this thing finished and this is the one thing thats been more difficult than the project itself. I'm going to rewrrite a little bit of that procedure and see if it works out better. The reason I was using the "Setting=Value" format is because it is intended to have a level editor associated with it and I thought it would be more user friendly to see those settings. But I plan on making a readme with it so I suppose if they follow instructions they will be ok. Thanks for the help and I'll post my results soon!

##### Share on other sites
You can make
PROPERTIES value
so it is easier for c++ to read, if you dont want to
write the parser.

NAME Megaman

then
fin >> string1; //get NAME
fin >> string2; //get Megaman

##### Share on other sites
Here's my suggestion:

Let's say you have your data as you showed it:
NAME=MegamanTYPE=PLAYERX_POSITION=400Y_POSITION=400HEIGHT=100WIDTH=100TEXTURE=MegamanFit.bmp,14,14,5RUN=0,10,1,20

Now the format you have is as follows:
Identifier = token1, token2, ..., tokenN

Now, you know that the order is as such and each line contains one definition, right? What if you were to parse by tokens, specifically the =, the comma, and the newline? Then you would have all of your tokens in a convient form. On this thread I have a little collection of useful standard C++ library functions. Using a few of those, I came up with this:

#include <iostream>#include <string>#include <fstream>#include <vector>std::vector<std::string> TokenizeString(const std::string& str, const std::string& delim){	using namespace std;	vector<string> tokens;	size_t p0 = 0, p1 = string::npos;	while(p0 != string::npos)	{		p1 = str.find_first_of(delim, p0);		if(p1 != p0)		{			string token = str.substr(p0, p1 - p0);			tokens.push_back(token);		}		p0 = str.find_first_not_of(delim, p1);	}	return tokens;}std::vector<std::string> FileToVector(const std::string& filename, const std::string& tokens = "\n"){	std::ifstream fin(filename.c_str());	return TokenizeString(std::string((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>()), tokens);}int main(int argc, char* argv[]){	// Load this file and tokenize it into a vector using \n	std::vector<std::string> linetokens = FileToVector("test.txt", "\n");		// Make a new vector of vectors based on the number of lines there are in the file	std::vector< std::vector<std::string> > tokens(linetokens.size());	// Loop though the lines and tokenize them	for(int x = 0; x < linetokens.size(); x++)	{		// Now parse each individual line by the = and , delimeters, 		// we know that tokens[x][0] will be the name of the setting, such as "NAME" or "TYPE"		tokens[x] = TokenizeString(linetokens[x], ",=");	}	// Now go though all of the tokens	for(int x = 0; x < tokens.size(); x++)	{		// If we have a Name		if(tokens[x][0] == "NAME")		{			// There should be a total of 2 items with a NAME			if(tokens[x].size() != 2)				exit(-1);			// We know there should be only 1 parameter after a name			std::cout << "The name is: " << tokens[x][1] << std::endl;		}		// If we have a type		else if(tokens[x][0] == "TYPE")		{			// There should be a total of 2 items with a TYPE			if(tokens[x].size() != 2)				exit(-1);			// We know there should be only 1 parameter after a type			std::cout << "The type is: " << tokens[x][1] << std::endl;		}		// ... Add the rest here!	}	return 0;}

Now, if you go though that you can see exactly what is going on. 1st, I go though and load the file into a vector based on new lines, since each entry is only on 1 line. Next, I go though all lines and break up the tokens based on the = and the , since parameters are seperated by ,'s and the entry is seperated by the =. What results is a vevctor of strings that contain all of the tokens.

For example, the line "TEXTURE=MegamanFit.bmp,14,14,5" would be stored as:
TEXTUREMegamanFit.bmp14145

In the vector. Also, you cam see the crude error checking added in, if you know the NAME should only have 1 parameter after it, you can test the size to make sure nothing was added or is missing (don't forget that the identifier itself counts as part of the size, so 1 parameter = 2 items, 2 params = 3 items.)

I hope that helps some, you can make a few improvements as you need, but that's the general idea you are after. Good luck on your game! [smile]

##### Share on other sites

This topic is 4261 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628718
• Total Posts
2984374

• 25
• 11
• 10
• 14
• 14