# Total char * confusion

This topic is 4305 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi I'm using ID3DXFont to print som basic text on the screen. All goes well when I do: char strBuffer[255]; sprintf_s(strBuffer,"Movingnation: %i", movingnation); MyFont->Print(strBuffer, 0, 40); I have a class (MyText) which among other things have a char * member (newtext). When I try this: char strBuffer[255]; sprintf_s(strBuffer,"Country: %s", nations[movingnation]->sCountryName); MyText->newtext = strBuffer; It print some garbled nonsense. I understand that we're talking about different formats of strings but I just don't know how to solve this problem. After googling for an hour I'm still lost, so any help would be nice :) A

##### Share on other sites
First are you using C or C++, if you are using C++ switch to std::string. You could have many problems for example if your code looks like this:
TextClass MyText;void func(){    char strBuffer[255];    sprintf_s(strBuffer,"Country: %s", nations[movingnation]->sCountryName);    MyText->newtext = strBuffer;}

This will introduce a problem because your variable newtext only points to strBuffer, and when we exit the function func strBuffer is getting destructed and newtext will point to a destroyed string. You should use strcpy to copy strings, anyway without more code I doubt anyone can guess your error.

##### Share on other sites
a char * is NOT a string. It's a pointer to a place in memory where a character lives. When you assign newtext to be strBuffer all you've done is assign newtext to point to the memory location on the stack where strBuffer lives. As soon as you leave the scope in which strBuffer was declared your newtext pointer points to what is now a random point in mempory

to reiterate this statement does NOT copy the string. it copies a memory pointer:

MyText->newtext = strBuffer;

the correct way to copy char* is like this:

//i think you need the +1 for the \0 character...
MyText->newtext = new char[ strlen(strBuffer)+1 ];
strcpy(myText->newtext, strBuffer);

now you have actually copied the string. but now you have to remember to deallocate the memory when you are done with it:

delete[] MyText->newtext

if you want simple strings use the std::string class. To use char* strings without destroying your program you MUST understand pointers and how to use them.

-me

##### Share on other sites

I messed up on the respones, sorry. = ]

##### Share on other sites
Ok, I see my error. I still keep confusing the use of pointers from time to time :) Another day in the life of a newbie :)

I solved the problem by making strBuffer a member of my MyText class. That way there's still something to point at when I'm exiting the function. There are probably many better solutions to this, but it works for now.

Thanks guys!

A

##### Share on other sites
Quote:
 Original post by Attala101Ok, I see my error. I still keep confusing the use of pointers from time to time :) Another day in the life of a newbie :)I solved the problem by making strBuffer a member of my MyText class. That way there's still something to point at when I'm exiting the function. There are probably many better solutions to this, but it works for now.Thanks guys!A

I strongly urge you to reconsider. You _will_ have more of these problems in the future if you continue to use raw char arrays over std::string.

Seriously, use std::string, it's soo much easier.

##### Share on other sites
Quote:
Original post by rip-off
Quote:
 Original post by Attala101Ok, I see my error. I still keep confusing the use of pointers from time to time :) Another day in the life of a newbie :)I solved the problem by making strBuffer a member of my MyText class. That way there's still something to point at when I'm exiting the function. There are probably many better solutions to this, but it works for now.Thanks guys!A

I strongly urge you to reconsider. You _will_ have more of these problems in the future if you continue to use raw char arrays over std::string.

Seriously, use std::string, it's soo much easier.

Ok, I will :) I just thought a std::string could not be passed directly to the ID3DXFont DrawText function, (don't ask me why). Anyway, that is why I built the whole thing around char arrays.

A

##### Share on other sites
Quote:
 Original post by Attala101Ok, I will :) I just thought a std::string could not be passed directly to the ID3DXFont DrawText function, (don't ask me why).

It can't, but std::string::c_str() can.

##### Share on other sites
Ok, now I have converted all my char arrays to std::string. With the use of c_str() most of it compiled fine. I am left with one error though.

MyFont->Print(MyText->infotext[i].c_str(), MyText->xpos[i], MyText->ypos[i], opacity );

the Print function in my Fontclass calls the DrawText function.

I'm getting the error: error C2664: 'Fontclass::Print' : cannot convert parameter 1 from 'const char *' to 'char *'

##### Share on other sites
Quote:
 Original post by Attala101Ok, now I have converted all my char arrays to std::string. With the use of c_str() most of it compiled fine. I am left with one error though.MyFont->Print(MyText->infotext[i].c_str(), MyText->xpos[i], MyText->ypos[i], opacity );the Print function in my Fontclass calls the DrawText function.I'm getting the error: error C2664: 'Fontclass::Print' : cannot convert parameter 1 from 'const char *' to 'char *'

The Fontclass is your own right? You need to make the first parameter of type const char*, which shows that the print function won't actually modify the string. This is a requirement for std::string, you can only access the c_str as read-only (const). Anyway since this function is most likely your own you should also use std::string here and not call c_str until you are passing it to a third-party function using const char*.

##### Share on other sites
Done :) Making good progress here :)
Now I have a problem with my sprintf and printf functions though.

sprintf_s(MyText->strBuffer.c_str(),"%s is making it's turn", nations[movingnation]->sCountryName);
MyText->newtext = MyText->strBuffer;

This was working fine when I was working with char arrays. Now it gives me the error:

error C2664: 'sprintf_s' : cannot convert parameter 1 from 'const char *' to 'char *'

The sprintf function is not my own, (big surprise), so how do I convert from const char * to char * ?

##### Share on other sites
I don't know if you know it, but const means that a type can't be changed (read-only). When you use std::string you can't directly manipulate the char* since it might be stored in another way, or use optimizations which wouldn't be possible if the char* was non-const. Your problem is that you still use the CRT (C Runtime) functions instead of the C++ Standard Library's functions.
sprintf_s(MyText->strBuffer.c_str(),"%s is making it's turn", nations[movingnation]->sCountryName);MyText->newtext = MyText->strBuffer;

Could be written like this (you need to include <sstream> before using string streams):

std::stringstream ssss << nations[movingnation]->sCountryName << " is making it's turn";MyText->strBuffer = ss.str();MyText->newtext = MyText->strBuffer;

I don't see why you use both strBuffer and newtext, but this code does the same as your code should do in the above example.

Streams is a powerful utility in the C++ Standard Library, you are most likely familar with cout which is a stream (output). Or cin which is also a stream (input).

EDIT: As you can see below in rip-off's post there are many ways to do this. In this case simply appending strings (like rip-off does) might be a better choice. But if you want to append stuff like ints, floats and custom types, or if you want to be able to specify which base (hexidecimal, binary, decimal) numbers should be printed in, if floats should be printed in scientific format etc. then you should use streams.

##### Share on other sites
Quote:
 Original post by Attala101Done :) Making good progress here :)Now I have a problem with my sprintf and printf functions though.sprintf_s(MyText->strBuffer.c_str(),"%s is making it's turn", nations[movingnation]->sCountryName);MyText->newtext = MyText->strBuffer;This was working fine when I was working with char arrays. Now it gives me the error:error C2664: 'sprintf_s' : cannot convert parameter 1 from 'const char *' to 'char *'The sprintf function is not my own, (big surprise), so how do I convert from const char * to char * ?
The first argument to sprintf_s() is the target buffer, so it has to be non-constant (mutable). c_str() returns a constant pointer; it's not meant to provide mutable access to the contents of std::string.

This is a sign of sorts that you're mixing C and C++ in 'unnatural' ways ;-) The first step in switching to the C++ way was replacing raw character pointers with std::string. The next step will be to ditch sprintf_s() and its kin in favor of streaming (or a safer substitute such as boost::format). Ask if you need more details.

[Edit: Bah, too slow.]

##### Share on other sites
Quote:
 Original post by Attala101Done :) Making good progress here :)Now I have a problem with my sprintf and printf functions though.sprintf_s(MyText->strBuffer.c_str(),"%s is making it's turn", nations[movingnation]->sCountryName);MyText->newtext = MyText->strBuffer;This was working fine when I was working with char arrays. Now it gives me the error:error C2664: 'sprintf_s' : cannot convert parameter 1 from 'const char *' to 'char *'The sprintf function is not my own, (big surprise), so how do I convert from const char * to char * ?

Ugh. Try:
std::string thingToBePrinted = nations[movingnation]->sCountryName;thingToBePrinted += " is making it's turn";printFunctionThatTakesCharPointer( thingToBePrinted.c_str() );

##### Share on other sites
I'm not sure I understood everything here, but I'm gonna read up on this. I actually thought I was using standard C++ functions, so I have learned a lot today.

Oh, and the program compiles fine now :)