#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 ?