• Welcome to Valhalla Legends Archive.
 

[C++] Parsing warcraft 3 statstring

Started by Okee, May 17, 2005, 01:48 AM

Previous topic - Next topic

Okee

Hey guys. Thanks for all the help so far, by the way. I really appreciate it.

I'm parsing warcraft 3 roc/tft's statstring - and comming to a problem. I've been looking at a past post by Stealth documenting the statstring format - and I understand it fully. I'm having a problem displaying it in my console though - here's the code, then I'll explain my problem.


char *ParseW3Stats(char *stats)
{
static const char *war3races[] = {
"random",
"humans",
"orcs",
"undead",
"night elves",
"unknown"
};

char IconRace, IconTier;
char *statbuf = new char[512];
memset(statbuf, 0, 512);

if(!strnicmp(stats, "3RAW", 4))
strcat(statbuf, "WarCraft III: Reign of Chaos (");
else
strcat(statbuf, "WarCraft III: The Frozen Throne (");

IconTier = stats[5];
IconRace = stats[6];

strcatfmt(statbuf, "tier-%d %d icon", IconTier, IconRace);

return statbuf;
}


Now, the above code as-is takes the 6th and 7th char of the statstring (tier, race) and puts them into seperate variables. When the program runs, its printed as the following though...

Quote
User: *SomeUser@Lordaeron is here using WarCraft III: Reign of Chaos (tier-49 82 icon)

I figured maybe it was the %d in the strcat function converting it, so I tried to use %s and the program crashed when it got to the point of printing that specific war 3 statstring.

Anyone got some advice?

Kp

Looks ok to me.  Assuming you intended to print out the decimal value of the character in the statstring...? ;)  Remember that ASCII '0' has value 48, not 0.  Based on your output, SomeUser is tier 1 with an icon of 'R'.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Zakath

Also note that your function leaks memory.
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.

UserLoser.

Quote from: Okee on May 17, 2005, 01:48 AM
Hey guys. Thanks for all the help so far, by the way. I really appreciate it.

I'm parsing warcraft 3 roc/tft's statstring - and comming to a problem. I've been looking at a past post by Stealth documenting the statstring format - and I understand it fully. I'm having a problem displaying it in my console though - here's the code, then I'll explain my problem.


char *ParseW3Stats(char *stats)
{
static const char *war3races[] = {
"random",
"humans",
"orcs",
"undead",
"night elves",
"unknown"
};

char IconRace, IconTier;
char *statbuf = new char[512];
memset(statbuf, 0, 512);

if(!strnicmp(stats, "3RAW", 4))
strcat(statbuf, "WarCraft III: Reign of Chaos (");
else
strcat(statbuf, "WarCraft III: The Frozen Throne (");

IconTier = stats[5];
IconRace = stats[6];

strcatfmt(statbuf, "tier-%d %d icon", IconTier, IconRace);

return statbuf;
}


Now, the above code as-is takes the 6th and 7th char of the statstring (tier, race) and puts them into seperate variables. When the program runs, its printed as the following though...

Quote
User: *SomeUser@Lordaeron is here using WarCraft III: Reign of Chaos (tier-49 82 icon)

I figured maybe it was the %d in the strcat function converting it, so I tried to use %s and the program crashed when it got to the point of printing that specific war 3 statstring.

Anyone got some advice?

You forgot "tournament" as a best race.  Also, try using %c instead of %d

Kp

Quote from: Zakath on May 17, 2005, 10:43 AM
Also note that your function leaks memory.

Not necessarily.  It returns a pointer to the allocated memory, so the caller could free it after use.  That's a fairly common practice when the exact size cannot be predicted by the caller.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Okee

Okay. I got it working. It was crashing because the pointer to my character array, for holding the formatted statstring, that was being passed to my parsestatstring function and then to my parsewc3statstring function didn't allocate enough size. It was writing past the end of the variable I guess? Anyways, here's my function incase anyone else needs help on it, or just wants it - or wants to point out better ways of doing it.

I know it's sloppy, but it works. I was thinking of using strtok, or getchr to make it a little cleaner.


char *ParseW3Stats(char *stats)
{
char IconRace, IconTier;
char LevelOne = '0';
char LevelTwo = '0';
char Clan[6];
char *statbuf = new char[512];
memset(statbuf, 0, 512);

if(!strnicmp(stats, "3RAW", 4))
strcat(statbuf, "WarCraft III: Reign of Chaos (");
else
strcat(statbuf, "WarCraft III: The Frozen Throne (");

IconTier = stats[5];
IconRace = stats[6];

strcatfmt(statbuf, "tier-%c ", IconTier);

switch(IconRace) {
case 'R':
{
strcat(statbuf, "random icon, ");
break;
}
case 'N':
{
strcat(statbuf, "night elf icon, ");
break;
}
case 'O':
{
strcat(statbuf, "orc icon, ");
break;
}
case 'U':
{
strcat(statbuf, "undead icon, ");
break;
}
case 'H':
{
strcat(statbuf, "human icon, ");
break;
}
case 'T':
{
strcat(statbuf, "tournament icon, ");
break;
}
default:
{
strcat(statbuf, "unknown icon, ");
}
}

if(strlen(stats) == 11) {
LevelOne = stats[10];
}
if(strlen(stats) == 12) {
LevelOne = stats[10];
LevelTwo = stats[11];
}

strcatfmt(statbuf, "level %c%c", LevelOne, LevelTwo);

if(strlen(stats) > 12) {
strcpy(Clan, stats+12);
strcatfmt(statbuf, " in clan %s", Clan);
}

strcat(statbuf, ")");
return statbuf;
}

UserLoser.

Actually, 'D' is tournament, not 'T'.

Kp

Quote from: Okee on May 17, 2005, 10:32 PM
Okay. I got it working. It was crashing because the pointer to my character array, for holding the formatted statstring, that was being passed to my parsestatstring function and then to my parsewc3statstring function didn't allocate enough size. It was writing past the end of the variable I guess? Anyways, here's my function incase anyone else needs help on it, or just wants it - or wants to point out better ways of doing it.

I know it's sloppy, but it works. I was thinking of using strtok, or getchr to make it a little cleaner.

Ugh!  That's horrible code! :)  Some quick notes: don't use strcpy when copying into a buffer of fixed size.  You run the risk of overrun.  Don't keep calling strlen.  It's a const function, act like it.  Your switch statement always takes the action of "copy a string and break", so you could have the switch itself just figure which string you want to copy, then do the copy down below.  Example:
switch (i) {
    case 0:
        pstr = "foo";
        break;
    case 1:
         pstr = "bar";
         break;
}
strcat(buf, pstr);


Also, take note of Zak's comment and my response - make sure your caller frees the allocated buffer.  For proper paranoia, run the code under valgrind's memcheck and make sure it comes out error free. :)
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!