Как заменить значение LPTSTR?

#c #windows

Вопрос:

 LPTSTR in;  // ...   std::wstring wstr(in);  boost::replace_all(wstr, "in", ",");  wcscpy(in, wstr.data());  

Есть ли какой-либо другой способ заменить значение a LPTSTR ?

В коде, LPTSTR является wchar_t*

Комментарии:

1. Вы уверены, что вам это нужно LPTSTR ? Если область применения wstr достаточно широка, вы можете wstr.c_str() .

2. Да, мне нужно продолжить с LPTSTR, мне просто нужно изменить ее значение в определенный момент.

3. An LPTSTR не обязательно совместим с std::wstring . Если вы хотите использовать широкие строки, то используйте широкие строки явно. Во всяком случае, это должно быть LPWSTR , если вы хотите придерживаться имен на базе Windows.

4. LPTSTR не выделяется в вашем коде. Если он выделен, используйте wcscpy(in, wstr.c_str()); для копирования. Предположительно, вы передаете это API. В зависимости от использования, in = wstr.data(); может быть действительным.

5. Да, мне нужно продолжить с LPTSTR, мне просто нужно изменить ее значение в определенный момент. — Держу пари, что это совсем не так. Вы можете подумать, что вам нужно это сделать.

Ответ №1:

Ан LPTSTR -это просто а wchar_t * . В этом случае вы пытаетесь заменить что-то в данных, на которые оно указывает.

Для этого вам нужно убедиться, что он указывает на изменяемые данные. В обычном случае инициализации его с помощью литерала это не сработает:

 LPCTSTR foo = "Foo"; LPTSTR mFoo = (LPTSTR)"Foo";  *foo = 'a'; // won't compile *mFoo = 'a'; // crash and burn  

Чтобы сделать его изменяемым, вы можете (для одной возможности) инициализировать его так, чтобы вместо этого указывать начало массива правильного типа:

 wchar_t buffer[256] = L"Foo";  LPTSTR foo = buffer; *foo = 'a'; // no problem  

Изменение самого строкового литерала приведет к ошибке, но при этом выделяется массив и инициализируется из строкового литерала, а затем изменяется содержимое этого массива. И изменение массива-это нормально.

Комментарии:

1. LPTSTR foo = "Foo"; не будет компилироваться. Я думаю, ты имеешь LPCTSTR в виду очень странные обозначения.

2. @BarmakShemirani: Да, мне, наверное, следует не забывать смотреть на вещи, когда имеешь дело с такими вещами.

Ответ №2:

Если и только если строка замены меньше/равна по длине строке поиска, то вы можете напрямую изменить содержимое входной строки.

Однако, если строка замены больше по длине, чем строка поиска, вам придется выделить новую строку большего размера и скопировать в нее нужные символы по мере необходимости.

Попробуйте что-нибудь вроде этого:

 LPTSTR in = ...;  ...  const int in_len = _tcslen(in); LPTSTR in_end = in   in_len;  LPCTSTR search = ...; // _T("in") const int search_len = _tcslen(search);  LPCTSTR replace = ...; // _T(",") const int replace_len = _tcslen(replace);  LPTSTR p_in = _tcsstr(in, search);  if (replace_len lt; search_len) {  if (p_in != NULL)  {  const int diff = search_len - replace_len;   do  {  memcpy(p_in, replace, replace_len * sizeof(TCHAR));  p_in  = replace_len;  LPTSTR remaining = p_in   diff;  memmove(found, remaining, (in_end - remaining) * sizeof(TCHAR));  in_end -= diff;  }  while ((p_in = _tcsstr(p_in, search)) != NULL);   *in_end = _T('');  } } else if (replace_len == search_len) {  while (p_in != NULL)  {  memcpy(p_in, replace, replace_len * sizeof(TCHAR));  p_in = _tcsstr(p_in   replace_len, search);  } } else {  int numFound = 0;  while (p_in != NULL)  {    numFound;  p_in = _tcsstr(p_in   search_len, search);  }   if (numFound gt; 0)  {  const out_len = in_len - (numFound * search_len)   (numFound * replace_len);  LPTSTR out = new TCHAR[out_len   1];  // or whatever the caller used to allocate 'in', since  // the caller will need to free the new string later...   LPTSTR p_out = out, found;   p_in = in;  while ((found = _tcsstr(p_in, search)) != NULL)  {  if (found != p_in)  {  int tmp_len = found - p_in;  memcpy(p_out, p_in, tmp_len * sizeof(TCHAR));  p_out  = tmp_len;  }   memcpy(p_out, replace, replace_len * sizeof(TCHAR));  p_out  = replace_len;   p_in = found   search_len;  }   if (p_in lt; in_end)  {  int tmp_len = in_end - p_in;  memcpy(p_out, p_in, tmp_len * sizeof(TCHAR));  p_out  = tmp_len;  }   *p_out = _T('');   delete[] in;  // or whatever the caller uses to free 'in'...   in = out;  } }  

Видите, почему работать с необработанными указателями строк в стиле C намного сложнее, чем с использованием строковых классов в стиле C ?