How to convert std::string to const char*? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert std::string to const char* or char*
void Foo::bar(const std::string& foobar) {
// ...
const char* foobar2 = (char*)foobar;
// ...
}
That does not work and I get an error during compilation about invalid casting.
Is there some other way to convert std::string to const char*?

Use foobar.c_str().
You might find this link useful: http://www.cppreference.com/wiki/string/start

std::string::c_str() gets you a const char* pointer to a character array that represents the string (null-terminated).
You should not manipulate the data this pointer points to, so if you need to do that, copy the data.
Double edit - doing it in a more C++ fashion
Since it is nicer to avoid the use of raw pointers and arrays where possible, you can also get the data into an std::vector<char>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<char> cvec(str.begin(), str.end());
// do stuff
}
edit this is more like C since it uses raw pointers and explicitly allocates mem
#include <string>
#include <cstring>
int main()
{
std::string str = "Hello";
char *cptr = new char[str.size()+1]; // +1 to account for \0 byte
std::strncpy(cptr, str.c_str(), str.size());
// do stuff...
delete [] cptr;
}

You're going to get a lot of kinda incorrect answers about str.c_str() here. :) While c_str() is indeed useful, please keep in mind that this will not actually convert the string into a char*, but rather return the contents of the string as a const char*. And this is a big difference!
What's important here is that the pointer you obtain from c_str() is valid only as long as the given string object exists. So this would be terribly wrong:
class Something {
const char* name;
public:
Something(const std::string& pname) {
this->name = pname.c_str(); /* wrong! the pointer will go wrong as the object from the parameter ceases to exist */
}
};
So if you want to convert, as in: create a new value which will be independent of the original std::string, then you'll want to do something like this:
char* convert(const std::string& str) {
char* result = new char[str.length()+1];
strcpy(result,str.c_str());
return result;
}
But still c_str() will be quite enough for you in most cases. Just try to think in terms of objects' time of life.

const char* foobar2 = foobar.c_str();
Notice the const.
Otherwise you have to copy it to a char buffer.

Related

How to append c-style string or string literals to std::vector<char*>?

I am trying to append string literals to std::vector<char*> but whatever I try i can not append them.
std::vector<char*> vector1;
vector1.push_back("examplestring"); // gives warning C++11 does not allow conversion form string literal..
const char* anotherstring = "examplestring";
vector1.push_back(anotherstring); // gives error no matchcing member to call push_back
Can someone please correct me with the proper way of adding string to the vector?
Thanks in advance.
For starters in your code snippet there is no object of the type std::string. You code snippet deals with string literals.
String literals in C++ have types of constant character arrays.
So for example the string literal used in this call
vector1.push_back("examplestring");
can not be converted from the type const char[14] to the type char *.
If you are going to store in the vector only pointers to string literals then you should declare the vector like
std::vector<const char *> vector1;
Otherwise you need to dynamically allocate strings and push them on the vector. For example
#include <cstring>
#include <vector>
//...
std::vector<char *> vector1;
char *s = new char[ sizeof( "examplestring" )];
std::strcpy( s, "examplestring" );
vector1.push_back( s );
When the vector will not be needed any more you have to free the allocated memory for stored strings.
If you want to store objects of the type std::string nevertheless you have to create copies of the objects using dynamic memory allocation. Otherwise the lifetime of strings should be at least not less than the lifetime of the vector.
For example
std::vector<char *> vector1;
std::string str( "examplestring" );
char *s = new char[ str.size() + 1];
std::strcpy( s, str.c_str() );
vector1.push_back( s );
You can use const_cast to cast away const-ness for the sake of passing a const object where a non-const object is expected by an interface. Note, however, that this is just for bridging the interface; the function to which you pass the (casted) const-value (or any other part accessing the passed object) must not alter the object, though. This would yield undefined behaviour:
std::vector<char*> vector1;
const char* anotherstring = "examplestring";
char* anotherStringNonConst = const_cast<char*>(anotherstring);
vector1.push_back(anotherStringNonConst);
#include <cstdio>
//#include <string>
#include <vector>
int main() {
std::vector<const char*> vector1;
vector1.push_back("examplestring");
const char* anotherstring = "examplestring";
vector1.push_back(anotherstring);
for (auto* pCstring : vector1) {
printf("%s\n", pCstring);
}
return 0;
}
Using std::vector<const char*> works, but still suggest strongly to use std::vector<std::string> for memory safety.
How to append std::string to std::vector<char*>?
Example:
std::string example;
std::vector<char*> vector1;
vector1.push_back(example.data());
Note that you must be careful to keep example alive for at least as long as pointer is being used. And you mustn't modify the string in ways that would invalidate the pointer.

Convert to std::string and get const char * in one line

I have a number that I need to convert to a const char * (an API I'm using them requires const char * as input to many of its functions). The following works:
int num = 5;
std::string s = std::to_string(5);
const char * p = s.c_str();
as suggested by answers like those in how to convert from int to char*?, but it involves creating the seemingly unnecessary variable s, so I tried the following, but it doesn't work (p points to an empty string afterwards):
int num = 5;
const char * p = std::to_string(num).c_str();
Is there a clean way I can accomplish this? Why doesn't the second example work? The behavior is very similar to what happens if I made this obvious mistake:
const char * p;
{
std::string tempStr( "hi" );
p = tempStr.c_str( );
// p points to "hi" string.
}
// now p points to "" string.
Which makes me suspect that the issue std::to_string(num) immediately goes out of scope or something similar because it's not used to directly initialize anything.
std::string encapsulates managing dynamic memory (created with new[] and delete[]). Let's break it down.
const char * p = std::to_string(num).c_str();
Create a std::string (with a human-readable representation of num).
Get the new[]ly allocated const char* to the string.
Assign that value to p.
Destroy the std::string → delete[] the allocated const char*.
p points to... deallocated data
If you are using a pointer, the data that the pointer points to must exist throughout the lifetime of that pointer.
So, no, there is no way around this other than new[]ing a copy of the string, which you will have to explicitly delete[] later. And at that point, you've thrown the baby out with the bath and have no need to use std::string.
Create a string that lives at least as long as you want to refer to its internal data.
Just use std::string it does everything you want and everything that you would have to do manually if you don't use it.
When you need to pass a const char* to a const char* function simply use std::string::c_str() like this:
some_api_function(mystring.c_str()); // passes a const char*
What you need is a function which returns a char* which holds your value and can be used to manage its lifetime. The problematic version is broken because the char* points to memory which it does not manage.
For example:
std::unique_ptr<char[]> str(int32_t x)
{
std::unique_ptr<char[]> res(new char[12]);
snprintf(res.get(), 12, "%d", x);
return res;
}
Usestd::string everywhere and don't use const char* when not nessecary. They are basically the same thing. I use const char* only when I'm using a file-path.
Use std::string everywhere and your program should work.

Double pointer as parameter

I have the follow prototype:
int Split(const char* str, const char* delim,unsigned int& numtokens,char **tokensRes)
The last parameter is used to return the response of this function. In the function we have the follow:
.
.
char **tokens =(char**) calloc(tokens_alloc, sizeof(char*));
.
.
.
//at the end of the code
tokensRes = tokens;
.
When returns the value of tokens variable direct when the return of the function is char** I receive the correct answer, but using the method above the return of the function came empty. How can I make this function work correctly?
EDIT 1:
My intent is receive an array of char arrays, eg:
array[0] = "ABC"
array[1] = "ABC"
array[2] = "ABC"
array[3] = "ABC"
Change the prototype from:
int Split(const char* str, const char* delim,unsigned int& numtokens,char **tokensRes)
To:
int Split(const char* str, const char* delim,unsigned int& numtokens,char ** &tokensRes)
And the code tokensRes = tokens; will work. To understand why learn more about C++ and references.
Other answers about using strings are valid if you're planning to move from a C style of coding to a C++ one. The ease of coding would improve a lot and no worries about memory management and pointers (well not often), which are done automatically by classes. No worries about a performance decrease either as long as you follow good practices such as passing objects by reference and not value.
Assuming you want to return an array of strings (char**), then you need to pass a pointer to such an array that you can assign. That is, you need to pass a char*** and assign it like *tokensRes = tokens.
Just ditch the plain C types and use C++ types:
std::vector<std::string> Split(std:;string const& str, std::string const& delim, unsigned int& numtokens);
If you have to stick to the C interface, you need an additional indirection with a triple pointer (I am assuming that you want to return an array of token strings).
int Split(const char* str, const char* delim,unsigned int& numtokens,char ***tokensRes)
char** tokens;
Split("String;String", ";", 2, &tokens);
I really dislike output parameters, and I always wonder why anybody does not use std::string in C++.
Tokenizing has been implemented in many libraries, e.g. in boost::split or boost::tokenizer. No need to reinvent the wheel:
// simple_example_1.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "This is, a test";
tokenizer<> tok(s);
for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
The output from simple_example_1 is:
This
is
a
test

Copy string value into address

I have the following class
class MyClass{
char myValue[14] //has a 13 character string in it already
public
void toStr(char* str) const;
}
The instruction is: The member function toStr is query that receives the address of a C-style, null-terminated string and fills that address with the object's value
This function assumes that the caller has allocated enough space to hold a thirteen (13) character string.
So I coded:
void myClass::toStr(char* str) const
{
std::strcpy(str, myValue);
}
However str is receiving the address of myValue and not the string itself. I did quite a bit of searching here and couldn't find anything similiar. I CANNOT use dynamic memory in this exercise.
Here is your class used in a simple example (this is all I wanted you to post, but for some reason you couldn't do it).
#include <cstring>
#include <iostream>
class MyClass
{
char myValue[14];
public:
void toStr(char* str) const;
MyClass() { std::strcpy(myValue, "0123456789012"); }
};
void MyClass::toStr(char* str) const
{ std::strcpy(str, myValue); }
int main()
{
MyClass m;
char testString[100];
m.toStr(testString);
std::cout << testString;
}
This function works as expected. I see testString being assigned the myValue text. I added a constructor to MyClass to ensure it is the same as you described, namely that myValue has a 13 character string before the call to toStr.
Now take that example I posted, and either
1) Change whatever you need to change to duplicate your error -- comments can come later as to why what you did doesn't work, or
2) point out what you missed in your code that you see in the example above, thus fixing your error.
There is no plagiarism here, since I have no idea what your assignment is really supposed to be -- this is purely written given your description. See how easy it is just to provide a simple example?
In your assignment there is written that str can hold only 13 characters while myValue is defined as an array of 14 characters. So you should use std::strncpy instead of std::strcpyFor example
void myClass::toStr(char* str) const
{
std::strncpy(str, myValue, 13);
str[12] = '\0';
}
I think you get the weird result because myValue is not zero-terminated. If you are considering the both strings as some buffers of bytes then you should use function std::memcpy In this case the function will look as
void myClass::toStr(char* str) const
{
std::memcpy(str, myValue, 13);
}
I
Try this! You dont need to bother about myValue array size.
void myClass::toStr(char* pstr) const
{
std::string str(myValue);
pstr = new char[str.size()+1];
strcpy(pstr, str.c_str());
}
We obviously need more information on this. But what I understood, your calling code should be as below:
MyClass a;
char *astr = new char[15]; //Allocate enough space for astr to hold myValue
a.toStr(astr);
cout << astr;
delete astr;
Also, value should be assigned in constructor or any other setter as below:
strcpy(myValue,"Test String");
Edit: As explained in another answer by Vlad, strncpy should be better.
This function assumes that the caller has allocated enough space to
hold a thirteen (13) character string.
This means before calling your function, your string already allocated space (as I have done with new).
Looks like you mis-understood question.

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.