string and sprintf()

Aug 8, 2011 at 3:04pm
Hello, I've a got a question.
How can I use std::string object as the first argument of sprintf(), i.e. write to std::string using the C function sprintf() instead of sstream, or some other kind of stream.

1
2
3
4
5
char ss[] = "a string";
std::string sd;

sprintf(sd, "This is %s!", ss); // of course this won't compile because
                                // sprintf expects char[], not a string 

I thought of using string::c_str(), but it returns const char[] and const_cast-ing it is not a bright idea.
Is there another way I can get std::string to behave like a writable char[]?

Again, I need to use a string and I need to use sprintf().
Last edited on Aug 8, 2011 at 3:14pm
Aug 8, 2011 at 3:21pm
sprintf() is susceptible to buffer overruns because there is no check as to whether the allocated buffer is large enough to hold the data. What you need to do (in your example) is make sd a std::stringstream. When you create it, you give it a size (make it large enough, again, to avoid buffer overruns) and then you call sprintf(sd.str(), ...).
Aug 8, 2011 at 3:33pm
I think there is no way to do it.
(Only:
1
2
3
4
char ss[] = "a string";
std::string sd(strlen("This is !") + strlen(ss), '\0');

sprintf(const_cast<char*>(sd.c_str()), "This is %s!", ss);

But it's terrible!)
And why do you need to use exactly sprintf and string? std::ostringstream offers a better variant, I think..
Aug 8, 2011 at 3:40pm
std::stringstream::str() returns a std::string, so that still won't work. If you are going to use a stringstream anyway, just use the usual stream options:

1
2
3
4
5
char cs[] = "a string";
std::ostringstream ss;
ss << "This is " << cs << "!";

std::cout << ss.str() << std::endl;

Again, I need to use a string and I need to use sprintf().

All known implementations of std::string::c_str() simply return a pointer to the strings internal buffer, so if you don't mind the possibility that it may break someday, you could just cast it, as you thought:

1
2
3
4
5
6
7
8
9
char cs[] = "a string";
std::string s;

s.reserve( 100 );  // You had better have room for what you are sprintf()ing!
s.resize( std::max( 0,
  sprintf( (char*)s.c_str(), "This is %s!", cs )
  ) );

std::cout << s << std::endl;

However, best use is simply to use an intermediate buffer:

1
2
3
4
5
6
7
8
9
10
char cs[] = "a string";
std::string s;

{
  char sb[ 100 ];  // You had better have room for what you are sprintf()ing!
  sprintf( sb, "This is %s!", cs );
  s = sb;
}

std::cout << s << std::endl;

Hope this helps.
Aug 8, 2011 at 3:41pm
You're supposed to use snprintf.

e.g.
1
2
3
4
char ss[] = "a string";
std::string sd;

sprintf(sd, sizeof(sd), "This is %s!", ss);


EDIT: It's supposed to be:
1
2
3
char ss[] = "a string";

sprintf(ss, sizeof(ss), "This is %s!", "some string");
Last edited on Aug 9, 2011 at 7:51am
Aug 8, 2011 at 3:43pm
I figured it out. I just create a temporary char[], I do the writing into it and then assign the contents of the char[] string into the std::string.
The code goes like this:
1
2
3
4
5
char ss[] = "a string";
std::string sd;
char stemp[100] = "";
snprintf(stemp, 100, "This is %s!", ss); // I use the safer version of sprintf() -- snprintf()
sd = stemp; // the contents of sd are now "This is a string!" 

I guess there's no better way.
Last edited on Aug 8, 2011 at 3:44pm
Aug 8, 2011 at 3:48pm
My bad. I thought stringstream::str() was a pointer to the char buffer.
Aug 8, 2011 at 4:35pm
Thank you all for the answers. They confirmed the solution I suggested. When I wrote my second post there were no answers. Thanks again, cheers.
Aug 8, 2011 at 6:38pm
The snprintf() function is C99, and it has some issues.
http://linux.die.net/man/3/snprintf

It is a good function though. Personally, I just play very carefully and stick to sprintf(), as it is always possible to determine a good upper limit for things you are sprintf()ing, even with locale issues. But that is just me...
Topic archived. No new replies allowed.