Valhalla Legends Forums Archive | Battle.net Bot Development | [C++] Parsing warcraft 3 statstring

AuthorMessageTime
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.

[code]
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;
}
[/code]

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)
[/quote]

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?
May 17, 2005, 6:48 AM
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'.
May 17, 2005, 3:41 PM
Zakath
Also note that your function leaks memory.
May 17, 2005, 3:43 PM
UserLoser.
[quote author=Okee link=topic=11607.msg112711#msg112711 date=1116312496]
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.

[code]
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;
}
[/code]

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)
[/quote]

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?
[/quote]

You forgot "tournament" as a best race.  Also, try using %c instead of %d
May 17, 2005, 6:38 PM
Kp
[quote author=Zakath link=topic=11607.msg112725#msg112725 date=1116344598]
Also note that your function leaks memory.
[/quote]

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.
May 17, 2005, 9:24 PM
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.

[code]
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;
}
[/code]
May 18, 2005, 3:32 AM
UserLoser.
Actually, 'D' is tournament, not 'T'.
May 18, 2005, 4:16 AM
Kp
[quote author=Okee link=topic=11607.msg112834#msg112834 date=1116387134]
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.[/quote]

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:
[code]switch (i) {
    case 0:
        pstr = "foo";
        break;
    case 1:
        pstr = "bar";
        break;
}
strcat(buf, pstr);[/code]

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. :)
May 18, 2005, 3:19 PM

Search