Initializing std::string with const char * results in gibberish - c++

I use rapidjson to read JSON files, and some of the values are string. Now, rapidjson's GetString() method returns a const char *. I'd like to store this in std::string, though. I've tried this:
const char* foo = d["foo"].GetString();
printf("Foo: %s\n", foo); // Prints correctly
std::string fooStr(foo);
printf("FooString: %s\n", fooStr); // Gibberish
How do I get the correct std::string?

You can't pass std::string directly to printf. It's a C-style variadic function, that only works with C-compatible types, not (non-trivial) C++ classes. In particular, the %s specifier requires its matching argument to be a pointer to C-style string (a zero-terminated character array), of type const char *.
You can either use a C++ stream:
std::cout << "FooString: " << fooStr << '\n';
or extract a C-style pointer from the string:
printf("FooString: %s\n", fooStr.c_str());
You should also enable compiler warnings; that should tell you exactly what's wrong.

To convert string to const char* use string::c_str()

Related

What is wrong with this char array to std::string conversion?

I'm trying to convert a char array to an std::string, but I only get gibberish in the std::string. What is wrong?
char char_buff[40];
sprintf_s(char_buff, 40, "test" );
printf("%s\n", char_buff); // prints "test"
std::string str(char_buff);
printf("%s\n", str); // prints random nonsense
Passing a std::string to printf gives undefined behavior.
When you try to print out the string instance, try using std::cout instead:
char char_buff[40];
sprintf_s(char_buff, 40, "test" );
std::cout << char_buff << "\n";
std::string str(char_buff);
std::cout << str << "\n";
std::string str(char_buff);
printf("%s\n", str); // prints random nonsense
The problem is that %s makes printf() expect a const char*; in other words, %s is a placeholder for const char*.
Instead, you passed str, which is an instance of std::string, not a const char*.
To fix that, just use the c_str() method of std::string:
printf("%s\n", str.c_str());
c_str() returns a C-style pointer to a NUL-terminated string, as expected from C functions like printf().
As a side note:
char char_buff[40];
sprintf_s(char_buff, 40, "test" );
Note that sprintf_s() can be used in a simpler form, making it to automatically deduce the destination buffer length, thanks to some template "magic":
sprintf_s(char_buff, "test"); // char_buff size automatically deduced
See this sprintf_s() template from MSDN documentation:
template <size_t size>
int sprintf_s(
char (&buffer)[size],
const char *format [,
argument] ...
); // C++ only
Unfortunately, printf is an old c function and is not type safe. It just interprets the given arguments as you tell it to.
By using the %s as the first occurring format specifier you tell printf to interpret the first argument as a char *, causing gibberish to be printed.
In order to have the contents of the string be printed you need to get to the char* data that the std::string wraps. You can do this using .c_str().

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*.

C++ converting string to char is not working

I have the following code to convert a string to char :
string tempLine = dataLine[studentIndex];
char str = tempLine.c_str();
but this line returns an error : " a value of type "constant char *" cannot be used to initialize an entity of type "char".
How can I fix this issue??
should be:
const char *str = tempLine.c_str();
Note that you're not supposed to change the content of the string. Generally, its not a good way to work with C++ strings. If you really have to fully convert a C++ string to C string - allocate memory and use strcpy to copy data, don't use the C++ string buffers directly.
edit for your request in the comments: Look here for C++ learning resources.
You cannot convert a const char*, which is what std::string::c_str() returns, to char. Change:
char str = tempLine.c_str();
to:
const char* str = tempLine.c_str();
Note this does not copy the characters in tempLine to str, str just refers to the characters in tempLine.

What is the use of the c_str() function?

I understand c_str converts a string, that may or may not be null-terminated, to a null-terminated string.
Is this true? Can you give some examples?
c_str returns a const char* that points to a null-terminated string (i.e., a C-style string). It is useful when you want to pass the "contents"¹ of an std::string to a function that expects to work with a C-style string.
For example, consider this code:
std::string string("Hello, World!");
std::size_t pos1 = string.find_first_of('w');
std::size_t pos2 = static_cast<std::size_t>(std::strchr(string.c_str(), 'w') - string.c_str());
if (pos1 == pos2) {
std::printf("Both ways give the same result.\n");
}
See it in action.
Notes:
¹ This is not entirely true because an std::string (unlike a C string) can contain the \0 character. If it does, the code that receives the return value of c_str() will be fooled into thinking that the string is shorter than it really is, since it will interpret \0 as the end of the string.
In C++, you define your strings as
std::string MyString;
instead of
char MyString[20];.
While writing C++ code, you encounter some C functions which require C string as parameter.
Like below:
void IAmACFunction(int abc, float bcd, const char * cstring);
Now there is a problem. You are working with C++ and you are using std::string string variables. But this C function is asking for a C string. How do you convert your std::string to a standard C string?
Like this:
std::string MyString;
// ...
MyString = "Hello world!";
// ...
IAmACFunction(5, 2.45f, MyString.c_str());
This is what c_str() is for.
Note that, for std::wstring strings, c_str() returns a const w_char *.
Most old C++ and C functions, when dealing with strings, use const char*.
With STL and std::string, string.c_str() is introduced to be able to convert from std::string to const char*.
That means that if you promise not to change the buffer, you'll be able to use read-only string contents. PROMISE = const char*
In C/C++ programming there are two types of strings: the C strings and the standard strings. With the <string> header, we can use the standard strings. On the other hand, the C strings are just an array of normal chars. So, in order to convert a standard string to a C string, we use the c_str() function.
For example
// A string to a C-style string conversion //
const char *cstr1 = str1.c_str();
cout<<"Operation: *cstr1 = str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"\nOperation: strlen(cstr1)"<<endl;
cout<<"The length of C-style string str1 = "<<strlen(cstr1)<<endl;
And the output will be,
Operation: *cstr1 = str1.c_str()
The C-style string c_str1 is: Testing the c_str
Operation: strlen(cstr1)
The length of C-style string str1 = 17
c_str() converts a C++ string into a C-style string which is essentially a null terminated array of bytes. You use it when you want to pass a C++ string into a function that expects a C-style string (e.g., a lot of the Win32 API, POSIX style functions, etc.).
It's used to make std::string interoperable with C code that requires a null terminated char*.
You will use this when you encode/decode some string object you transfer between two programs.
Let’s say you use Base64 to encode some array in Python, and then you want to decode that into C++. Once you have the string you decode from Base64-decoded in C++. In order to get it back to an array of float, all you need to do here is:
float arr[1024];
memcpy(arr, ur_string.c_str(), sizeof(float) * 1024);
This is pretty common use, I suppose.
const char* c_str() const;
It returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C string), representing the current value of the string object.
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null - character ('\0') at the end.
std::string str = "hello";
std::cout << str; // hello
printf("%s", str); // ,²/☺
printf("%s", str.c_str()); // hello

How to convert a char* pointer into a C++ string?

I have a C++ string. I need to pass this string to a function accepting a char* parameter (for example - strchr()).
a) How do I get that pointer?
b) Is there some function equivalent to strschr() that works for C++ strings?
To get the C string equivalent of
the C++ string object use c_str
function.
To locate the first occurence of a
char in a string object use
find_first_of function.
Example:
string s = "abc";
// call to strlen expects char *
cout<<strlen(s.c_str()); // prints 3
// on failure find_first_of return string::npos
if(s.find_first_of('a') != string::npos)
cout<<s<<" has an a"<<endl;
else
cout<<s<<" has no a"<<endl;
Note: I gave the strlen just an example of a function that takes char*.
Surprisingly, std:;string has far, far more capabilities than C-style strings. You probably want the find_first_of() method. In general, if you find yourself using the strxxx() functions on C++ std::strings, you are almost certainly doing something wrong.
Like much of the C++ Standard Library, the string class is a complex beast. To make the most of it, you really need a good reference book. I recommend The C++ Standard Library, by Nicolai Josuttis.
You can't get a char* from a string
string does not allow you free access to its internal buffer.
The closest you can get is a const char* using .c_str() if you want it null terminated or .data() if it doesn't have to be null terminated.
You can then cast the pointer returned by these functions to char* but you do this on your own risk. That being said this is a relatively safe cast to make as long as you make sure you're not changing the string. If you changed it then the pointer you got from c_str() may no longer be valid.
This code:
string str("Hello World!");
char* sp = (char*)str.c_str();
sp[5] = 'K';
is probably ok
However this:
string str("Hello World!");
char* sp = (char*)str.c_str();
str = "Chaged string";
sp[5] = 'K';
is most definitely not ok.
If you just want to assign a string literal to pw, you can do it like
char *pw = "Hello world";
If you have a C++ std::string object, the value of which you want to assign to pw, you can do it like
char *pw = some_string.c_str()
However, the value that pw points to will only be valid for the life time of some_string.
More here :
How to assign a string to char *pw in c++
GoodLUCK!!
std::string yourString("just an example");
char* charPtr = new char[yourString.size()+1];
strcpy(charPtr, yourString.c_str());
If str in your string use str.c_str() method to get the char* inside it.
Perhaps this exmaple will help you
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("Replace the vowels in this sentence by asterisks.");
size_t found;
found=str.find_first_of("aeiou");
while (found!=string::npos)
{
str[found]='*';
found=str.find_first_of("aeiou",found+1);
}
cout << str << endl;
return 0;
}
The C++ Standard provides two member functions of claass std::basic_string that return pointer to the first element of the string. They are c_str() and data(). But the both return const char *, So you may not use them with a function that has parameter of type char *.
As for function strchr then its first parameter is const char *. So you may use c_str() and data() with this function. However it is much better to use member function find()of class sttd::basic_string instead of strchr.