views:

150

answers:

6

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?

+7  A: 

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.

jamesdlin
`vector<char>` can be substituted for a `char*`?
Maulrus
@Maulrus, yes - `vector<char> buffer(size); func(`
Mark Ransom
Simple temp object wrapper to implement this in a generic way below as my alternate answer
Elemental
+4  A: 

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.

Eugen Constantin Dinca
jamesdlin
@jamesdlin: I meant resize() sorry. Tnx for caching that up.
Eugen Constantin Dinca
+1  A: 

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.

Steve Townsend
A: 

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
noisy
You might want to rethink the name of that function.
Ben Voigt
A: 

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

pm100
That may lead to undefined behavior.
Eugen Constantin Dinca
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
@eugene - i guarantee that it leads to undefined behavior. Just that it works in VS and GCC
pm100
@pm100: 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
A: 

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).

Elemental