|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| converting int to const char* |
|
![]() Lith Member since: 10/19/2009 |
||||
|
|
||||
| how would i convert an int to const char* i need to do this because im using the SDL_TTF extention library to render text. i have my to scores(int) and i have my two surfaces(SDL_Surface*) the TTF_RenderText_Solidfunction needs const char* EDIT: the error im getting is this: main.cpp(143) : error C2664: 'TTF_RenderText_Solid' : cannot convert parameter 2 from 'int' to 'const char *' with this code: lscore_spr = TTF_RenderText_Solid(font, lscore, textColor); |
||||
|
||||
![]() rip-off GDNet+ Member since: 3/16/2005 From: Ireland |
||||
|
|
||||
In C++, we use boost::lexical_cast, or std::stringstream:#include <string> #include <boost/lexical_cast.hpp> // ... std::string text = boost::lexical_cast<std::string>(lscore); lscore_spr = TTF_RenderText_Solid(font, text.c_str(), textColor); Or: #include <string> #include <sstream> // ... std::stringstream stream; stream << lscore; std::string text = stream.str(); lscore_spr = TTF_RenderText_Solid(font, text.c_str(), textColor); blog |
||||
|
||||
![]() Lith Member since: 10/19/2009 |
||||
|
|
||||
| Thanks But theres one thing: i have to draw two different scores(pong game) this is my code: //render scores //left stream << lscore; text = stream.str(); lscore_spr = TTF_RenderText_Solid(font, text.c_str(), textColor); text.c_str() = ""; //right stream << rscore; text = stream.str(); rscore_spr = TTF_RenderText_Solid(font, text.c_str(), textColor); text.c_str() = ""; draww(40,40,lscore_spr,screen); draww(40,600,rscore_spr,screen); it just prints one 0 after the other: 00000000000000000 the two score vars(lscore and rscore) are set to 0 i tryed to understand the problem more by using a log file to log what text.c_str() was every time i used it. It came up with something like this: 0 00 000 0000 00000 000000 0000000 00000000 so i thought that this: text = stream.str(); was adding to it so i tyed to set it to NULL after it got the string i needed to use this is the error i got: main.cpp(150) : error C2106: '=' : left operand must be l-value |
||||
|
||||
![]() rip-off GDNet+ Member since: 3/16/2005 From: Ireland |
||||
|
|
||||
The simplest solution is to create a new stringstream every frame, and for each score variable. For example, make a function:std::string toString(int number) { std::stringstream stream; stream << number; return stream.str(); } SDL_Surface *renderNumber(TTF_Font *font, int number, SDL_Color colour) { return TTF_RenderText_Solid(font, toString(number).c_str(), colour); } // ... lscore_spr = renderNumber(font, lscore, textColor); rscore_spr = renderNumber(font, rscore, textColor); // ... blog |
||||
|
||||
![]() Lith Member since: 10/19/2009 |
||||
|
|
||||
| thankyou, but... the compiler is complaining about missing ;in my classes now EDIT: btw it want doing that before i tryed your code |
||||
|
||||
![]() Zahlman Moderator - Game Programming Member since: 1/9/2004 From: Toronto, Canada |
||||
|
|
||||
Quote: There are two conceptual problems here. 1) This: text.c_str() = ""; does nothing useful. The .c_str() member function returns a pointer, after all, so this is just taking the copy of the string's internal pointer and assigning it to point at an empty string. This has no effect on the text pointed at by the string. This is deliberate: you are not supposed to be able to re-point the string's internal pointer. The string is responsible for keeping track of that pointer, not you. If you want to clear out the string, assign to the string. 2) But even then, assigning to the string would have no effect on the stream, because the string 'text' is, again, a copy of the stream's internal string object. Rip-off's code gets around this by re-creating the stream from scratch every time (via calling the function). Notice that he doesn't reset the contents of anything afterward; there is no need to, because the stream is thrown away, and the string can also be thrown away once you've passed its .c_str() to the rendering function. Quote: That's because there's a ; missing somewhere. Error messages include line numbers, which should point you to the right part of the code. You're supposed to be able, by now, to read code and figure out where simple things like this have gone wrong. This kind of problem-solving is more basic than doing stuff like rendering text with SDL, so you should make sure you can do it yourself first. As a general rule, if you post in For Beginners and your code contains the word 'char', you have a bug. std::string roxors teh big one one one one. "OMG! I'm so happy! I have "1 Friends"!!!" -- coldacid "Basically whenever you invoke the dread ellipses construct you leave the happy world of type safety." -- SiCrane "I mean, if you had sex for every time O'Reilly used the word Patriotism you'd be almost as awesome as Chuck Norris." -- tthibault <triforce101> uh im not a noob i finished the game |
||||
|
||||
![]() Lith Member since: 10/19/2009 |
||||
|
|
||||
it said that im missing ; 's on this line:SDL_Surface* LoadImg(blah blah blah); its saying: \func.cpp(10) : error C2143: syntax error : missing ';' before '*' after some google searches i found out that theres proberly a missing ; somewhere in a different file, even though it said it was missing in a different file. I found out that i was missing a ; in a header file Thanks for explaining it to me |
||||
|
||||
![]() stephe Member since: 11/4/2009 From: Zlin, Czech Republic |
||||
|
|
||||
| This may be useful: itoa() Atheron MMORPG |
||||
|
||||
![]() jyk GDNet+ Member since: 10/23/2003 |
||||
|
|
||||
Quote:Is there any particular reason you would recommend itoa() over the previous suggestions, lexical_cast and stringstream? (Note that itoa() is non-standard, and may not even be available to the OP.) [ Configurable Math Library ] |
||||
|
||||
![]() dj3hut1 Member since: 10/9/2009 From: Berlin, Germany |
||||
|
|
||||
| Hello Lith, you can also use sprintf ( from <cstdio> ). char buf[80]; sprintf( buf, "%d", number ); |
||||
|
||||
![]() stephe Member since: 11/4/2009 From: Zlin, Czech Republic |
||||
|
|
||||
Quote: Yes, but it is only alternative, I didnt say it is better. I think effect is same and easy to use, if available.. in every way, you are right, itoa() is non standard Atheron MMORPG |
||||
|
||||
![]() SiCrane Staff Member since: 12/10/1999 From: Vernon Hills, IL, United States |
||||
|
|
||||
Quote: Whether or not it is easy to use depends highly on which version of itoa() is provided, and itoa() is one of the more severely non-standard functions out there. I've run across at least five different function signatures for itoa: char * itoa(int, char *, int); // you supply the buffer char * itoa(int, int, char *); // you supply the buffer char * itoa(int, char *); // you supply the buffer char * itoa(int, int); // you need to free the pointer char * itoa(int); // you need to free the pointer And this ignores the fact that itoa() may in fact be spelled _itoa() depending on your platform. In addition to the variants I've run across myself, I've been told about one more that apparently appeared in very early Unix machines: void itoa(int input, void (*subr)(char)) This calls the subr function for each character in the resulting string. I believe most people would agree that this would not fall in the "easy to use" category. |
||||
|
||||
![]() leeor_net Member since: 4/5/2004 From: Charles Town, WV, United States |
||||
|
|
||||
I haven't seen this suggested but this may be too simple:stringstream myString; myString << someInteger; myString.str().c_str(); -The Legend of Mazzeroth- Project Lead, Windows Programming Lead and General Tasks. http://www.newagesoftware.org |
||||
|
||||
![]() mattd Member since: 2/26/2000 |
||||
|
|
||||
| Check post #2? :) |
||||
|
||||
![]() phresnel Member since: 10/22/2008 From: Nettetal, Germany |
||||
|
|
||||
Quote: It has been suggested in the first answer given to the OP, which was very concise. Quote: Possible undefined behaviour if a compiler defines an int to be 34 or more bytes long. Because of that, we use sooner mentioned methods in C++. |
||||
|
||||
![]() dclyde Member since: 7/21/2003 From: USA |
||||
|
|
||||
Quote: Which when it comes down to it that implementation ends up using sprintf or sprintf_s just with a little bit of a smarter buffer size declaration somehow relative to _MAX_INT_DIG from yvals.h |
||||
|
||||
![]() phresnel Member since: 10/22/2008 From: Nettetal, Germany |
||||
|
|
||||
Quote: _MAX_INT_DIG and yvals.h are non-standard extensions. Also note that _MAX_INT_DIG fails to communicate the base for which an int yields that maximum number of digits. If for whatever reason you really must use C string functions, then do it at least generic: #include <climits> // Make *_MAX available for template code. template <typename T> struct get_val_max; template <> struct get_val_max<char> { enum { value = CHAR_MAX }; }; template <> struct get_val_max<signed char> { enum { value = SCHAR_MAX }; }; template <> struct get_val_max<unsigned char> { enum { value = UCHAR_MAX }; }; template <> struct get_val_max<short> { enum { value = SHRT_MAX }; }; template <> struct get_val_max<unsigned short> { enum { value = USHRT_MAX }; }; template <> struct get_val_max<int> { enum { value = INT_MAX }; }; template <> struct get_val_max<unsigned int> { enum { value = UINT_MAX }; }; template <> struct get_val_max<long> { enum { value = LONG_MAX }; }; template <> struct get_val_max<unsigned long> { enum { value = ULONG_MAX }; }; #ifdef LLONG_MAX template <> struct get_val_max<long long> { enum { value = LLONG_MAX }; }; template <> struct get_val_max<unsigned long long> { enum { value = ULLONG_MAX }; }; #endif // Check signedness of a type. template <typename T> struct is_signed { enum { value = 1 }; }; template <> struct is_signed <char> { enum { value = CHAR_MIN < 0 }; }; template <> struct is_signed <unsigned char> { enum { value = 0 }; }; template <> struct is_signed <unsigned short> { enum { value = 0 }; }; template <> struct is_signed <unsigned int> { enum { value = 0 }; }; template <> struct is_signed <unsigned long> { enum { value = 0 }; }; #ifdef LLONG_MAX template <> struct is_signed <unsigned long long> { enum { value = 0 }; }; #endif // Recurse and divide by base until zero is reached template <typename T, T base, T val, bool recurse=val!=0> struct get_dig_max_rec { enum { value = 1 + get_dig_max_rec<T, base, val/base>::value }; }; template <typename T, T base, T val> struct get_dig_max_rec<T,base,val,false> { enum { value = 0 }; }; Replacement for non-standard and non-generic _MAX_INT_DIG: // Get number of digits needed to represent any value of T in base template <typename T, int base> struct get_dig_max { enum { value = is_signed<T>::value + get_dig_max_rec<T, base, get_val_max<T>::value>::value }; }; // some typedefs template <typename T> struct get_base10_dig_max : get_dig_max<T,10> {}; template <typename T> struct get_base16_dig_max : get_dig_max<T,16> {}; template <typename T> struct get_base2_dig_max : get_dig_max<T,2> {}; Test: #include <iostream> int main () { std::cout << get_base10_dig_max<char>::value << '\n'; std::cout << get_base10_dig_max<signed char>::value << '\n'; std::cout << get_base10_dig_max<unsigned char>::value << '\n'; std::cout << get_base10_dig_max<unsigned int>::value << '\n'; std::cout << get_base10_dig_max<int>::value << '\n'; // etc. } So in case of dj3hut1's code: char buf[get_base10_dig_max<int>::value + 1]; or later when C++0x is here char buf[get_base10_dig_max<decltype(your_var)>::value + 1]; That way, the code does not and won't yield undefined behaviour, and does not waste memory at the same time. edit: fixed is_signed, thanks mattd. [Edited by - phresnel on November 9, 2009 10:50:23 AM] |
||||
|
||||
![]() mattd Member since: 2/26/2000 |
||||
|
|
||||
| I think you got the is_signed specializations for unsigned types the wrong way around. |
||||
|
||||
![]() phresnel Member since: 10/22/2008 From: Nettetal, Germany |
||||
|
|
||||
Quote: Much appreciated :) |
||||
|
||||
![]() Antheus Member since: 3/3/2006 |
||||
|
|
||||
I would do something like this:class ScoreText { public: ScoreText(int x, int y, TTF_Font * font, SDL_Color color) : current_score(0) , font(font) , cache(NULL) , color(color) { dst.x = x; dst.y = y; } ~ScoreText() { clear_cache(); } void update(int new_score) { if (current_score == new_score) return; current_score = new_score; clear_cache(); } void set_position(int x, int y) { dst.x = x; dst.y = y; } bool render(SDL_Surface * s) { SDL_Surface * text = get_cached(); if (text != NULL) { int result = SDL_BlitSurface(text, NULL, s, &dest); if (result == -2) clear_cache(); } return result == 0; } private: void clear_cache() { if (cache != NULL) SDL_FreeSurface(cache); cache = NULL; } SDL_Surface * get_cached() { if (cache == NULL) { char buf[40]; sprintf(buf, "%d", current_score); cache = TTF_RenderText_Solid(font, buf, color); } return cache; } int current_score; SDL_Rect dest; SDL_Surface * cache; SDL_Color color; }; sprintf is ideal choice. We have a well known range, it avoids potential heap allocations, and doesn't require third-party libraries and SDL is a C library, so some 'print_score()' function could be provided as straight C function. In addition, it works on C strings, same as SDL, so there is no need to bring in std::string. For more generic printing, the alternatives were listed above. Stringstream is a must when several things need to be printed, lexical_cast can be used to work with std::string. printf in general is very clumsy when dealing with straight user input simply due to manual memory management - but this is not the case here. Good code is primarily about choosing proper compromises. Unless any other constraints are given, stringstream would be generic choice. But this is a common problem today - massive over-engineering without any critical thinking about the actual problem to be solved. The task here is to Print Score In Pong Game. Score will not be represented with 272 bits. It will probably be 0 to 10. Instead, rather than writing 500 lines of code to Print a freeking int, going through all the SDL documentation to properly handle all the return codes would be much more productive. When must a surface be freed, what happens if surface is lost (I don't handle this case thoroughly above), which encoding to use, etc... 999:1 chance says that someone will forget to call FreeSurface and leak memory long before their code breaks due to 272-bit integer stack buffer overflow. |
||||
|
||||
![]() phresnel Member since: 10/22/2008 From: Nettetal, Germany |
||||
|
|
||||
Quote: Uhm, you did not get the point:
And then, as long as I am not scratching memory limits, I pretty much prefer stringstream over my own solution, which is exactly 0 lines more code and has been shown in the very first answer to the OP. Which is also why I wrote that prologue Quote:. "If", the spartans responded. Quote: Buffer overflow. It is just called buffer overflow. |
||||
|
||||
![]() szecs Member since: 5/27/2009 From: Miskolc, Hungary / Jyvaskyla, Finland |
||||
|
|
||||
| These discussions show me that I'm not a programmer at all. The arguing about for and while, int* pt vs. int *pt, and printing a poor integer are far beyond me. I'm beginning to feel ashamed because I don't spend much time with these problems (and simply use sprintf), which were probably important when building pong from diodes and wires. Sorry for this totally non productive reply! ________________________ My first (and probably last) demo |
||||
|
||||
![]() jpetrie Moderator - For Beginners Member since: 6/11/2003 From: Redmond, WA, United States |
||||
|
|
||||
| This is starting to edge too far into the realm of pedantry for the scope of the original question and this forum; rip-off's replies are sufficient. Josh Petrie | Scientific Ninja | Twitter | SlimDX: October is the new August. |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|