Linux string to char

std::string to char*

Results in: “error: cannot convert ‘std::string’ to ‘char’ . ”. What methods are there available to do this?

18 Answers 18

It won’t automatically convert (thank god). You’ll have to use the method c_str() to get the C string version.

std::string str = "string"; const char *cstr = str.c_str(); 

Note that it returns a const char * ; you aren’t allowed to change the C-style string returned by c_str() . If you want to process it you’ll have to copy it first:

std::string str = "string"; char *cstr = new char[str.length() + 1]; strcpy(cstr, str.c_str()); // do stuff delete [] cstr; 
std::vector cstr(str.c_str(), str.c_str() + str.size() + 1); 

@Kerrek SB: It was an example, would use a smart pointer in real code, or more likely avoid this c_str madness completely.

The answer is bulky, inelegant, non-local, uses raw arrays, and requires attention to exception safety. vector was invented precisely as a wrapper for dynamic arrays, so not using it seems like a missed opportunity at best, and in violation of the spirit of C++ at worst.

First of all, yes the answer is bulky. First I explain the OP’s error (thinking that std::string would automatically convert) and then I explain what he should use, with a short code sample. Thinking forward I also explain some side effects of the use of this function, of which one is that you may not edit the string returned by c_str() . You mistakenly see my short examples as real problem-solving code, which it’s not.

I downvoted the answer. This answer is indeed not useful and the fact that it was accepted is most unfortunate. This answer completely disregards good C++ programming practices and exception safety and there are far superior solutions, some of which are given in other answers to this question (e.g. the answer given by ildjarn which uses std::vector ).

@james-mcnellis, I picked this answer as the correct one because it answered EXACTLY what I was asking for. No more, no less. I did not ask for what you think that I should do, I did not ask for a different solution for what you think that I am doing, I did not ask for good practices. You have no idea what I am working in, where my code is going to be implemented and under what conditions. Some should learn to read, understand questions and to answer what is actually being asked. No need to show off here.

string str = "some string" ; char *cstr = &str[0]; 

As of C++11, you can also use the str.data() member function, which returns char *

string str = "some string" ; char *cstr = str.data(); 

FWIW, in my book, this is the only correct answer to the question that was actually asked. An std::string is inherently mutable: people who are making it sound like modifying the contents of the string is somehow the devil’s work seem to be missing this fact.

yes, this is the correct answer. it’s silly that, given the frequency of use, there isn’t a standart method to do this, like msoft’s lockbuffer.

I changed 0 to 0u. Because some compilers/libraries will (believe it or not) complain about some ambiguity when warnings are turned all the way on for the &str[0] construct

Читайте также:  Kali linux format usb

Note that this is C++11 only. Previous versions might not have continuous storage or are missing the terminating null

This is the only one that worked for me, for some reason c_str() kept stopping at my null bytes even though my reading seems to indicate that it shouldn’t. Maybe I did something else wrong somewhere else, but swapping c_str() with this (or even &str.first()) worked perfectly

If I’d need a mutable raw copy of a c++’s string contents, then I’d do this:

std::string str = "string"; char* chr = strdup(str.c_str()); 

So why don’t I fiddle with std::vector or new[] like anyone else? Because when I need a mutable C-style raw char* string, then because I want to call C code which changes the string and C code deallocates stuff with free() and allocates with malloc() (strdup uses malloc). So if I pass my raw string to some function X written in C it might have a constraint on it’s argument that it has to allocated on the heap (for example if the function might want to call realloc on the parameter). But it is highly unlikely that it would expect an argument allocated with (some user-redefined) new[]!

(This answer applies to C++98 only.)

Please, don’t use a raw char* .

std::string str = "string"; std::vector chars(str.c_str(), str.c_str() + str.size() + 1u); // use &chars[0] as a char* 

I actually just needed something like this earlier today. I was wondering, is it OK to say vector(str.c_str(), str.c_str() + str.size() + 1) , without assigning the char pointer to a temporary?

@Kerrek : Yes, the return value of std::basic_string<>::c_str() is valid until the string is changed or destroyed. This also implies that it returns the same value on subsequent calls as long as the string isn’t modified.

@friendzis : There is no speed or space overhead using vector in this way. And if one were to write exception-safe code without a RAII mechanism (i.e., using raw pointers), the code complexity would be much higher than this simple one-liner.

It’s a myth that vector has a huge amount of overhead and complexity. If your requirement is that you have a mutable char array, then in fact a vector of chars is pretty much the ideal C++ wrapper. If your requirement actually just calls for a const-char pointer, then just use c_str() and you’re done.

char* ca = new char[str.size()+1]; std::copy(str.begin(), str.end(), ca); ca[str.size()] = '\0'; 
size_t const MAX = 80; // maximum number of chars char ca[MAX] = <>; std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca); 

std::string doesn’t implicitly convert to these types for the simple reason that needing to do this is usually a design smell. Make sure that you really need it.

If you definitely need a char* , the best way is probably:

vector v(str.begin(), str.end()); char* ca = &v[0]; // pointer to start of vector 

Why &str.front(), &str.back() (which aren’t present in C++03) instead of the more common str.begin() and str.end() ?

what about str.begin() , or even std::begin(str) , iterator-like? I don’t believe string has any obligation to be in contiguous memory like vector , or has it?

@xtofl: I already edited those in. And yes, as of C++11 there is an obligation; this was implicit in C++03.

Читайте также:  Проверить размер папок linux

@xtofl: Not in C++03. In C++11 we have that guarantee, along with the front() and back() functions, which were misused in the original answer anyway

This would be better as a comment on bobobobo’s answer, but I don’t have the rep for that. It accomplishes the same thing but with better practices.

Although the other answers are useful, if you ever need to convert std::string to char* explicitly without const, const_cast is your friend.

std::string str = "string"; char* chr = const_cast(str.c_str()); 

Note that this will not give you a copy of the data; it will give you a pointer to the string. Thus, if you modify an element of chr , you’ll modify str .

There’s probably a good reason the API designers made the returned pointer const char* and not just char * . const says «don’t modify this object.» When you use const_cast , you are saying «I know better, I really can modify the object.» Or, you are saying «I won’t modify the object, I just need to pass it through this function that could have declared its input const but didn’t. Although it seems safe to just throw away the const ness of the C-string, because we know it’s mutable data underneath, you really shouldn’t. You should avoid use of const_cast when you can.

Correct. Sometimes, you have to interface with an older API and don’t have the luxury of rewriting the whole thing to be «clean and pure». Since on my VS the std::string.data () returns const char*, removing const-ness for few older methods (that have been production tested long before std::string was a thing) is definitely a right thing to do. For my situation.

Источник

convert string to char* [duplicate]

@john: Maybe some people thought that this is a duplicate of another question, or they thought that this question shows no effort, I don’t really know. For a beginner this isn’t an obvious question, but I don’t expect a comment from the downvoters in this case, since it’s a duplicate.

@Zeta Maybe but the downvotes appeared before any indication of the duplication. Seems like bad manners to me.

2 Answers 2

There are many ways. Here are at least five:

/* * An example of converting std::string to (const)char* using five * different methods. Error checking is emitted for simplicity. * * Compile and run example (using gcc on Unix-like systems): * * $ g++ -Wall -pedantic -o test ./test.cpp * $ ./test * Original string (0x7fe3294039f8): hello * s1 (0x7fe3294039f8): hello * s2 (0x7fff5dce3a10): hello * s3 (0x7fe3294000e0): hello * s4 (0x7fe329403a00): hello * s5 (0x7fe329403a10): hello */ #include #include #include int main() < std::string s0; const char *s1; char *s2; char *s3; char *s4; char *s5; // This is the initial C++ string. s0 = "hello"; // Method #1: Just use "c_str()" method to obtain a pointer to a // null-terminated C string stored in std::string object. // Be careful though because when `s0` goes out of scope, s1 points // to a non-valid memory. s1 = s0.c_str(); // Method #2: Allocate memory on stack and copy the contents of the // original string. Keep in mind that once a current function returns, // the memory is invalidated. s2 = (char *)alloca(s0.size() + 1); memcpy(s2, s0.c_str(), s0.size() + 1); // Method #3: Allocate memory dynamically and copy the content of the // original string. The memory will be valid until you explicitly // release it using "free". Forgetting to release it results in memory // leak. s3 = (char *)malloc(s0.size() + 1); memcpy(s3, s0.c_str(), s0.size() + 1); // Method #4: Same as method #3, but using C++ new/delete operators. s4 = new char[s0.size() + 1]; memcpy(s4, s0.c_str(), s0.size() + 1); // Method #5: Same as 3 but a bit less efficient.. s5 = strdup(s0.c_str()); // Print those strings. printf("Original string (%p): %s\n", s0.c_str(), s0.c_str()); printf("s1 (%p): %s\n", s1, s1); printf("s2 (%p): %s\n", s2, s2); printf("s3 (%p): %s\n", s3, s3); printf("s4 (%p): %s\n", s4, s4); printf("s5 (%p): %s\n", s5, s5); // Release memory. free(s3); delete [] s4; free(s5); >

Источник

Читайте также:  Самый маленький linux сервер

Need to convert String^ to char *

I am using the .NET DateTime to get the current date and time. I am converting it to a string to use as part of a file name. The problem is the OpenCV command to save an image requires a char * not a string type, and DateTime will only output a String^ type. How do I make this work? Heres the code not completed

String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); IplImage* toSave; CvCapture* capture = cvCreateCameraCapture(0); toSave = cvQueryFrame( capture ); cvSaveImage(nowString, toSave); cvReleaseImage(&toSave); cvReleaseCapture(&capture); 

«mistakenly»? I guess you mistakenly clicked submit, mistakenly forgetting to read before you submitted. You don’t need to explain or apologize. Just fix it. Many people do far worse things.

5 Answers 5

Your best bet is to use StringToHGlobalAnsi . Here is complete code showing how its done and remembering to free the memory allocated.

using namespace System::Runtime::InteropServices; void MethodName() < String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); IntPtr ptrToNativeString = Marshal::StringToHGlobalAnsi(nowString); try < CvCapture* capture = cvCreateCameraCapture(0); IplImage* toSave = cvQueryFrame(capture); cvSaveImage(static_cast(ptrToNativeString.ToPointer()), toSave); cvReleaseImage(&toSave); cvReleaseCapture(&capture); > catch (. ) < Marshal::FreeHGlobal(ptrToNativeString); throw; >Marshal::FreeHGlobal(ptrToNativeString); > 

You might want to rethink using a ‘:’ character in the filename, as I don’t believe windows likes this very much.

Would it be more appropriate to use Marshal::FreeHGlobal() instead of Marshal::FreeCoTaskMem()? My MSDN help for StringToHGlobalAnsi() says use FreeHGlobal() to free the memory.

Actually, I found the easiest way to get a char * from a String^ is to use good ol’ sprintf() . So in your case, you can simple do this:

char cNow[17] = < 0 >; String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator sprintf(cNow, "%s", nowString); 

No need to call the Marshal functions!

So it appears that VS 2015 adheres more closely to the C++11 standards, so using sprintf() with the .NET String won't work. The easiest way is to use the marshal_as() function like this:

Include these lines before your code:

#include using namespace msclr::interop; 
char cNow[17] = < 0 >; String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); string sNow = marshal_as(nowString); if (sNow.length() < sizeof(cNow)) // make sure it fits & allow space for null terminator sprintf(cNow, "%s", sNow.c_str()); 

Otherwise, if you don't want to use the marshal_as() function, you can copy the string character by character like this:

char cNow[17] = < 0 >; String^ nowString = DateTime::Now.ToString("yyyy-MM-dd-HH:mm"); if (nowString->Length < sizeof(cNow)) // make sure it fits & allow space for null terminator < for (int i = 0; i < nowString->Length; i++) cNow[i] = static_cast(nowString[i]); > 

Источник

Оцените статью
Adblock
detector