I have a string with non-ASCII characters, for example std::string word ("żółć"); or std::string word ("łyżwy");
I need to convert it properly to const char * in order to call system(my_String_As_A_Const_Char_Pointer);
I'm working on Linux.
How can I do it?
You can use the std::string::c_str member function. It will return a const char * that can be used in functions that accept that type of argument. Here's an example:
int main(int, char*[]) {
std::string word("żółć");
const char* x = word.c_str();
std::cout << x;
}
And here's a live example.
With these conversions the only thing to care about is mixing wide chars with normal chars (which fails horribly). You are using a std:string, so c_str() is fine for pulling out a const char* to pass to some other library call.
Related
I have just read about the overloading functions on a beginner book.
Just out of curiosity I 'd like to ask whether it is safe to overload between char* and std::string.
I played with the below code and get some result. But I was not sure whether it is an undefined behavior.
void foo(std::string str) {
cout << "This is the std::string version. " << endl;
}
void foo(char* str) {
cout << "This is the char* version. " << endl;
}
int main(int argc, char *argv[]) {
foo("Hello"); // result shows char* version is invoked
std::string s = "Hello";
foo(s); // result shows std::string version
return 0;
}
Yes, it's safe, as long as you make it const char*, and actually often useful. String literals cannot be converted to char* since C++11 (and it was deprecated before that).
The const char* overload will be picked for a string literal because a string literal is a const char[N] (where N is the number of characters). Overloads have a kind of priority ordering over which one will be picked when multiple would work. It's considered a better match to perform array-to-pointer conversion than to construct a std::string.
Why can overloading std::string and const char* be useful? If you had, for example, one overload for std::string and one for an bool, the bool would get called when you passed a string literal. That's because the bool overload is still considered a better match than constructing a std::string. We can get around this by providing a const char* overload, which will beat the bool overload, and can just forward to the std::string overload.
Short Answer: Perfectly safe. Consider the following uses:
foo("bar");//uses c string
foo(std::string("bar") );//uses std::string
char* bar = "bar";
foo(bar);//uses c string
std::string bar_string = "bar";
foo(bar_string);//uses std::string
foo(bar_string.c_str()); //uses c string
Word of warning, some compilers (namely those with c++11 enabled) require the const keyword in parameter specification in order to allow temporary strings to be used.
For instance, in order to get this:
foo("bar");
You need this:
void foo(const char* bar);
I have a few files named like so: file1, file2, file3, etc.
I have a function:
load(const char *file)
which I would call like so load(file1), load(file2), etc.
I am trying do this a bit more dynamically, based on the number of files imported.
So if I have more than 1 file do something like this:
if (NUM_OF_FILES > 1) {
for (int i = 2; i <= NUM_OF_FILES; i++) {
load("file" + i);
}
}
However, this is not working.
Is there a way of doing this?
The type of a string literal like "file" is char const[N] (with a suitable N) whic happily decays into a char const* upon the first chance it gets. Although there is no addition defeined between T[N] and int, there is an addition defined between char const* and int: it adds the int to the pointer. That isn't quite what you want.
You probably want to convert the int into a suitable std::string, combine this with the string literal you got, and get a char const* from that:
load(("file" + std::to_string(i)).c_str());
It depends on what version of C++ you are using. If it's C++11, the solution will involve std::to_string. If it's an older version of C++, you can convert an integer to a string like this:
#include <sstream>
// ...
std::ostringstream converter;
converter << i; // i is an int
std::string s(convert.str());
Now, the load function takes a const char *. Is it your own function? Then consider changing it so that it takes a std::string const& instead, and you'll be able to pass the string directly. Otherwise, this is how can pass the string's contents to it:
load(s.c_str());
I am converting a project written in C++ for windows. Everything is going fine (meaning I clearly see what needs to be changed to make things proper C++) until I hit this, which is my own little routine to find a keyword in along string of keyword=value pairs:
bool GetParameter(const char * haystack, const char *needle) {
char *search, *start;
int len;
len = strlen(needle) + 4; // make my own copy so I can upper case it...
search = (char *) calloc(1,len);
if (search == NULL) return false;
strcpy(search,needle);
strupr(search);
strcat(search,"="); // now it is 'KEYWORD='
start = strstr(haystack,search); <---- ERROR from compiler
g++ is telling me "Invalid conversion from const char * to char * "
(the precise location of the complaint is the argument variable 'search' )
But it would appear that g++ is dyslexic. Because I am actually going the other way. I am passing in a char * to a const char *
(so the conversion is "from char * to const char *" )
The strstr prototype is char * strstr(const char *, const char *)
There is no danger here. Nothing in any const char * is being modified.
Why is it telling me this?
What can I do to fix it?
Thanks for any help.
The background to the problem is that C defines the function strstr as:
char* strstr(const char*, const char*);
This is because C doesn't allow overloaded functions, so to allow you to use strstr with both const and non-const strings it accepts const strings and returns non-const. This introduces a weakness in C's already fragile type-system, because it removes const-ness from a string. It is the C programmer's job to not attempt to write via a pointer returned from strstr if you pased in non-modifiable strings.
In C++ the function is replaced by a pair of overloaded functions, the standard says:
7. The function signature strstr(const char*, const char*) shall be replaced by the two declarations:
const char* strstr(const char* s1, const char* s2);
char* strstr( char* s1, const char* s2);
both of which shall have the same behavior as the original declaration.
This is type-safe, if you pass in a const string you get back a const string. Your code passes in a const string, so G++ is following the standard by returning a const string. You get what you asked for.
Your code compiles on Windows because apparently the standard library you were using on Windows doesn't provide the overloads and only provides the C version. That allows you to pass in const strings and get back a non-const string. G++ provides the C++ versions, as required by the standard. The error is telling you that you're trying to convert the const return value to a non-const char*. The solution is the assign the return value to a const char* instead, which is portable and compiles everywhere.
Error is not regarding the arguments to stsrtr. Compiler is complaining about the conversion of the 'const char *' returned by strstr. You can't assign it to *start which is just char *
You can try one of these:
const char *start;
or
string start(strstr(haystack,search));
Although declaring start as const char* might suffice, what seems more appropriate to me is to use std::string objects instead:
#include <string>
#include <cctype>
#include <algorithm>
bool GetParameter(const char * haystack, const char *needle) {
std::string hstr(haystack), nstr(needle);
std::transform(nstr.begin(), nstr.end(),nstr.begin(), ::toupper);
nstr += "=";
std::size_t found = hstr.find(nstr);
if (found != std::string::npos) {
... // "NEEDLE=" found
}
else {
...
}
...
}
The conversion it is complaining about is from strstr(...) to start. Change the declaration of start to const char* start;
you can use such like:
start = const_cast<char *>(strstr( haystack, static_cast<const char *>(search) ));
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*.
When I wrote the following code and executed it, the compiler said
deprecated conversion from string constant to char*
int main()
{
char *p;
p=new char[5];
p="how are you";
cout<< p;
return 0;
}
It means that I should have written const char *.
But when we pass arguments into main using char* argv[] we don't write const char* argv[].
Why?
Because ... argv[] isn't const. And it certainly isn't a (static) string literal since it's being created at runtime.
You're declaring a char * pointer then assigning a string literal to it, which is by definition constant; the actual data is in read-only memory.
int main(int argc, char **argv) {
// Yes, I know I'm not checking anything - just a demo
argv[1][0] = 'f';
std::cout << argv[1] << std::endl;
}
Input:
g++ -o test test.cc
./test hoo
Output:
foo
This is not a comment on why you'd want to change argv, but it certainly is possible.
Historical reasons. Changing the signature of main() would break too much existing code. And it is possible that some implementations allow you to change the parameters to main from your code. However code like this:
char * p = "helllo";
* p = 'x';
is always illegal, because you are not allowed to mess with string literals like that, so the pointer should be to a const char.
why is it required for char* to be constant while assigning it to a string
Because such literal strings (like "hi", "hello what's going on", etc), are stored in the read-only segment of your exe. As such, the pointers that point to them need to point to constant characters (eg, can't change them).
You are assigning a string constant (const char*) to a pointer to a non-constant string (char *p). This would allow you to modify the string constant, e.g. by doing p[0] = 'n'.
Anyway, why don't you use std::string instead ? (you seem to be using C++).
If you look at execution functions like execve, you will see that they actually don't accept const char* as parameters, but do indeed require char*, therefore you can't use a string constant to invoke main.