views:

13224

answers:

5

How can I convert an std::string to a char* or a const char*?

+5  A: 

Use the .c_str() method for const char *.

You can use &mystring[0] to get a char * pointer, but there are a couple of gotcha's: you won't necessarily get a zero terminated string, and you won't be able to change the string's size. You especially have to be careful not to add characters past the end of the string or you'll get a buffer overrun (and probable crash).

Mark Ransom
Johannes Schaub - litb
@litb, Argh! That's what I get for trying to whip up a quick answer. I've used your solution in the past, don't know why it wasn't the first thing that came to mind. I've edited my answer.
Mark Ransom
Technically, std::string storage will be contiguous only in C++0x.
MSalters
@MSalters, thanks - I didn't know that. I'd be hard pressed to find an implementation where that wasn't the case, though.
Mark Ransom
+37  A: 

If you just want to pass a std::string to a function that needs const char* you can use

std::string str;
const char * c = str.c_str();

If you want to get a writable copy, like char *, you can do that with this:

std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0

// don't forget to free the string after finished using it
delete[] writable;

Edit: Notice that the above is not exception safe. If anything between the new call and the delete call throws, you will leak memory, as nothing will call delete for you automatically. There are two immediate ways to solve this.

boost::scoped_array

boost::scoped_array will delete the memory for you upon going out of scope:

std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0

// get the char* using writable.get()

// memory is automatically freed if the smart pointer goes 
// out of scope

std::vector

This is the standard way (does not require any external library). You use std::vector, which completely manages the memory for you.

std::string str;
std::vector<char> writable(str.size() + 1);
std::copy(str.begin(), str.end(), writable.begin());

// get the char* using &writable[0] or &*writable.begin()
Johannes Schaub - litb
Simply use char *result = strdup(str.c_str());
Jasper Bekkers
you could, but strdup is not a c or c++ standard function, it's from posix :)
Johannes Schaub - litb
what i would probably prefer generally is std::vector<char> writable(str.begin(), str.end()); writable.push_back('\0'); char * c =
Johannes Schaub - litb
You could also construct the vector with: vector<char> writable(str.c_str(), str.size() + 1);
efotinis
Definitely use std::vector. Allocating the array of char is not exception safe.
Martin York
I agree: litb, you should add your "vector" solution to your main answer, as it is (exception-) safer than the raw new/delete solution.
paercebal
ok, thanks i will put them there. you've convinced me
Johannes Schaub - litb
I'm curious why you're bending over backwards to use std::copy(). Wouldn't using strcpy( the_destination, str.c_str()) - or strlcpy() if you have it - work as well and be more immediately obvious what's going on? strcpy() will work with any of scoped_array, vector, or a raw memory allocation.
Michael Burr
std::copy is the c++ way of doing this, without the need of getting at the string pointer. I try to avoid using C functions as much as i can.
Johannes Schaub - litb
+1 (I was waiting for the exception safe addition)... ^_^
paercebal
A: 

Thank you very much!

write a comment about it, not a post.
Nazgob
A: 

Thank you Johannes Schaub - litb..your answer helped us a lot..

neha
write a comment about it, not a post.
Nazgob
A: 

Instead of: char * writable = new char[str.size() + 1]; You can use char writable[str.size() + 1];

Then you don't need to worry about deleting writable or exception handling.

Aaron Wohl