std::string to char* - c++

I want to convert a std::string into a char* or char[] data type.
std::string str = "string";
char* chr = str;
Results in: “error: cannot convert ‘std::string’ to ‘char’ ...”.
What methods are there available to do this?

It won't automatically convert (thank god). You'll have to use the method c_str() to get the C string version.
std::string str = "string";
const char *cstr = str.c_str();
Note that it returns a const char *; you aren't allowed to change the C-style string returned by c_str(). If you want to process it you'll have to copy it first:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Or in modern C++:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);

More details here, and here but you can use
string str = "some string" ;
char *cstr = &str[0];
As of C++11, you can also use the str.data() member function, which returns char *
string str = "some string" ;
char *cstr = str.data();

If I'd need a mutable raw copy of a c++'s string contents, then I'd do this:
std::string str = "string";
char* chr = strdup(str.c_str());
and later:
free(chr);
So why don't I fiddle with std::vector or new[] like anyone else? Because when I need a mutable C-style raw char* string, then because I want to call C code which changes the string and C code deallocates stuff with free() and allocates with malloc() (strdup uses malloc). So if I pass my raw string to some function X written in C it might have a constraint on it's argument that it has to allocated on the heap (for example if the function might want to call realloc on the parameter). But it is highly unlikely that it would expect an argument allocated with (some user-redefined) new[]!

(This answer applies to C++98 only.)
Please, don't use a raw char*.
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*

If you just want a C-style string representing the same content:
char const* ca = str.c_str();
If you want a C-style string with new contents, one way (given that you don't know the string size at compile-time) is dynamic allocation:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Don't forget to delete[] it later.
If you want a statically-allocated, limited-length array instead:
size_t const MAX = 80; // maximum number of chars
char ca[MAX] = {};
std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);
std::string doesn't implicitly convert to these types for the simple reason that needing to do this is usually a design smell. Make sure that you really need it.
If you definitely need a char*, the best way is probably:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector

This would be better as a comment on bobobobo's answer, but I don't have the rep for that. It accomplishes the same thing but with better practices.
Although the other answers are useful, if you ever need to convert std::string to char* explicitly without const, const_cast is your friend.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Note that this will not give you a copy of the data; it will give you a pointer to the string. Thus, if you modify an element of chr, you'll modify str.

Assuming you just need a C-style string to pass as input:
std::string str = "string";
const char* chr = str.c_str();

To obtain a const char * from an std::string use the c_str() member function :
std::string str = "string";
const char* chr = str.c_str();
To obtain a non-const char * from an std::string you can use the data() member function which returns a non-const pointer since C++17 :
std::string str = "string";
char* chr = str.data();
For older versions of the language, you can use range construction to copy the string into a vector from which a non-const pointer can be obtained :
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
But beware that this won't let you modify the string contained in str, only the copy's data can be changed this way. Note that it's specially important in older versions of the language to use c_str() here because back then std::string wasn't guaranteed to be null terminated until c_str() was called.

To be strictly pedantic, you cannot "convert a std::string into a char* or char[] data type."
As the other answers have shown, you can copy the content of the std::string to a char array, or make a const char* to the content of the std::string so that you can access it in a "C style".
If you're trying to change the content of the std::string, the std::string type has all of the methods to do anything you could possibly need to do to it.
If you're trying to pass it to some function which takes a char*, there's std::string::c_str().

Here is one more robust version from Protocol Buffer
char* string_as_array(string* str)
{
return str->empty() ? NULL : &*str->begin();
}
// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here

Conversion in OOP style
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
usage
StringConverter::strToChar("converted string")

For completeness' sake, don't forget std::string::copy().
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy() doesn't NUL terminate. If you need to ensure a NUL terminator for use in C string functions:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);

You can make it using iterator.
std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);
Good luck.

A safe version of orlp's char* answer using unique_ptr:
std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());

char* result = strcpy((char*)malloc(str.length()+1), str.c_str());

Alternatively , you can use vectors to get a writable char* as demonstrated below;
//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0');
char* cstring = &writable[0] //or &*writable.begin ()
//Goodluck

This will also work
std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;

No body ever mentioned sprintf?
std::string s;
char * c;
sprintf(c, "%s", s.c_str());

Related

Can I get a char * to a std::sregex_iterator match str()

string b="some string another string";
std::regex r("string");
std::sregex_iterator m(b.begin(),b.end(),r);
for (std::sregex_iterator end; m!=end; m++)
{
// want a char* to m->str() in here
}
I'm gettng totally lost trying to determine what's what because of the templates. I've tried
const char *c = m->str().c_str() // compiles but points to ""
Answer
Pointed out by lightness below
const char *c = &b[m->position()]; // length of str is m->length()
const char *c = m->str().c_str()
m->str() is a temporary value, not a reference to data inside m, so c is immediately dangling.
Just store the string first:
const std::string str = m->str();
const char* c = str.c_str();
Yes, the copy is unfortunate.
A cheaper way than the copy would be:
const std::string_view sv{
b.data() + m->position(),
m->length()
};
This is great if you can use string views. But it is not null-terminated! So, if you really do need a const char*, this won't work for you and you're pretty much stuck with a fresh buffer.

Filling char pointer correctly

I have a char pointer:
char* s = new char[150];
Now how do i fill it? This:
s="abcdef";
Gives warning about deprecation of conversion between string literal and char*, but generally works.
This:
char* s = new[150]("abcdef");
Does not work, gives an error.
How to do this properly? Note that I want the memory allocation to have 150*sizeof(char) bytes and contain "abcdef". I know about malloc, but is it possible to do with new?
Its for an assignment where i cant use the standard library.
This sequence of statements
char* s = new char[150];
s="abcdef";
results in a memory leak because at first a memory was allocated and its address was assigned to the pointer s and then the pointer was reassigned with the address of the string literal "abcdef". And moreover string literals in C++ (opposite to C) have types of constant character arrays.
If you allocated a memory for a string then you should copy a string in the memory either by using the C standard function strcpy or C standard function strncpy.
For example
char* s = new char[150];
std::strcpy( s, "abcdef" );
Or
const size_t N = 150;
char* s = new char[N];
std::strncpy( s, "abcdef", N );
s[N-1] = '\0';
Or even the following way
#include <iostream>
#include <cstring>
int main()
{
const size_t N = 150;
char *s = new char[N]{ '\0' };
std::strncpy( s, "abcdef", N - 1 );
std::cout << s << '\n';
delete []s;
}
In any case it is better just to use the standard class std::string.
std::string s( "abcdef" );
or for example
std::string s;
s.assign( "abcdef" );
The basic procedure for creating a memory area for a string and then filling it without using the Standard Library in C++ is as follows:
create the appropriate sized memory area with new
use a loop to copy characters from a string into the new area
So the source code would look like:
// function to copy a zero terminated char string to a new char string.
// loop requires a zero terminated char string as the source.
char *strcpyX (char *dest, const char *source)
{
char *destSave = dest; // save copy of the destination address to return
while (*dest++ = *source++); // copy characters up to and including zero terminator.
return destSave; // return destination pointer per standard library strcpy()
}
// somewhere in your code
char *s1 = new char [150];
strcpyX (s1, "abcdef");
Given a character array:
char * s = new char [256];
Here's how to fill the pointer:
std::fill(&s, &s + sizeof(s), 0);
Here's how to fill the array:
std::fill(s, s+256, '\0');
Here's how to assign or copy text into the array:
std::strcpy(s, "Hello");
You could also use std::copy:
static const char text[] = "World";
std::copy(text, text + sizeof(text), s);
Remember that a pointer, array and C-Style string are different concepts and objects.
Edit 1: Prefer std::string
In C++, prefer to use std::string for text rather than character arrays.
std::string s;
s = "abcdef";
std::cout << s << "\n";
Once you've allocated the memory for this string, you could use strcpy to populate it:
strcpy(s, "abcdef");

Substitute char array with std::string in an input parameter to a function

Following are two legacy routines. I cannot change the routine declarations.
static bool GetString(char * str); //str is output parameter
static bool IsStringValid(const char * str); //str is input parameter
With call as follows
char inputString[1000];
GetString(inputString);
IsStringValid(inputString);
Instead of using fixed char array, I want to use std::string as the input. I am not able get the semantics right (string::c_str).
With IsEmpty it should not be a problem:
std::string str = "Some text here";
IsEmpty(str.c_str());
Though it's pretty useless if you have a std::string as then you would normally just call str.empty().
The other function though, that's harder. The reason is that it's argument is not const, and std::string doesn't allow you to modify the string using a pointer.
It can be solved, by writing a wrapper-function which takes a string reference, and have an internal array used for the actual GetString call, and uses that array to initialize the passed string reference.
Wrapper examples:
// Function which "creates" a string from scratch
void GetString(std::string& str)
{
char tempstr[4096];
GetString(tempstr);
str = tempstr;
}
// Function which modifies an existing string
void ModifyString(std::string& str)
{
const size_t length = str.size() + 1;
char* tempstr = new char[length];
std::copy_n(str.c_str(), tempstr, length);
ModifyString(tempstr);
str = tempstr;
delete[] tempstr;
}
You can't use c_str for the first function, because it returns a const char*. You can pass a std::string by reference and assign to it. As for is empty, you can call c_str on your string, but you'd be better of calling the member empty().
I think you can use the string container of STL ( Standard template Library ) .
#include <string>
bool isempty ( int x ) {
return ( x == 0 ) ? true : false ;
}
// inside main()
string s ;
cin >> s ; // or getline ( cin , s) ;
bool empty = isEmpty (s.length()) ;
std::string has c_str() which you can use for IsEmpty. There ist no function which gives you a non const pointer. Since std::string's allocation is not guaranteed to be contiguous you cannot do something like &s[0] either. The only thing you can do is to use a temporary char buffer as you do in your example.
std::string s;
char inputString[1000];
std::vector<char> v(1000);
GetString(inputString);
GetString(&v[0]);
s = &v[0];
IsEmpty(s.c_str());

How to store a const char* in std :: string?

char *buffer1 = "abc";
const char *buffer2 = (const char*) buffer;
std :: string str (buffer2);
This works, but I want to declare the std::string object i.e. str, once and use it many times to store different const char*.
What's the way out?
You can just re-assign:
const char *buf1 = "abc";
const char *buf2 = "def";
std::string str(buf1);
str = buf2; // Calls str.operator=(const char *)
Ah well, as I commented above, found the answer soon after posting the question :doh:
const char* g;
g = (const char*)buffer;
std :: string str;
str.append (g);
So, I can call append() function as many times (after using the clear()) as I want on the same object with "const char *".
Though the "push_back" function won't work in place of "append".
str is actually copying the characters from buffer2, so it is not connected in any way.
If you want it to have another value, you just assign a new one
str = "Hello";
Make a Class say MyString which compose String buffer.
Have a constant of that class.
and then u can reassign the value of the composed string buffer, while using the same constant.

how to copy char * into a string and vice-versa

If i pass a char * into a function. I want to then take that char * convert it to a std::string and once I get my result convert it back to char * from a std::string to show the result.
I don't know how to do this for conversion ( I am not talking const char * but just char *)
I am not sure how to manipulate the value of the pointer I send in.
so steps i need to do
take in a char *
convert it into a string.
take the result of that string and put it back in the form of a char *
return the result such that the value should be available outside the function and not get destroyed.
If possible can i see how it could be done via reference vs a pointer (whose address I pass in by value however I can still modify the value that pointer is pointing to. so even though the copy of the pointer address in the function gets destroyed i still see the changed value outside.
thanks!
Converting a char* to a std::string:
char* c = "Hello, world";
std::string s(c);
Converting a std::string to a char*:
std::string s = "Hello, world";
char* c = new char[s.length() + 1];
strcpy(c, s.c_str());
// and then later on, when you are done with the `char*`:
delete[] c;
I prefer to use a std::vector<char> instead of an actual char*; then you don't have to manage your own memory:
std::string s = "Hello, world";
std::vector<char> v(s.begin(), s.end());
v.push_back('\0'); // Make sure we are null-terminated
char* c = &v[0];
You need to watch how you handle the memory from the pointer you return, for example the code below will not work because the memory allocated in the std::string will be released when fn() exits.
const char* fn(const char*psz) {
std::string s(psz);
// do something with s
return s.c_str(); //BAD
}
One solution is to allocate the memory in the function and make sure the caller of the function releases it:
const char* fn(const char*psz) {
std::string s(psz);
// do something with s
char *ret = new char[s.size()]; //memory allocated
strcpy(ret, s.c_str());
return ret;
}
....
const char* p = fn("some text");
//do something with p
delete[] p;// release the array of chars
Alternatively, if you know an upper bound on the size of the string you can create it on the stack yourself and pass in a pointer, e.g.
void fn(const char*in size_t bufsize, char* out) {
std::string s(psz);
// do something with s
strcpy_s(out, bufsize, s.c_str()); //strcpy_s is a microsoft specific safe str copy
}
....
const int BUFSIZE = 100;
char str[BUFSIZE];
fn("some text", BUFSIZE, str);
//ok to use str (memory gets deleted when it goes out of scope)
You can maintain a garbage collector for your library implemented as
std::vector<char*> g_gc; which is accessible in your library 'lib'. Later, you can release all pointers in g_gc at your convenience by calling lib::release_garbage();
char* lib::func(char*pStr)
{
std::string str(pStr);
char *outStr = new char[str.size()+1];
strcpy(outStr, str.c_str());
g_gc.push_back(outStr); // collect garbage
return outStr;
}
release_garbage function will look like:
void lib::release_garbage()
{
for(int i=0;i<g_gc.size();i++)
{
delete g_gc[i];
}
g_gc.clear();
}
In a single threaded model, you can keep this g_gc static. Multi-threaded model would involve locking/unlocking it.