Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

kappa

help with std::string and char* conversion

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am reading programming roleplaying games with direct x, I am changing the C code to C++ witch has been working fine untill I got tangeled up with this:

const string g_szClass		= "FrameClass";
const string g_szCaption	= "FrameCaption";

void AppError( bool Fatal, string Text, ... )
{
	string CaptionText;
	string ErrorText;
	va_list valist;

	if( Fatal == false )
		CaptionText = "Error";
	else
		CaptionText = "Fatal Error";
        
  
	va_start( valist, Text.c_str() ); // dosent work!!!

	vsprintf( ErrorText.c_str(), Text.c_str(), valist ); // nope, not this either!!!

	va_end	( valist );

	MessageBox( NULL, ErrorText.c_str(), CaptionText.c_str(), 
				MB_OK | MB_ICONEXCLAMATION );

	if( Fatal == true )
		PostQuitMessage(0);
}
I get these errors "c:\Documents and Settings\Fredrik Sjöborg\Mina dokument\Visual Studio Projects\DX\WinMain.cpp(147): error C2102: '&' requires l-value" "c:\Documents and Settings\Fredrik Sjöborg\Mina dokument\Visual Studio Projects\DX\WinMain.cpp(148): error C2664: 'vsprintf' : cannot convert parameter 1 from 'const char *' to 'char *'" can anyone tell me why? [edited by - kappa on June 2, 2004 12:59:27 PM]

Share this post


Link to post
Share on other sites
Advertisement
.c_str() returns a const char *. Which means that you can use this char pointer to read the string, but you''re not allowed to write to the string as though it were a normal C-style string.

I think you need to simply pass in the string variable itself, Text, not Text.c_str(), since Text is the actual parameter, and Text.c_str() points off somewhere else and would get everything confused.

It''s been a while since I used variable sized arguments, though. They can probably be kinda dangerous sometimes, and I wouldn''t be surprised if they don''t always work well with templated classes that perform a lot of self-maintanence.

Share this post


Link to post
Share on other sites
This is a const correctness issue.

std::string::c_str returns const char* but the function
you''re passing it to takes a char*.

One way of doing it is to cast away the constness like so:

const std::string myStr = "test";
char* theCStr = const_cast< char* >(myStr.c_str());
doSomething(theCStr);

I general const_cast should be avoided, but if you''re working
with non-const aware APIs then it can be accetable.

Another, slightly less clean way of doing it is like this:

std::string myStr = "test";
doSomething(&(*(myStr.begin())));

Hope that helps

Share this post


Link to post
Share on other sites
thx, casting it worked but this std::string myStr = "test";
doSomething(&(*(myStr.begin()))); did not.

Share this post


Link to post
Share on other sites
quote:
Original post by kappa

vsprintf( ErrorText.c_str(), Text.c_str(), valist ); // nope, not this either!!!
[edited by - kappa on June 2, 2004 12:59:27 PM]


It is not a good idea to cast away const in this case. Since vsprintf actually writes to a string, it may screw up its internals and you may never be sure what will happen in the future.

Share this post


Link to post
Share on other sites
vsprintf wants to write into a plain, non-resizable, non-const buffer (if it were const then it wouldn''t be able to write into it yeah?) Your message box apparently wants a char * as well. So having "string ErrorText;" isn''t going to work for you. You''re only trying to use its underlying representation, and the string class const-ifies it up for you first, which is bad.

So just use char * ErrorText = new char[SOME_LEN]; , after figuring out how much buffer space you''re going to need. (You''re also only using the CaptionText as if it were a char *, which you could just point at the data "Error" or "Fatal Error" as needed. As it stands, you''re constructing this String object on top of a char array, just so that you can grab the char array back out of it.)

Of course, that''s rather error-prone. Which is a good reason not to be trying to use nasty va_args stuff in C++ (which loses you huge amounts of type safety anyway). I can''t imagine what you''re planning to have in your extra arguments after the Text, anyway. Are you trying to make Text a C-style substitution string with %-codes or something? Don''t Do That(TM) in C++.

Try making an AppError class, which contains a string and an associated stringstream. Give it an overload (templated?) for operator << (which will use the stringstream to append to the string), and methods error() and fatal() (to print the two different types of error messages). If you have those methods "return *this;", then you should be able to do something like


delete (*(new AppError()) << "Oh dear! Have " << numWidgets << " widgets, need " << reqWidgets).fatal();


(er, C++ will let you use anonymous instances like that won''t it?)

Or, give the "Fatal" bool as a constructor arg, and invoke the dialog box in the destructor. I guess that''s more RAII-ish. (I initially typed "RIAA". Hee.)

If you really want the %-substitution thingy, I think there''s a Boost library for it. :/

Share this post


Link to post
Share on other sites
you CANNOT use string.c_str() to get a buffer to then WRITE to it ...

c_str() returns a READ ONLY buffer to the internals of your string object ... if you cast away const, that''s fine, as long as everyone still treats it as const implicitly (DOESNT WRITE TO IT), but if someone tries to write to it, your program has a memory violation ... and will almost definately fail on processors and OSes that detect writing to code segments (both Intel and AMDs new chips have this feature, and Windows XP SP2 will enable it for windows - to protect against viruses) ...

you use string for easy string manipulation in C++

you use string.c_str() to allow your string''s buffer to be passed to algorithms which READ FROM a char*.

you must use a char array if you need to let people write into a buffer through a char*.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!