Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / [tier2] problem using sprintf with a string

Author
Message
erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 01:25
Hello,

I'm using some code similar to what was discussed back in this thread.

Except this time I'm using a string, rather than an int.

I've been reading C++ docs such as

http://www.cplusplus.com/reference/cstdio/sprintf/
http://gribblelab.org/CBootcamp/9_Strings.html

And feel like what I should be doing is something like this



player.getPlayerName() is a std::string

When I inspect it in my debugger it has the right value in it.

But when it shows up on the screen it ends up being a value like "*/!" or other non standard extended ascii characters.

When I do this it works fine:


When I do this it does not:



But if I inspect the pName variable it has the right value before and after?

So I don't quite understand how its going from a string like "Charlie" to "^@2" .. usually 3 digits ironically?

I thought it was the %s but the documentation seems to say thats for a string, I also tried %c and that only does 1 character (and the wrong one at that).

Int's continue to work fine?

Any insight what I'm doing wrong?

Thanks!

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Sep 2013 01:39
In order to get the actual string from a std::string, you use the c_str() method.

Change this: sprintf(playerNameText, "%s", pName);
to this: sprintf(playerNameText, "%s", pName.c_str());

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 02:11
@ Ancient Lady

That worked perfectly thank you. I had saw some people discussing the .c_str() in stackoverflow but they were kind of insulting to the person asking the question and not very explanatory to the point the reply lacked any kind of context or example (they told the original poster they should spend more time reading documentation for instance)

so those google searches weren't enough to understand the usage well enough.

Thank you kindly for taking the time to help once again!

And here is a screenshot in action:




Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Sep 2013 02:22
Dueling Gems? Cool!

Always glad to help.

If you want to avoid memory leaks with strings generated by AppGameKit functions, you need to remember to clean up after them (this applies to every AppGameKit command that returns a char* value:


Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 02:36
Thanks Ancient Lady for the tip; I'm aware of that -- however every time I try to something like



My application crashes horribly .. so I know I am doing something wrong but as of yet don't know how to figure it out.

My only suspicion is that I do things all in one function ; do I perhaps need to exit out to the sync in the main app loop before I delete it?

Not sure why that would be needed because once I use the agk::SetStringText() command then the char [] array is now no longer needed right?

Hodgey
14
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Sep 2013 03:10 Edited at: 21st Sep 2013 03:13
Quote: "My application crashes horribly .. so I know I am doing something wrong but as of yet don't know how to figure it out."

That's because given your code above, playerNameText is on the stack. Only use delete or delete[] on things that were allocated with the 'new' keyword (ie on the heap). In this case, all char* returned from AppGameKit commands have used the 'new' keyword so you need to clean up after them. It's best to catch all char* returned by AppGameKit in another char* and then free it once you're done with it.



Memory can be tricky at times and takes practice.

Edit- realised that what I said is pretty much what AL said. Practice with allocation and freeing a bit as it's important to know in which area of memory things are stored. As you can see, it can make all of the difference.

erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 03:13
Interesting, I'll have to try that out! Thank you.

Hodgey
14
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Sep 2013 03:19
erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 03:37
Okay Hodgey I did some testing .. your example used an AGK::Str() command to change an int, and I'm using a string so I couldn't follow your example 100%

So what I came up with is this:



std::string pName = player.getPlayerName();
char* playerNameText = new char[256];
sprintf(playerNameText, "%s", pName.c_str());
agk::SetTextString(551,playerNameText);

delete [] playerNameText;


This seems to work but feels like I'm "over doing it" as it takes 5 lines to get it all done; and you did yours in 3? Any refinement tips?

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Sep 2013 03:47
This is not all necessary, since you said that getPlayerName() returns a std::string:


You only need to do this:


Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master
Hodgey
14
Years of Service
User Offline
Joined: 10th Oct 2009
Location: Australia
Posted: 21st Sep 2013 03:56 Edited at: 21st Sep 2013 03:58
Okay, I've whipped up a basic class to handle all of the mess.

Header


Cpp


I've just given it a quick test and seems to work nicely. I did a little memory profiling and it didn't detect any leaks however, I'm on a mac which might use auto-referencing and so it gets cleaned up for me if I leak memory or not.

Anyway, all you have to do is this:


No freeing/deleting on your part, the class should handle it all.

NOTE: only ever use this class on strings returned from AppGameKit commands (or char* which are on the heap).

Don't do this:
AGKString s = "Hello World";

This will cause a crash!

Use them for AppGameKit commands and you should be fine.

@erebusman: regarding your above example, if it is just the name (and no other data like a number with it), couldn't you simply do something like:

agk::SetTextString(551,player.getPlayerName().data());

Edit- AL beat me to it...again

erebusman
12
Years of Service
User Offline
Joined: 23rd Jul 2011
Location: Sacramento, CA
Posted: 21st Sep 2013 04:04
@Ancient Lady : AAAAHhhhhh , funny I got so tied up in the old way once you showed me the c_str() bit I was so far gone I never tied back in I could do it that way!

@Hodgey: Thats pretty awesome ; I think I may still have a use for something like that and the way you did it is a superb example of making a helper class to do common tasks that I have to do with AppGameKit ; I hadn't thought of that either.

Thank you both great learning thread for me; hopefully some others read it and get a few useful tips too!

Ancient Lady
Valued Member
20
Years of Service
User Offline
Joined: 17th Mar 2004
Location: Anchorage, Alaska, USA
Posted: 21st Sep 2013 05:09
Hodgey, that is a very nice class. I just might use it. Thank you.

erebusman, we all get that way sometimes. It helps to occasionally walk away from code and come back the next day (I have a Perl script that is giving me fits like that right now, it will work tomorrow).

Cheers,
Ancient Lady
AGK Community Tester and AppGameKit Master

Login to post a reply

Server time is: 2024-05-09 04:30:19
Your offset time is: 2024-05-09 04:30:19