1

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?

4
  • 1
    The obvious question is: Can you not modify your existing function(s) to take a const char *? If those functions don't modify the input, then they really should be const. Commented Apr 11, 2011 at 11:02
  • @Oli It does modify the string im afraid hence the trouble Commented Apr 11, 2011 at 11:14
  • Do you want the changes to be visible back in the original std::string? Commented Apr 11, 2011 at 11:17
  • @Oli the program reads this one file. in it are the names of all the files it has to load in order to run the game. maps can be added or subtracted at the designers whim. As long as the function gets them I never use them again, if I could I would read them in as char *. Commented Apr 11, 2011 at 11:25

5 Answers 5

12

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.

Sign up to request clarification or add additional context in comments.

16 Comments

Oh, hang on. Will this give you a null terminator?
@Konrad: +1 reinstated! The major advantage of this over @codebolt's solution is that there's no need to remember to delete.
@Konrad: I prefer strcpy when it's appropriate, as here. It's pointless to use complex C++ methods when simpler ones are available. To prove my point, your code still has a bug (actually two, but one of them is a typo).
@Nim But that’s unfortunately potentially much more inefficient.
@TonyK I don’t agree that strcpy is simpler – at all. The mistakes I made in the code are almost all caught by the compiler. The strcpy code has no such safety harness. It just quietly leaks memory or overwrites buffers. Code which has this potential is just never appropriate. There is nothing “simpler” about the new char/strcpy method, for any meaningful usage of the word “simpler”.
|
6

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()); 

9 Comments

+1: Copying is one solution (so longer as your remember to delete!).
But why use the unsafe function strcpy instead of std::copy, and why use a C-style string instead of a char array?
@Konrad: At some point, the OP will need to have a char * available for his legacy function. Are you suggesting copying into e.g. a std::vector first, and then getting &v[0]?
@Oli Exactly. See my answer. In C++, there’s just no reason not to use C++ tools when available.
@codebolt: If it is declared with new, it is guaranteed, because it would be created on the static store. I should have mention that.
|
2

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()); 

Comments

1

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!

Comments

0

Can't you just pass the string as such to your function that takes a char*:

func(&string[0]); 

8 Comments

This will probably wreak havoc if the called function modifies its argument.
This is what std::string::c_str() is for. But that doesn't avoid the non-const issue...
I thought c and c++ strings were treated differently.
@Frank Schmitt: Care to explain such an example? Assuming that the function takes a char* by value it cannot possibly modify the argument (pointer), and regardless of whether it does modify the contents of the string (as long as it does not go beyond the end of the string, which there probably is size as a second argument) this should be fine. The only grey issue here is that std::string is allowed not to be contiguous or nul terminated by the standard, but there isn't any current implementation that uses ropes, and the upcoming standard requires contiguity.
... as of the nul termination, the fact is that s[s.size()] (when using the const version of operator[]) is required to return '\0', and all implementations I know of will do the simple thing: allocate an extra element and set it to nul. This might not be the best option available, but from a practical standpoint it might just be acceptable, as applying const_cast<> to the result of .c_str() was recommended for C functions that do not modify the received char* contents...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.