Jump to content
  • Advertisement
Sign in to follow this  
Hexed

C Strings (ugh)

This topic is 4839 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

I am not good with strings in C, please tell me how you would go about the solution: Textures are loaded into a game engine, and if the filename(s) provided starts with an underscore ('_') it is interpreted as an animation. The name of the animation is provided as a string and follows the template "_name_nnn.ext", where nnn is a three-digit number containing the number of frames in the animation, and ext is the file extension. The corresponding animation frames are named similarly, e.g. "_name_000.ext" would be the first frame. How would you extract the number of frames from the string? How would you construct a string for the filename of each animation frame? Currently my code is a mess and I just think I'm going about it the wrong way. I dare not show the original function this came from, so I've made a sample program outlining the current state of things, take a look:
int main (void)
{
	char strGivenName[256], strFrameName[256];
	char strNumFrames[4], strFileExtension[4];
	int i, intNumFrames;
	size_t fnlen;

	// clear arrays
	memset (strNumFrames, NULL, 4);
	memset (strFileExtension, NULL, 4);

	// This will be the filename provided
	strcpy (strGivenName, "data/textures/_animation_030.png");

	// Get string lenth so we can extract frame count and extension later
	fnlen = strlen (strGivenName);

	// Copy frame count only into another string
	strncat (strNumFrames, &strGivenName[fnlen-7], 3);

	// Then use sscanf to convert to integer
	sscanf (strNumFrames, "%d", intNumFrames);

	// Then save the file extension to another string
	strncat (strFileExtension, &strGivenName[fnlen-3], 3);
	
	// Now we have the information needed to produce the actual filenames
	for (i = 0; i < intNumFrames; i++)
	{
		// Start out with filename provided
		strcpy (strFrameName, strGivenName);

		// Overwrite the last 7 characters with frame number and extension
		sprintf (&strFrameName[fnlen-7], "%.3d.%s", i, strFileExtension);
		printf ("%s\n", strFrameName);
	}

	return (0);
}

Share this post


Link to post
Share on other sites
Advertisement

int frame;
char num[4];
const char * c = strstr( filename, ".ext" );
num[0] = *(c-3);
num[1] = *(c-2);
num[2] = *(c-1);
num[3] = 0;
frame = atoi( num );

You may need to toy with it, do some things to prevent crashes like make sure c - 3 isn't less than filename's start.

Share this post


Link to post
Share on other sites
Quote:
Original post by Hexed
Hey thanks for reply looks good, is atoi() portable?


atoi is part of the standard C library, so it's pretty well supported.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Yes, it is. (beware: itoa() is not.)


Oh yea that's what I was thinking of. Thanks guys.

Share this post


Link to post
Share on other sites
Well... I would do it in C++ instead (or even better, some other language) :)

But just for educational purposes, let's do it the really hard (but clean - there's really no sense copying things around that much) way:


int main() {
char* input = "data/textures/_animation_030.png";
char* name, *nameindex;
int id = 0;
char* searcher = input;
while (*++searcher); /* find end of string */
name = nameindex = malloc(searcher - input);
if (!name) return -1; /* couldn't grab that memory :( */
/* the difference basically gives us the strlen(). The name can't be any
* longer than the context from which it was fetched */

while (*--searcher != '/'); /* now positioned at last slash */
++searcher; /* skip slash; now positioned on underscore */
while ((*nameindex++ = *++searcher) != '_'); /* copy to underscore */
*--nameindex = '\0'; /* overwrite the underscore */
/* Now searcher is on the second underscore */
while (*++searcher >= '0' && *searcher <= '9') {
id = 10 * id + (*searcher - '0');
}
printf(name);
printf("\n%d\n", id);
free(name);
}



I had 3 problems the first time I typed this in: missing * on nameindex (thus it was the wrong type, producing compile errors), missing guard for the malloc call (this isn't c++ with it's fancy exceptions), and missing free() (bad programmer, no cookie).

Share this post


Link to post
Share on other sites
Hey Zahlman, I think I'll stick with C. Thanks for the added perspective, I love seeing different ways of accomplishing a common goal.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
A better solution to your problem would be to use a header at the beginning of your file.

e.g.

File header description
Magic - 4 bytes of char to indicate file type

if Magic=="ANIM" then
{
Next 4 bytes are length of header
next 4 bytes are frame count
array of offsets to each frame
}
if Magic=="MESH" then
{
...
}
...

So your file would look something like this (I've put actual numbers in {})
ANIM{0x00000100}{0x0000000C}{0x00000100}{0x00000230}{0x00000450}....

Share this post


Link to post
Share on other sites
True, data type should normally be indicated in the file format - however it appears here that "animation" doesn't describe the physical type of data (it's a .png), but instead a logical type - what the data will be used for.

In any case, the parsing problem is likely to persist.

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!