Я разрабатываю крошечное приложение Win32 на C ++.
Я изучал основы C ++ очень давно, поэтому теперь я полностью сбит с толку из-за символьных строк в C ++. Не было WCHAR
или же TCHAR
только char
а также String
,
После небольшого расследования я решил не использовать TCHAR
,
Я думаю, что моя проблема очень проста, но я не могу найти четкого руководства по работе со строками в C ++. В последние несколько лет под влиянием PHP-кодирования я ожидал чего-то простого с манипуляциями со строками и ошибался!
Просто все, что мне нужно, это поместить новые данные в строку символов.
WCHAR* cs = L"\0";
swprintf( cs, "NEW DATA" );
Это была моя первая попытка. При отладке моего приложения я исследовал, что swprintf помещает только первые 2 символа в мою переменную cs. Я решил свою проблему следующим образом:
WCHAR cs[1000];
swprintf( cs, "NEW DATA" );
Но обычно этот трюк может не сработать, потому что в моем случае новые данные — это не постоянное значение, а другая переменная, которая потенциально может быть шире, чем 1000 символов. И мой код выглядит так:
WCHAR cs[1000];
WCHAR* nd1;
WCHAR* nd2;
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, "The paths are %s and %s", nd1, nd2);
В этом случае существует вероятность, что общее число символов nd1 и nd2 может быть больше 1000 символов, поэтому критические данные будут потеряны.
Вопрос в том, как мне скопировать все данные, которые мне нужны, в строку WCHAR, объявленную таким образом. WCHAR* wchar_var;
ничего не потеряв?
Постскриптум Поскольку я русский, вопрос может быть неясным. Позвольте мне рассказать об этом, и я постараюсь объяснить мою проблему более четко и сложно.
В современном программировании Windows нормально игнорировать TCHAR
и вместо этого использовать wchar_t
(WCHAR
) и Unicode UTF-16.
(TCHAR
Это модель прошлого, когда вы хотели иметь единую кодовую базу и создавать сборки ANSI / MBCS и Unicode, изменяя некоторые препроцессорные переключатели, такие как _UNICODE
а также UNICODE
.)
В любом случае, вы должны использовать C ++ и удобно классы строки упростить ваш код. Ты можешь использовать ATL::CString
(что соответствует CStringW
в сборках Unicode (по умолчанию с VS2005) или STL std::wstring
,
С помощью CString
, ты можешь сделать:
CString str1 = L"Some value";
CString str2 = L"Another value";
CString cs;
cs.Format(L"The paths are %s and %s", str1.GetString(), str2.GetString());
CString
также обеспечивает надлежащие перегрузки operator+
объединить строки (чтобы вам не приходилось вычислять общую длину полученной строки, динамически выделять буфер для строки назначения или проверять существующий размер буфера, вызывать wcscpy
, wcscat
не забудьте освободить буфер и т. д.)
И вы можете просто передать экземпляры CString
ожидающих API Win32 const wchar_t*
(LPCWSTR/PCWSTR
) параметры, так как CString
предлагает оператор неявного преобразования const wchar_t*
,
Когда вы используете WCHAR*
, вы вызываете неопределенное поведение, потому что у вас есть указатель, но вы не указали на что-либо действительное. Вам необходимо выяснить, какова будет длина полученной строки, и динамически выделить место для этой строки. Например:
WCHAR* cs;
WCHAR* nd1;
WCHAR* nd2;
nd1 = new WCHAR[lstrlen(L"Some value") + 1]; // +1 for the null terminator
nd2 = new WCHAR[lstrlen(L"Another value") + 1];
cs = new WCHAR[lstrlen(L"The paths are and ") + lstrlen(nd1) + lstrlen(nd2) + 1];
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, L"The paths are %s and %s", nd1, nd2);
delete[] nd1;
delete[] nd2;
delete[] cs;
Но это очень уродливо и подвержено ошибкам. Как уже отмечалось, вы должны использовать std::wstring
вместо этого что-то вроде этого:
std::wstring cs;
std::wstring nd1;
std::wstring nd2;
nd1 = L"Some value";
nd2 = L"Another value";
cs = std::wstring(L"The paths are ") + nd1 + L" and " + nd2;
Предложить использовать ATL CStringW
класс вместо сырья WCHAR
Гораздо удобнее. CString
является оберткой для динамически размещаемой C-строки Он будет управлять длиной строки & Распределите буфер памяти соответствующим образом после каждой операции, чтобы вам было все равно.
Типичное использование:
#include <atlstr.h>
CStringW s;
s.Format(L"The paths are %s and %s", L"Some value", L"Another value");
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
или же
#include <atlstr.h>
CStringW s(L"The paths are ");
s += L"Some value";
s += L" and ";
s += L"Another value";
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR