Jump to content
  • Advertisement
Sign in to follow this  
d h k

Simple: Loading strings from file...

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everybody, I have a rather simple problem, but somehow I can't manage to get around it. I have a working sidescrolling-shooter game and now I want to add levels. I use a simple text file for storing the level information. At the moment, I only have three pieces of information in this level file: what image to use as background for this level, what image as middleground and what as foreground. This is important because I want each level to be looking different from the last one. I use three layers, because I use parallax scrolling. Anyways, later on, I will also add information about the position and type of enemies etc. to this file, but that's not the point right now. I want to read the filenames for my image files for all three layers. The level file looks exactly like this at the moment:
[images]
background: sprites/background.bmp
middleground: sprites/middleground.bmp
foreground: sprites/foreground.bmp
And this is the code, with which I try to load this information (those three strings) into my program (straight from my level.load-function):
void clevel::load ( SDL_Surface *screen_surface, const char* filename )
// loads a level from a level file
{
	FILE	*file;
	char	line[255];
	string	background_filename;
	string	middleground_filename;
	string	foreground_filename;
	int		enemy_count;
	
	// open the file
	file = fopen ( filename, "rt" );

	if ( !file )
	// if there was an error 
		return_error ( "Failed to load level..." );

	// read first line and ignore it
	read_string ( file, line );

	// read second line and scan background filename
	read_string ( file, line );
	sscanf ( line, "background: %s\n", &background_filename );

	// read third line and scan middleground filename
	read_string ( file, line );
	sscanf ( line, "middleground: %s\n", &middleground_filename );

	// read fourth line and scan foreground filename
	read_string ( file, line );
	sscanf ( line, "foreground: %s\n", &foreground_filename );

	// close the file again
	fclose ( file );

	// now initialize the images
	background.init ( screen_surface, background_filename.c_str ( ), 0.3f );
	middleground.init ( screen_surface, middleground_filename.c_str ( ), 0.7f );
	foreground.init ( screen_surface, foreground_filename.c_str ( ), 1.2f );
}


My problem is that the game now crashes, because I didn't read proper values out as filenames. The init-function for the back-, middle- and foreground in the last three lines of the presented code expect const char*-values - but I don't know how to convert the strings into that format properly. I also tried to read out the filenames as const char*-values rightaway using %c instead of %s, but that only seems to work for single tokens and not a series of characters (a string). Any help? I know there has to be some way, but I am just not confident enough with those things yet.

Share this post


Link to post
Share on other sites
Advertisement
Hmm... Okay, could you however give me an example of how to ditch "FILE" for example? I am not yet so experienced with that std::string class.

EDIT: Hey, where has your reply gone, jyk?

Share this post


Link to post
Share on other sites
Quote:
Original post by d h k
Hmm... Okay, could you however give me an example of how to ditch "FILE" for example? I am not yet so experienced with that std::string class.

EDIT: Hey, where has your reply gone, jyk?
I made a mistake in my first post and deleted it; sorry about that. Anyway, the advice to switch to the corresponding C++ classes and functions holds. I'd write out an example, but I don't use this sort of file streaming that much and I'm not sure of the syntax off the top of my head. I'm sure someone else could whip up and example in no time though...

Share this post


Link to post
Share on other sites
You cannot read std::string like that. A std::string is a class and as such it is a record of data that, among other things, contains a (heap!) pointer to character data. If you read dta from a file into a string object like this (i.e. using sscanf), you will not only overwrite the additional data that the string object stores, but also cause an invalid memory access. This is because a std::string implementation will most likely allocate memory to store the character data.
Simply writing data to it is similar to having a plain char* and reading into it without allocating memory first.

Without altering your FILE-based code, a valid solution would look something like this:

void clevel::load ( SDL_Surface *screen_surface, const char* filename )
// loads a level from a level file
{
FILE *file;
char line[255];
char filename[256];
int enemy_count;

// add some more error-handling
bool readOk = true;

// open the file
file = fopen ( filename, "rt" );

if ( !file )
// if there was an error
return_error ( "Failed to load level..." );

// read first line and ignore it
read_string ( file, line );

// read second line and scan background filename
read_string ( file, line );
filename[0] = '\0';
readOk = sscanf ( line, "background: %s\n", filename ) == 1;
if ( readOk )
background.init ( screen_surface, filename, 0.3f );
else {
fclose( file );
return_error ( "Failed to read background image..." );
}

// read third line and scan middleground filename
read_string ( file, line );
filename[0] = '\0';
readOk = sscanf ( line, "middleground: %s\n", filename ) == 1;
if ( readOk )
middleground.init ( screen_surface, filename, 0.7f );
else {
fclose( file );
return_error ( "Failed to read middleground image..." );
}
// read fourth line and scan foreground filename
read_string ( file, line );
filename[0] = '\0';
readOk = sscanf ( line, "foreground: %s\n", filename ) == 1;
if ( readOk )
foreground.init ( screen_surface, filename, 1.2f );
else {
fclose( file );
return_error ( "Failed to read foreground image..." );
}

// close the file again
fclose ( file );
}


You can also use the file streams from the C++ stdlib instead of FILE. This would allow you to use std::string objects instead of fixed size and hence error-prone character arrays (i.e. buffer overflow issues).

HTH,
Pat.

Share this post


Link to post
Share on other sites
Here you go:

#include <fstream>

/* ... */

std::ifstream file("level.txt");
if (!file) {
/* error handling goes here */
std::string skip;
std::string background_filename;
std::string middleground_filename;
std::string foreground_filename;

file >> skip; // [images]
file >> skip; // background:
file >> background_filename;
file >> skip; // middleground:
file >> middleground_filename;
file >> skip; // foreground:
file >> foreground_filename;

background.init ( screen_surface, background_filename.c_str ( ), 0.3f );
middleground.init ( screen_surface, middleground_filename.c_str ( ), 0.7f );
foreground.init ( screen_surface, foreground_filename.c_str ( ), 1.2f );



This is a somewhat crude example, but it will get the job done. More robust code would parse the file in a more generic manner and check for and report any errors encountered. The above should get you started though.

[Edit: darookie's example is a better example of proper error-checking and so forth, but, as he suggests, you'll be better off using the C++ standard library as in the above example. So just combine the two examples and you should be all set :-)]

Share this post


Link to post
Share on other sites
Oh, but now I need to read in some integer values, is therr an easy way to do this with those new functions, or will I need to use "my" old way for numbers?

EDIT: Nevermind! Figured it out on my own... Easy stuff! :)

[Edited by - d h k on June 26, 2006 9:50:33 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!