4

Currently I have a complex function that myself and our team are not wanting to refactor to utilize std::string and it takes a char* which is modified. How would I properly make a deep-copy of string::c_str() into a char*? I am not looking to modify the string's internally stored char*.

char *cstr = string.c_str(); 

fails because c_str() is const.

3
  • 4
    Is this C++11? Copy the std::string and use &stringCopy[0]. Commented Aug 28, 2013 at 15:16
  • 1
    strdup, new/strcpy, @chris' suggestion, ... You have the choice. Commented Aug 28, 2013 at 15:18
  • sprintf(cstr,"%s", somestring.c_str()) Commented Aug 28, 2013 at 15:20

3 Answers 3

8

You can do it like this:

const std::string::size_type size = string.size(); char *buffer = new char[size + 1]; //we need extra char for NUL memcpy(buffer, string.c_str(), size + 1); 
Sign up to request clarification or add additional context in comments.

3 Comments

Please, please use a correct type for the string size, eg. std::string::size_type or std::size_t.
@syam ahh you are absolutely right :)
Don't forget to delete it. Or better still, get std::vector<char> to do that for you, and access the array as v.data() or &v[0]. Or even another string, if you don't mind borderline-undefined behaviour.
4

Rather than modify the existing function, I'd just create an overload that acts as a wrapper. Assuming the existing function is ret_type f(char *), I'd write the overload something like:

ret_type f(std::string s) { return f(&s[0]); } 

Note passing s by value instead of reference, minimizing the effort expended to get a copy of the string.

In theory, this isn't guaranteed to work (i.e., a string's buffer isn't guaranteed to be contiguous) until C++03. In reality, that guarantee was fairly easy for the committee to add primarily because nobody knew of an implementation of std::string that did anything else.

Likewise, it could theoretically be missing the NUL terminator. If you're concerned about that possibility you could use return f(const_cast<char *>(s.c_str())); instead, or add an s.push_back('\0'); before the return:

ret_type f(std::string s) { s.push_back('\0'); return f(&s[0]); } 

2 Comments

I would do a s.push_back( '\0' ) in your wrapper function, just to be sure. And you surely meant const_cast in the last bit of code.
@JamesKanze: Oops -- yes, of course.
1

The obvious solution is:

std::vector<char> tmp( string.begin(), string.end() ); tmp.push_back( '\0' ); function( &tmp[0] ); 

(I rather like Jerry Coffin's solution, however.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.