I'm trying to get back into programming, specifically console games. I'd heard that curses was good for that, so I found a curses tutorial and I'm getting into that. I'm using C++, and naturally I wanted to take advantage of std::string, but functions like getstr()
only accept char*. Is there any way to pass a string as a char*, or am I gonna have to forgo using C++ strings?

- 1,787
- 2
- 17
- 27
-
Can you clarify 'changes its contents' - does this change the length of the string? or just alters the bytes in the buffer without changing the length of the string? – Steve Townsend Oct 27 '10 at 20:41
-
Changes its contents as in potentially changing the length, yes. – Maulrus Oct 27 '10 at 20:42
-
1With C-style array or C++ containers or please use the functions specifying the size of the buffer (i.e getnstr not getstr), it will save you a lot of headaches along the road... – Eugen Constantin Dinca Oct 27 '10 at 20:58
-
Ohh, right, I'd heard about the benefits of `strncat` over `strcat`, but because I'm so used to C++ iostreams I'd never had to worry about it til now. Thanks for the tip! – Maulrus Oct 28 '10 at 01:21
-
Is there anything wrong with `getstr(&variable[0])` (variable being a `std::string`)? – Carcamano Dec 17 '13 at 15:36
6 Answers
You can still use C++ std::string
, but you'll have to copy the contents into a buffer (std::vector<char>
would be good) and copy it back when using functions that expect a writable char*
buffer.

- 81,374
- 13
- 159
- 204
-
-
4
-
Simple temp object wrapper to implement this in a generic way below as my alternate answer – Elemental Oct 28 '10 at 13:48
The only C++ containers that can be safely passed to functions expecting modifiable C-style arrays are std::vector
(don't forget to resize()
it or create it big enough from the start) and boost::array
(or std::array
since C++11).

- 8,994
- 2
- 34
- 51
-
1Why would you use `std::vector::reserve`? Even if you use `reserve`, you shouldn't write to the memory. (`size`/`empty` would return the wrong values, who knows what `&v[0]` would do, etc.) Really you need to construct the vector with `std::vector
v(numElements)`. – jamesdlin Oct 27 '10 at 21:24 -
@jamesdlin: I meant resize() sorry. Tnx for caching that up. – Eugen Constantin Dinca Oct 27 '10 at 21:34
This is going to be tricky to manage if the library modifies the contents AND the length arbitrarily. You could try to use an existing C++ wrapper on CURSES. Or this one (kind of old...).
NCURSES has built-in C++ bindings. Not sure what implementation you are on but check for this.

- 53,498
- 9
- 91
- 140
if you want to put string to such function, you can of course use c_str();
getstr(string.c_str());
moreover, std::string contains also const char string::data() which returns a pointer to the first character in the current string (however not null terminated!).
but it impossible to change this string (gotten in one of above ways) in this function.
but you can do this:
change_c-str(char* str, int size);
//...
string str = "foo";
char arr[str.size()+1];
strcpy(arr, str.c_str());
change_c-str(arr, str.size()); //this is valid as long as change_c-str won't put string which is longer than size

- 6,495
- 10
- 50
- 92
and now the real but illegal answer. All std::string implementations I have ever used will quite happily let you hack the string data
char *naughty = const_cast<char*>(myStr.c_str());
naughty[3] = 'f';
this works. You wont be able to change the length though. Note that indexing outside the string will make Really Bad Things happen, But then thats true with char * anyway

- 48,078
- 23
- 82
- 145
-
-
There used to be some std::string implementations that had a small (16-64) byte fixed buffer and allocated heap memory only if the string exceeded that size. The internal string buffer was not sequential unless c_str() was called. – Zan Lynx Oct 27 '10 at 21:19
-
@eugene - i guarantee that it leads to undefined behavior. Just that it works in VS and GCC – pm100 Oct 27 '10 at 21:27
-
the only guarantee you have is that it **may** result in undefined behavior: for the first line if myStr itself was const and for the second it's pretty much implementation (of the C++ standard library, which compiler doesn't really matter) specific... – Eugen Constantin Dinca Oct 28 '10 at 04:12
As others have said you have to wrap the functions in a copy to and then back from a C-style buffer.This solution using a short life wrapper object does this pretty elegantly:
using namespace std;
class Wrap {
public:
Wrap(string &S,int Length):Buffer(Length),Orig(S)
{ //constructor copies the string to the buffer
copy(Orig.begin(),Orig.end(),&Buffer[0]);
cout<<"Construct\n";
}
~Wrap()
{ //destructor copies the buffer contents back to the string
Orig=&Buffer[0];
cout<<"Destruct\n";
}
operator char*() { return &Buffer[0]; }
vector<char> Buffer;
string &Orig;
};
void Func(char *T) //a typical C-Style function that modifies the string
{
cout<<"Function\n";
*(T+1)='Q';
*(T+2)='Q';
}
int main()
{
string X("Hiya");
Func(Wrap(X,20)); //Call the function with a wrapped string
cout<<X; //output the modified string
}
This code outputs:
Construct
Function
Destruct
HQQa
which demonstrates how and that it works. This doesn't solve the problem that you have to specify the buffer length but it does allow the function called to change the length AND contents of the string (up to the specified buffer size).

- 7,365
- 2
- 28
- 33