5

I'm using the pdCurses library and am aiming to only really use strings in my C++ console game but the curses mvinstr() function or any insert function requires a non-const char * as a parameter.

  • My solution at first to this problem was simply entering in string.c_str(), but that returns a const char * which apparently doesn't work with the function.
  • Next I put (char *)string.c_str() but this only causes an unhandled exception.
  • Finally I just tried char *test = string.c_str() but that's not compatible with const either.

What do I do to solve this?

K i just tried const_cast() and i still get an exception thrown and break.... I don't know why PDcurses only takes non-const char pointers.... =(

alright making a char* buffer didn't work when i used this code (time_s is the sting):

size_t length; char buffer[12]; length=time_s.copy(buffer,5,0); buffer[length]='\0'; mvinstr(time_loc_y, time_loc_x, buffer); 

i even put a stop before mvinstr() and checked the buffer's contents which was "00 /0" EXACTLY WHAT I WANTED.

but i get an access violation point to "xutility"....

3
  • Take into account that usually its not recommended to remove constness, this has something to do with design flaws. Commented May 16, 2011 at 23:33
  • Violation accessing what code and where? Commented May 17, 2011 at 0:26
  • Did you ever get this figured out? Commented May 17, 2011 at 3:53

7 Answers 7

7

mvinstr(x,y,str) and others "take characters (or wide characters) from the current or specified position in the window, and return them as a string in str (or wstr)."

The function will actually modify the string, so you cannot safely cast the const away, especially since c_str specifies that you should not modify the returned string.

You need something along the lines of:

const MAX = 100; char buf[MAX]; mvinnstr(x, y, buf, MAX); ...error checking... string s = buf; 

Note that I avoided mvinstr in favour of mvinnstr to avoid the potential for buffer overflows.

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

1 Comment

@Griffin, sounds like a buffer overflow, and I specifically showed how you can avoid that. Note: It's not clear whether you should pass MAX or MAX-1 to mvinnstr, but that can be determined from testing.
3

How about

char* buffer = &str[0]; int fetched_len = mvinnstr(time_loc_y, time_loc_x, buffer, str.size()); str.resize(fetched_len); 

In general, though, you should make a writable buffer instead of removing const from a pointer that has it. e.g.

vector<char> charvec(MAX_LENGTH); str = string(&charvec[0], mvinnstr(time_loc_y, time_loc_x, &charvec[0], charvec.size()); 

10 Comments

C++03 tried to guarantee your first snippet would work (and failed), but it is guaranteed to work in C++0x. In both cases, make sure there's enough reserved memory in the string.
@GMan: I was trying to avoid looking up the particular API, in order to provide a more general answer, but I've just edited it to prevent overflow.
Hmm... just realized this is similar to my answer but with the added resize call ... might you want to show what you're doing with the &str[0] call more explicitly so that the OP doesn't get lost. +1.
@Billy: That's what I had in an earlier revision, ... I'll see what I can do to emphasize that.
|
2

Cautiously - if the code that uses the was-const data tries to modify it, anything can happen.

In short:

const std::string str = "..."; char *caution = const_cast<char *>(str.c_str()); 

However, given that you are getting unhandled exceptions, you probably need to make a modifiable copy of the constant string before calling mvinstr(). Maybe:

const std::string str = "..."; char *caution = new char[str.length()+1]; str.copy(caution, str.length()+1); ...call to mvinstr()... delete[] caution; 

6 Comments

That's not a std::string, content of std::string is mutable.
Does const_cast<char > act differently than '(char)'aConst_char_pointer?
@Griffin: Use backticks to protect code snippets against interpretation of asterisk as formatting codes.
@Griffin: Yes. C style casts cannot remove const -- only const_cast can do that. (You should be using C++ style casts anyway)
@Billy: You might double-check that, as I'm quite sure that a C-style cast indeed can remove cv-qualfiers.
|
1

Since mvinstr is actually storing data into the array pointed at by the char*, you can't use a string there. You need to allocate an array of char, pass that to mvinstr, and then transfer the characters to a string if you want.

If you were using a function that could have been declared with a const char * (i.e. it doesn't actually modify the array), then you could use const_cast<> to remove the const.

const_cast<char *>(str.c_str()); 

But that's not what you're doing here. const_cast might work if you tried it, but it would be by accident, not because it's supposed to work, and a new compiler or library version could break it at any time.

2 Comments

@Ben: No, I mean an array. We're interfacing with C code here.
Yes, and a vector easily gives you a pointer which C code understands, and also frees the memory automatically.
1

Try something like the following, then use buffer wherever you need a char*. As Ben mentioned, you need to be very careful to keep the buffer larger than the string plus null terminator.

const int BUFFER_SIZE = 255; string str ("Your string"); char buffer[BUFFER_SIZE]; if (str.length() < BUFFER_SIZE) { size_t copy_length; copy_length=str.copy(buffer,str.length(),0); buffer[copy_length]='\0'; } 

2 Comments

This is just asking to become an accidental buffer overflow.
Try using mvinnstr(time_loc_y, time_loc_x, buffer, size);, where size is no larger than the size of your buffer - 1. Your 12-character buffer is probably too small.
0

Removing const can be done with const_cast, and is sometimes necessary for using legacy interfaces that were written in C and don't use const. In such cases, you can do:

char* ptr = const_cast<char*> (str.c_str()); 

However, from the cplusplus reference page on c_str():

The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only granted to remain unchanged until the next call to a non-constant member function of the string object.

This means that it is your responsibility to ensure that ptr is not used to modify the string, and you must handle the lifetime of ptr appropriately. I.e., you cannot continue to use ptr after str is out of scope, or after you call any non-const methods on str. If you do that, you go into Undefined Behavior, and will likely crash.

If you are looking for a safe way to interact with a legacy interface that takes char*, you can make your own writable copy:

char* ptr = new char[ str.size() + 1 ]; strcpy(ptr, str.c_str()); ptr[str.size()] = '\0'; // ... use ptr as much as you want... delete [] ptr; 

4 Comments

new [] and delete []? Just use std::vector.
@Ben, how is a vector<char> supposed to help with using a legacy interface that expects char* as an input parameter? A boost::scoped_array would work far better here.
vector<char> vec = FillMeWithData(); legacy_c_function(&vec[0]); Not so say boost::scoped_array isn't also an option. So long as there's no raw pointers floating around.
@Dennis: Although, the data comes from the legacy c function. So vector<char> vec(str.size() + 1); legacy_c_function(&vec[0]);
-1

if (string.empty()) foo(const_cast<char*>(string.c_str());

a better but still evil way to remove const is const_cast(const_string); (its better to find via grep/search)

Witch exception did you encountered? Do u just read the char* or do you change the values? if you change, you should redesign your code.

const char* test = string.c_str(); Does not create a deep copy of string, only a pointer to the internal data representation of string.data().

=> (a suggestion) find a C++ book where you can get a more in deep view of c++. Or something like to C++.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.