C++ stringstream string to function(test, char *test2) - c++

Have a MySQL query function, that needs to take a string parameter.
Which looks like this:
cin >> user_string;
stringstream ss;
ss << "select * from " << user_string;
Function looks like this:
mysql_perform_query(MYSQL *connection, char *sql_query)
Tried to convert to ss.c_str(); or ss.str().c_str();
Does not work.
What would be the correct way to do this? Skip Stingstream and build char?
C++ Strings confuses me...

It's unusual that mysql_perform_query doesn't want a const char *.
If that's your code, change it to accept a const char * and your approach will work.
mysql_perform_query( connection, user_string.str().c_str() );
If you can't change that function signature, this will work*.
mysql_perform_query( connection, &user_string.str()[0] );
*It's guaranteed to work in C++11, and while not guaranteed in C++03, does work in all common implementations

The SQL interface probably requires a char const*. ss.str()
will give you a string, and ss.str().c_str() will give you
a char const* from that string.
To points, however (more style than anything):
unless you actually need the bidirectional capacities of
stringstream, it's probably preferable to use the simpler
ostringstream (which only does output), and
if all you're doing is concatenation, there's no point in
using streams at all, just use the + operator on the strings.
(You can also use + to concatenate a string and a string
literal.) Streams are really for formatting and parsing, and
are overkill (unnecessary added complexity) for simple
concatenation.

ss.str().c_str() would be correct if only your function was
mysql_perform_query(MYSQL *connection, const char *sql_query);
This is because c_str() returns const char *.
If you are able to change the mysql_perform_query function to const char * then I would do so. Otherwise you could consider doing a const_cast, const_cast<char*>(ss.str().c_str()).
In the unlikely event that mysql_perform_query really does modify the C string being passed to it then you will have to copy your string to a vector and pass a pointer to that instead.
string str = ss.str();
vector<char> tmp(str.begin(), str.end());
tmp.push_back('\0');
mysql_perform_query(connection, &tmp[0]);

ss.str().c_str() is a const char * not a char * that is required. I would copy ss.str().c_str() into a char * then pass it to the function.

stringstream has a str method that returns a std::string; std::string has a c_str() method that returns a pointer to a char.
mysql_perform_query(connection, ss.str().c_str());
You did do a proper search before posting your question, didn't you?

Related

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

Converting string to C style string

I am trying to convert an int to a cstring. I've decided to read the int into a regular string via stringstream, and then read the string into a char array. The following seems to be working, but I'm wondering if I'm just getting lucky with my compiler. Does the code seem sound? Thanks!
int zip = 1234;
char zipString[30];
stringstream str;
str << zip;
str >> zipString;
cout << zipString;
You can get a C++ std::string from the stream's str() function, and an immutable C-style zero-terminated string from the string's c_str() function:
std::string cpp_string = str.str();
char const * c_string = cpp_string.c_str();
You might be tempted to combine these into a single expression, str.str().c_str(), but that would be wrong; the C++ string will be destroyed before you can do anything with the pointer.
What you are doing will work, as long as you're sure that the buffer is large enough; but using the C++ string removes the danger of overflowing the buffer. In general, it's best to avoid C-style strings unless you need to use an API that requires them (or, in extreme circumstances, as an optimisation to avoid memory allocation). std::string is usually safer and easier to work with.
Unless you have a specific reason that you need an array of char instead of a standard string, I'd use the latter. Although it's not strictly necessary in this case, I'd also normally use a Boost lexical_cast instead of explicitly moving things through a stringstream to do the conversion:
std::string zipString = lexical_cast<std::string>(zip);
Then, if you really need the result as a c-style string, you can use zipString.c_str() to get that (though it's still different in one way -- you can't modify what that returns).
In this specific case it doesn't gain you a lot, but consistent use for conversions on this general order adds up, and if you're going to do that, you might as well use it here too.
The std::string's c_str() member function returns a const char* (aka a C-style string).
std::string str = "world";
printf("hello, %s", str.c_str());

std::string.c_str() has different value than std::string?

I have been working with C++ strings and trying to load char * strings into std::string by using C functions such as strcpy(). Since strcpy() takes char * as a parameter, I have to cast it which goes something like this:
std::string destination;
unsigned char *source;
strcpy((char*)destination.c_str(), (char*)source);
The code works fine and when I run the program in a debugger, the value of *source is stored in destination, but for some odd reason it won't print out with the statement
std::cout << destination;
I noticed that if I use
std::cout << destination.c_str();
The value prints out correctly and all is well. Why does this happen? Is there a better method of copying an unsigned char* or char* into a std::string (stringstreams?) This seems to only happen when I specify the string as foo.c_str() in a copying operation.
Edit: To answer the question "why would you do this?", I am using strcpy() as a plain example. There are other times that it's more complex than assignment. For example, having to copy only X amount of string A into string B using strncpy() or passing a std::string to a function from a C library that takes a char * as a parameter for a buffer.
Here's what you want
std::string destination = source;
What you're doing is wrong on so many levels... you're writing over the inner representation of a std::string... I mean... not cool man... it's much more complex than that, arrays being resized, read-only memory... the works.
This is not a good idea at all for two reasons:
destination.c_str() is a const pointer and casting away it's const and writing to it is undefined behavior.
You haven't set the size of the string, meaning that it won't even necessealy have a large enough buffer to hold the string which is likely to cause an access violation.
std::string has a constructor which allows it to be constructed from a char* so simply write:
std::string destination = source
Well what you are doing is undefined behavior. Your c_str() returns a const char * and is not meant to be assigned to. Why not use the defined constructor or assignment operator.
std::string defines an implicit conversion from const char* to std::string... so use that.
You decided to cast away an error as c_str() returns a const char*, i.e., it does not allow for writing to its underlying buffer. You did everything you could to get around that and it didn't work (you shouldn't be surprised at this).
c_str() returns a const char* for good reason. You have no idea if this pointer points to the string's underlying buffer. You have no idea if this pointer points to a memory block large enough to hold your new string. The library is using its interface to tell you exactly how the return value of c_str() should be used and you're ignoring that completely.
Do not do what you are doing!!!
I repeat!
DO NOT DO WHAT YOU ARE DOING!!!
That it seems to sort of work when you do some weird things is a consequence of how the string class was implemented. You are almost certainly writing in memory you shouldn't be and a bunch of other bogus stuff.
When you need to interact with a C function that writes to a buffer there's two basic methods:
std::string read_from_sock(int sock) {
char buffer[1024] = "";
int recv = read(sock, buffer, 1024);
if (recv > 0) {
return std::string(buffer, buffer + recv);
}
return std::string();
}
Or you might try the peek method:
std::string read_from_sock(int sock) {
int recv = read(sock, 0, 0, MSG_PEEK);
if (recv > 0) {
std::vector<char> buf(recv);
recv = read(sock, &buf[0], recv, 0);
return std::string(buf.begin(), buf.end());
}
return std::string();
}
Of course, these are not very robust versions...but they illustrate the point.
First you should note that the value returned by c_str is a const char* and must not be modified. Actually it even does not have to point to the internal buffer of string.
In response to your edit:
having to copy only X amount of string A into string B using strncpy()
If string A is a char array, and string B is std::string, and strlen(A) >= X, then you can do this:
B.assign(A, A + X);
passing a std::string to a function from a C library that takes a char
* as a parameter for a buffer
If the parameter is actually const char *, you can use c_str() for that. But if it is just plain char *, and you are using a C++11 compliant compiler, then you can do the following:
c_function(&B[0]);
However, you need to ensure that there is room in the string for the data(same as if you were using a plain c-string), which you can do with a call to the resize() function. If the function writes an unspecified amount of characters to the string as a null-terminated c-string, then you will probably want to truncate the string afterward, like this:
B.resize(B.find('\0'));
The reason you can safely do this in a C++11 compiler and not a C++03 compiler is that in C++03, strings were not guaranteed by the standard to be contiguous, but in C++11, they are. If you want the guarantee in C++03, then you can use std::vector<char> instead.

Convert std::string to char * alternative

I have done a search in google and been told this is impossible as I can only get a static char * from a string, so I am looking for an alternative.
Here is the situation:
I have a .txt file that contains a list of other .txt files and some numbers, this is done so the program can be added to without recompilation. I use an ifstream to read the filenames into a string.
The function that they are required for is expecting a char * not a string and apparently this conversion is impossible.
I have access to this function but it calls another function with the char * so I think im stuck using a char *.
Does anyone know of a work around or another way of doing this?
In C++, I’d always do the following if a non-const char* is needed:
std::vector<char> buffer(str.length() + 1, '\0');
std::copy(str.begin(), str.end(), buffer.begin());
char* cstr = &buffer[0];
The first line creates a modifiable copy of our string that is guaranteed to reside in a contiguous memory block. The second line gets a pointer to the beginning of this buffer. Notice that the vector is one element bigger than the string to accomodate a null termination.
You can get a const char* to the string using c_str:
std::string str = "foo bar" ;
const char *ptr = str.c_str() ;
If you need just a char* you have to make a copy, e.g. doing:
char *cpy = new char[str.size()+1] ;
strcpy(cpy, str.c_str());
As previous posters have mentioned if the called function does in fact modify the string then you will need to copy it. However for future reference if you are simply dealing with an old c-style function that takes a char* but doesn't actually modfiy the argument, you can const-cast the result of the c_str() call.
void oldFn(char *c) { // doesn't modify c }
std::string tStr("asdf");
oldFn(const_cast< char* >(tStr.c_str());
There is c_str(); if you need a C compatible version of a std::string. See http://www.cppreference.com/wiki/string/basic_string/c_str
It's not static though but const. If your other function requires char* (without const) you can either cast away the constness (WARNING! Make sure the function doesn't modify the string) or create a local copy as codebolt suggested. Don't forget to delete the copy afterwards!
Can't you just pass the string as such to your function that takes a char*:
func(&string[0]);

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.