Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Textout and String

Credits go to X-G for helping out!
This thread is locked; no one can reply to it. rss feed Print
Textout and String
Tomoso
Member #3,128
January 2003
avatar

Since I cant use string with allegro's text functions am I doing this correctly?

void TEXT::Draw(BITMAP* buffer) {
    char* s;

    s = new char [m_sText.size()+1];
    strcpy (s, m_sText.c_str());

    textprintf_centre_ex(buffer, font, 0, 0, 0, -1, "%s", s);
    
    delete s;

}

Want to make some nice text effects for my menu's and such, thought it would be safer to handle the text I want to display in a string and play with it that way.

Regards,

Tomoso

Lazy Noob - Blog

X-G
Member #856
December 2000
avatar

What's wrong with std::string::c_str()? That's what it's for.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Tomoso
Member #3,128
January 2003
avatar

Sure I tried that first time round and it threw up an error so I decided to find a way around it.

It's working now... :P

What a waste of a post, thanks for the fast reply though =D

Lazy Noob - Blog

OnlineCop
Member #7,919
October 2006
avatar

void TEXT::Draw(BITMAP* buffer) {
   textprintf_center_ex(buffer, font, 0, 0, 0, -1, "%s", m_sText.c_str());
}

bamccaig
Member #7,536
July 2006
avatar

Edit: Negated.

What X-G means is that you can use the result of std::string::c_str(void) directly...

textprintf_centre_ex(buffer, font, 0, 0, 0, -1, "%s", m_sText.c_str());

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only granted to remain unchanged until the next call to a non-constant member function of the string object.

In other words, the result of std::string::c_str(void) is all you need if the C string won't be modified (in this case, you're just drawing it to a graphical display, so no problem there) and as long as the std::string object won't be modified before you're done with it (this shouldn't be a problem here unless you access m_sText from multiple threads).

Tomoso
Member #3,128
January 2003
avatar

That's what I tried to begin with but I got an error (probably becuase I used -> or something, can't remember now), I just assumed you couldn't do that and searched google for an alternative. Only when X-G say that I went back and tried it again and it worked where it didn't before (well obivously it wasn't exactly the same before).

Thanks all.

Lazy Noob - Blog

X-G
Member #856
December 2000
avatar

Caveat emptor: if you do what bamccaig suggested, and the string contains format specifiers, there will be trouble. For best results if you don't actually want to do formatted output, use textout_centre_ex.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Tomoso
Member #3,128
January 2003
avatar

Not quite sure what you mean by format modifiers?

Only thing I will do is spilt the string up into single characters then print each individually slightly changing its x/y co-ord to get a wave effect which is mainly what I want. Oh and use a nicer bitmap font.

I have a feeling what you said went straight over my head... ???

Edit
Wait I get it now... you mean the % things... I haven't done this in a long time :P

Edit 2
On second thoughts I think it's still going over my head! I'm so confused :-X

Lazy Noob - Blog

OnlineCop
Member #7,919
October 2006
avatar

If m_sText is either protected or private, you won't be able to access its text directly, which is probably why you'd have to call that TEXT::Draw() function. Were you trying to access it externally without proper access permissions (such as being a derived class or a friend) or having it a public variable?

%s is a string
%c is a single character

You can loop through each character in the array with the [] operators, so m_sText[0] through m_sText[length-1] and print each character in your sine-wave pattern as you want. Just print each character with the "%c" instead of the "%s".

Tomoso
Member #3,128
January 2003
avatar

TEXT is actually just an object within my "menu object" (created with new) class and is created when said menu object is created by passing a string and eventually a "text behaviour" into its constructor. From there I shouldn't have to worry about what the string is doing, only calling its draw\logic functions as necersary but they're called from the menu object anyway, along with its own draw\logic, which is called from my menu class (a group of menu objects) which is then controlled by my menu system class (a group of menus that can link back and forth between eachother).
It all gets complicated anyway but its easy to use, you just have to set up your menus before hand (adding objects like buttons\sliders\toggles etc..) then call the menu systems logic\draw functions in the game loop. It does work even though I probably didnt make it sound right :p

I'm probably over complicating it by using std::string, but I was using const char* text before, then I realised I wouldn't be able to get the single characters. So I then decided to change it to char[] but it didn't look right so I went for strings instead...

Anyway that's my life story over with, thanks for the clearing that up.

Lazy Noob - Blog

bamccaig
Member #7,536
July 2006
avatar

X-G said:

Caveat emptor: if you do what bamccaig suggested, and the string contains format specifiers, there will be trouble. For best results if you don't actually want to do formatted output, use textout_centre_ex.

While I didn't personally notice (I wasn't worried about the Allegro routine being called, only the C string), it seems Tomoso already took care of that possibility by using "%s" as the format string and [effectively] m_sText.c_str() as the parameter.

I said:

textprintf_centre_ex(buffer, font, 0, 0, 0, -1, "%s", m_sText.c_str());

I didn't technically say anything regarding the use of printf-family routines. ;) Of course, using textout_centre_ex would probably be quite a bit more efficient, but nevertheless I think the above code should effectively result in the same output regardless of the std::string's contents.

Tomoso said:

I'm probably over complicating it by using std::string, but I was using const char* text before, then I realised I wouldn't be able to get the single characters. So I then decided to change it to char[] but it didn't look right so I went for strings instead...

char * and char [] are actually very much the same in a lot of ways. Obviously because you used the const modifier on one you wouldn't be able to change the contents (without a cast), but otherwise they are the same most of the time. The exception being that as a variable (not a parameter) the array is stack allocated and the sizeof operator returns the size, in bytes, of the array, not the pointer; whereas the pointer is just a raw memory address that needs to be initialized by allocating memory (i.e., new char[size]), which will also need to be deallocated later (i.e., delete operator), and the sizeof operator always returns the size of the pointer (i.e., typically 4 or 8 bytes). As parameters of a function or method, they are exactly the same AFAIK.

#SelectExpand
1#include <cassert> 2#include <cctype> 3 4/* 5 * pointer and array are effectively the same data type (char *). 6 * This routine requires that each points to valid memory 7 * and is NUL (i.e., '\0' or 0) terminated. pointer is 8 * upper-cased and array is lower-cased. 9 */ 10void f(char *pointer, char array[]) 11{ 12 const char NUL = '\0'; // Not NULL, NUL (one L). 13 14 assert(pointer); 15 assert(array); 16 17 for(int i=0; pointer[i] != NUL; i++) 18 pointer[i] = toupper(pointer[i]); 19 20 for(int i=0; array[i] != NUL; i++) 21 array[i] = tolower(array[i]); 22}

(Untested)

All that said, I don't see anything wrong with using std::string for this and in fact it does save you a little bit of memory management, which is good.

anonymous
Member #8025
November 2006

Tomoso said:

I'm probably over complicating it by using std::string...

I think you got this exactly backwards, especially when we look at how you go about memory management:

    s = new char [m_sText.size()+1];
    ...
    delete s;

A nice bug that might or might not manifest itself in any way. If I remember correctly, I have never used the array form of new in a real C++ program other than exercises.

bamccaig said:

const char NUL = '\0'; // Not NULL, NUL (one L). 

Well, you could use the number 0 (or nothing at all) if you don't want to type '\0'. ;)

bamccaig
Member #7,536
July 2006
avatar

anonymous said:

Well, you could use the number 0 (or nothing at all) if you don't want to type '\0'. ;)

My reasoning is that it's somewhat more clear and to some degree compiler-checked: if I spell it wrong, there's some chance the compiler will complain that NU or NL is undefined, whereas '0' won't be. Of course, I could also accidentally type NULL, which would likely still work, but would be semantically wrong and could confuse someone. Also, at a quick glance, one might mistake NUL for NULL and be equally confused. I supposed lowercase nul is another approach. ;)

Go to: