Есть ли способ передать std :: string в функцию, которая принимает char * и изменяет его содержимое? - PullRequest
2 голосов
/ 28 октября 2010

Я пытаюсь вернуться к программированию, особенно к консольным играм.Я слышал, что проклятия были хороши для этого, поэтому я нашел учебник проклятий, и я вхожу в это.Я использую C ++, и, естественно, я хотел воспользоваться преимуществами std :: string, но такие функции, как getstr(), принимают только char *.Есть ли способ передать строку как char *, или мне придется отказаться от использования строк C ++?

Ответы [ 6 ]

8 голосов
/ 28 октября 2010

Вы все еще можете использовать C ++ std::string, но вам придется скопировать содержимое в буфер (std::vector<char> было бы хорошо) и скопировать его обратно при использовании функций, которые ожидают доступный для записи буфер char*.

5 голосов
/ 28 октября 2010

Единственные контейнеры C ++, которые можно безопасно передавать в функции, ожидающие модифицируемые массивы в стиле C, - это std::vector (не забудьте resize() создать его или создать достаточно большой с самого начала) иboost::array (или std::array начиная с C ++ 11).

1 голос
/ 28 октября 2010

Это будет сложно, если библиотека произвольно изменяет содержимое И длину. Вы можете попробовать использовать существующую оболочку C ++ на CURSES . Или этот (вроде старого ...).

NCURSES имеет встроенные привязки C ++ . Не уверен, что вы используете, но проверьте это.

0 голосов
/ 28 октября 2010

Как уже говорили другие, вы должны обернуть функции в копию и затем обратно из буфера в стиле C. Это решение, использующее объект-оболочку с коротким сроком службы, делает это довольно элегантно:

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
}

ЭтоВывод кода:

Construct
Function
Destruct
HQQa

, который демонстрирует, как и как это работает.Это не решает проблему, связанную с указанием длины буфера, но позволяет вызываемой функции изменять длину и содержимое строки (до указанного размера буфера).

0 голосов
/ 28 октября 2010

и теперь настоящий, но незаконный ответ. Все реализации std :: string, которые я когда-либо использовал, позволят вам взломать строковые данные

char *naughty = const_cast<char*>(myStr.c_str());
naughty[3] = 'f';

это работает. Вы не сможете изменить длину, хотя. Обратите внимание, что индексирование вне строки приведет к возникновению действительно плохих вещей, но в любом случае это верно для char

0 голосов
/ 28 октября 2010

если вы хотите поместить строку в такую ​​функцию, вы, конечно, можете использовать c_str ();

getstr(string.c_str());

, кроме того, std :: string также содержит const char string :: data (), который возвращает указатель на первый символ в текущей строке (но не завершенный нулем!).

, но невозможно изменить эту строку (полученную одним из вышеуказанных способов) в этой функции.

но вы можете сделать это:

 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...