C++: How to convert 'const char*' to char - c++

I know there are a lot of questions like this out there on StackOverflow, but I haven't been able to find any that help resolve my case. Whenever I try to do something like this:
// str = some string or char array
// some magic to get around fpermissive errors
stringstream convert;
convert << str;
// capture the stream's temporary string
const string store = convert.str();
// get a manageable array
const char* temp = store.c_str();
and then try to do something like atoi(temp[0]), I keep getting the classic conversion error that char couldn't be converted to const char. In the documentation for atoi and many other functions, const char is a required parameter. How can a char be sent in if there's only a const one? Does retrieving a char at a specific position auto-cast to char?

I'm not sure if this is what is causing the error, but atoi takes as its parameter not a char, but the pointer to one. So instead of
atoi(temp[0])
try this
atoi(&temp[0])
as that is a pointer.

Related

conversion between char* and std::string and const char*

I am now using C++ to program a robot using PROS. Pros has a print function, which is taking in a const char*. Now, I'm using lvgl to create my own screen, and I want to replicate the print function. Like the printf() functions, I want it to include variadic params to do the %d effect (so it converts all the %? to the corresponding values). The problem now is about the conversions between functions. I wanted to make a convert function to convert a string and the variadic params into a complete string. I need to input is a string which is like "hey" and I'm unsure what the type name should be. I need to be able to get size, search in it for %ds but I need the function to return a const char* to pass onto the lvgl to pring on the screen. I am having a bad time trying to convert a string into an const char* for the out put of the convert function.
Also, I tried using the input type as a char*, and when I input a string like "hello" is says a error [ISO C++11 does not allow conversion from string literal to 'char ' [-Wwritable-strings]]. But instead, when is use a const char, the error disappears. Anyone knows why?
Thanks everyone for your kind help!
char* and const char* are two flavours of the same thing: C-style strings. These are a series of bytes with a NUL terminator (0-byte). To use these you need to use the C library functions like strdup, strlen and so on. These must be used very carefully as missing out on the terminator, which is all too easy to do by accident, can result in huge problems in the form of buffer-overflow bugs.
std::string is how strings are represented in C++. They're a lot more capable, they can support "wide" characters, or variable length character sets like UTF-8. As there's no NUL terminator in these, they can't be overflowed and are really quite safe to use. Memory allocation is handled by the Standard Library without you having to pay much attention to it.
You can convert back and forth as necessary, but it's usually best to stick to std::string inside of C++ as much as you can.
To convert from C++ to C:
std::string cppstring("test");
const char* c_string = cppstring.c_str();
To convert from C to C++:
const char* c_string = "test";
std::string cppstring(c_string);
Note you can convert from char* (mutable) to const char* (immutable) but not in reverse. Sometimes things are flagged const because you're not allowed to change them, or that changing them would cause huge problems.
You don't really have to "convert" though, you just use char* as you would const char*.
std::string A = "hello"; //< assignment from char* to string
const char* const B = A.c_str(); //< call c_str() method to access the C string
std::string C = B; //< assignment works just fine (with allocation though!)
printf("%s", C.c_str()); //< pass to printf via %s & c_str() method

Initializing char Buffer with a string in c++

I wan't to initialize a static char buffer with a string str in the code below but I am getting the following error :
error: cannot convert ‘std::string’ to >‘char’ in initialization
and if I use
static char buf[500] = str.c_str();
I get the following error:
error: invalid conversion from ‘const char*’ to ‘char*’
Below is my code :
std::string str = "<Version="+version+" Ret=\"false\"/>";
static char buf[500] = str;
int len=strlen(buf);
buf[len]='\0';
INFO("Static Buffer :: "<<buf);
First of all, you cannot directly initialise a char[] from an std::string. It's just not possible. Even if you could, you would write = str, not = { str }.
So, you need to create the array first then assign the std::string's contents to it manually. Sadly, arrays are not assignable, so you're going to have to use an "algorithm" to do it.
Here we go:
const std::string str = "Hello world";
static char buf[500] = {};
std::copy(
// from the start of the string
std::begin(str),
// to the end of the string, or to 499 chars in, whichever comes first
std::begin(str) + std::min(str.size(), sizeof(buf)),
// into buf
std::begin(buf)
);
Yuck.
If you can, and this is likely the case, avoid it.
If you really need a C-string with the std::string's contents, just access str.c_str() whenever you need to. There is, in general, no need to keep a raw char array lying about, especially when you already have the right tool for the job doing that job.
Besides, as you are not initialising buf with that data, if it's function-static, this code probably does not have the intended effect.
You can use std::string::copy().
std::string text = "Hello there!";
char* cStrText = new char[text.length()];
//Copy the string into the buffer
text.copy(cStrText, text.length(), 0);
Obviously, this performs a copy which may not be optimal. You might want to look into trying to move it.
https://www.cplusplus.com/reference/string/string/copy/

How can I convert const char* to string and then back to char*?

I'm just starting c++ and am having difficulty understanding const char*. I'm trying to convert the input in the method to string, and then change the strings to add hyphens where I want and ultimately take that string and convert it back to char* to return. So far when I try this it gives me a bus error 10.
char* getHyphen(const char* input){
string vowels [12] = {"A","E","I","O","U","Y","a","e","i","o","u","y"};
//convert char* to string
string a;
int i = 0;
while(input != '\0'){
a += input[i];
input++;
i++;
}
//convert a string to char*
return NULL;
}
A: The std::string class has a constructor that takes a char const*, so you simply create an instance to do your conversion.
B: Instances of std::string have a c_str() member function that returns a char const* that you can use to convert back to char const*.
auto my_cstr = "Hello"; // A
std::string s(my_cstr); // A
// ... modify 's' ...
auto back_to_cstr = s.c_str(); // B
First of all, you don't need all of that code to construct a std::string from the input. You can just use:
string a(input);
As far as returning a new char*, you can use:
return strdup(a.c_str()); // strdup is a non-standard function but it
// can be easily implemented if necessary.
Make sure to deallocate the returned value.
It will be better to just return a std::string so the users of your function don't have to worry about memory allocation/deallocation.
std::string getHyphen(const char* input){
Don't use char*. Use std::string, like all other here are telling you. This will eliminate all such problems.
However, for the sake of completeness and because you want to understand the background, let's analyse what is going on.
while(input != '\0'){
You probably mean:
while(*input != '\0') {
Your code compares the input pointer itself to \0, i.e. it checks for a null-pointer, which is due to the unfortunate automatic conversion from a \0 char. If you tried to compare with, say, 'x' or 'a', then you would get a compilation error instead of runtime crashes.
You want to dereference the pointer via *input to get to the char pointed to.
a += input[i];
input++;
i++;
This will also not work. You increment the input pointer, yet with [i] you advance even further. For example, if input has been incremented three times, then input[3] will be the 7th character of the original array passed into the function, not the 4th one. This eventually results in undefined behaviour when you leave the bounds of the array. Undefined behaviour can also be the "bus error 10" you mention.
Replace with:
a += *input;
input++;
i++;
(Actually, now that i is not used any longer, you can remove it altogether.)
And let me repeat it once again: Do not use char*. Use std::string.
Change your function declaration from
char* getHyphen(const char* input)
to
auto hyphenated( string const& input )
-> string
and avoid all the problems of conversion to char const* and back.
That said, you can construct a std::string from a char_const* as follows:
string( "Blah" )
and you get back a temporary char const* by using the c_str method.
Do note that the result of c_str is only valid as long as the original string instance exists and is not modified. For example, applying c_str to a local string and returning that result, yields Undefined Behavior and is not a good idea. If you absolutely must return a char* or char const*, allocate an array with new and copy the string data over with strcpy, like this: return strcpy( new char[s.length()+1], s.c_str() ), where the +1 is to accomodate a terminating zero-byte.

Converting double to string. Boost Libraries appear not to work, and sstream causes "SEG FAULT"

I have a simple problem, and I think I'm just doing something stupid which is causing a SEGFAULT.
I simply want to convert a double variable to a string, and then 'strcat()' them both together and put the resultant concatenated string in a GTK Label. (It should be simple, surely?!)
Here is a section of my code:
double fps_target = 2.71828
std::string fps_target_string;
std::stringstream convert;
convert << fps_target;
fps_target_string = convert.str();
g_print("seg fault occurs below");
label_fps_target = gtk_label_new(strcat("FPS Target: ",
(const char*) fps_target_string.c_str()));
Why cannot it work?! :(
I tried using the Boost::Lexical_Cast thing, but that didn't work:
double fps_target = 3.14159;
const char* fps_target_string = (const char*) (boost::lexical_cast<std::string>(fps_target));
Any help is greatly appreciated. If either method works that would be awesome, but I'm not really bothered about how to do it, so long as I can get a double to cat with a string!
It shouldn't even compile. Make sure you have your compiler's warning and conformance levels set to high. That will save you much trouble in the long run.
Let us look at strcat's signature:
char *strcat( char *dest, const char *src );
So, it takes a char* as first parameter. But "FPS Target: " has type char const[13] which decays to char const*, which cannot be passed as a char*. char* allows modification, but char const* doesn't (string literals are not mutable!). This first parameter is char* because that's the buffer where the result will be put. You can't put it in that string literal because:
String literals are read-only;
That string literal is not large enough.
The second argument doesn't need a cast, as the return type of c_str() is already char const*.
The simplest way to concatenate strings is to use std::string and not bother with the C library string manipulation functions.
std::string result = "FPS Target: " + fps_target_string;
g_print("seg fault doesn't occur below");
label_fps_target = gtk_label_new(result.c_str());
Since the code is already using a stringstream, an even easier way would be to just insert both parts into the stream.
std::stringstream convert;
convert << "FPS Target: " << fps_target;
std::string result = convert.str();
g_print("seg fault doesn't occur below");
label_fps_target = gtk_label_new(result.c_str());
strcat() uses the first parameter as the output buffer. Of course, strcat("FPS Target: "...) will crash. Allocate a buffer and pass it as a first parameter.
const char* fps_target_string = (const char*) boost::lexical_cast<std::string>(fps_target) won't compile, because there's no conversion from std::string to const char*.

Tinyxml to print attributes

I'm trying to get std::string from attribute's value with TinyXml.
The only thing I can get is a const char * val, and I can't find any way to convert from const char * to a std::string.
so two possible answers to that:
1. How to get a string of an attribute with TinyXml?
2. How to convert const char * val to string val.
this is the code I have now:
TiXmlElement* data;
data->Attribute("some_name"); // return const char * which seems like unconvertible.
After googeling, I tried this:
char * not_const= const_cast<char *> (data->Attribute("some_name"));
There are no errors in the code itself, but after compiling and running I get exceptions.
std::string has a constructor that takes char const*. You don't need a char* for that.
std::string str = data->Attribute("some_name");
However, be aware that std::string doesn't like NULL values, so don't give it any.