Odpowiedzi:
str.c_str()
daje const char *
, czyli LPCSTR
(Long Pointer to Constant STRing) - oznacza, że jest to wskaźnik do 0
zakończonego ciągu znaków. W
oznacza szeroki ciąg (złożony z wchar_t
zamiast char
).
Zadzwoń, c_str()
aby uzyskać const char *
( LPCSTR
) z std::string
.
Wszystko w nazwie:
LPSTR
- (długi) wskaźnik do łańcucha - char *
LPCSTR
- (długi) wskaźnik do stałego ciągu - const char *
LPWSTR
- (długi) wskaźnik do łańcucha Unicode (szeroki) - wchar_t *
LPCWSTR
- (długi) wskaźnik do stałego (szerokiego) łańcucha Unicode - const wchar_t *
LPTSTR
- (długi) wskaźnik do TCHAR (Unicode, jeśli zdefiniowano UNICODE, ANSI, jeśli nie) string - TCHAR *
LPCTSTR
- (długi) wskaźnik do stałego ciągu TCHAR - const TCHAR *
Możesz zignorować L (długą) część nazw - jest to pozostałość po 16-bitowym systemie Windows.
Są to zdefiniowane przez Microsoft czcionki, które odpowiadają:
LPCSTR: wskaźnik do zakończonego znakiem null łańcucha const char
LPSTR: wskaźnik do łańcucha znaków zakończonego znakiem null char
(często jest przekazywany bufor i używany jako parametr wyjściowy '')
LPCWSTR: wskaźnik do zakończonego znakiem null łańcucha stałej wchar_t
LPWSTR: wskaźnik do łańcucha zakończonego znakiem null wchar_t
(często bufor jest przekazywany i używany jako parametr `` wyjściowy '')
Konwersja a std::string
na LPCSTR zależy od dokładnego kontekstu, ale zwykle wywołanie .c_str()
jest wystarczające.
To działa.
void TakesString(LPCSTR param);
void f(const std::string& param)
{
TakesString(param.c_str());
}
Pamiętaj, że nie powinieneś próbować robić czegoś takiego.
LPCSTR GetString()
{
std::string tmp("temporary");
return tmp.c_str();
}
Bufor zwrócony przez .c_str()
jest własnością std::string
instancji i będzie ważny tylko do następnej modyfikacji lub zniszczenia ciągu.
Konwersja a std::string
na a LPWSTR
jest bardziej skomplikowana. Chcących LPWSTR
oznacza, że trzeba modyfikowalna bufor i trzeba także mieć pewność, że wiesz, co postać kodowaniastd::string
korzysta. Jeśli std::string
zawiera ciąg znaków przy użyciu domyślnego kodowania systemu (zakładając, że okna są tutaj), wówczas można znaleźć długość wymaganego bufora szerokich znaków i przeprowadzić transkodowanie za pomocą MultiByteToWideChar
(funkcji Win32 API).
na przykład
void f(const std:string& instr)
{
// Assumes std::string is encoded in the current Windows ANSI codepage
int bufferlen = ::MultiByteToWideChar(CP_ACP, 0, instr.c_str(), instr.size(), NULL, 0);
if (bufferlen == 0)
{
// Something went wrong. Perhaps, check GetLastError() and log.
return;
}
// Allocate new LPWSTR - must deallocate it later
LPWSTR widestr = new WCHAR[bufferlen + 1];
::MultiByteToWideChar(CP_ACP, 0, instr.c_str(), instr.size(), widestr, bufferlen);
// Ensure wide string is null terminated
widestr[bufferlen] = 0;
// Do something with widestr
delete[] widestr;
}
Za pomocą LPWSTR
można zmienić zawartość ciągu, w którym wskazuje. Używanie LPCWSTR
you nie mogło zmienić zawartości łańcucha, w którym wskazuje.
std::string s = SOME_STRING;
// get temporary LPSTR (not really safe)
LPSTR pst = &s[0];
// get temporary LPCSTR (pretty safe)
LPCSTR pcstr = s.c_str();
// convert to std::wstring
std::wstring ws;
ws.assign( s.begin(), s.end() );
// get temporary LPWSTR (not really safe)
LPWSTR pwst = &ws[0];
// get temporary LPCWSTR (pretty safe)
LPCWSTR pcwstr = ws.c_str();
LPWSTR
jest tylko wskaźnikiem do oryginalnego ciągu. Nie powinieneś zwracać go z funkcji przy użyciu powyższego przykładu. Aby nie był tymczasowy LPWSTR
, powinieneś zrobić kopię oryginalnego ciągu na stercie. Sprawdź próbkę poniżej:
LPWSTR ConvertToLPWSTR( const std::string& s )
{
LPWSTR ws = new wchar_t[s.size()+1]; // +1 for zero at the end
copy( s.begin(), s.end(), ws );
ws[s.size()] = 0; // zero at the end
return ws;
}
void f()
{
std::string s = SOME_STRING;
LPWSTR ws = ConvertToLPWSTR( s );
// some actions
delete[] ws; // caller responsible for deletion
}
MultiByteToWideChar
Odpowiedź, że Charles Bailey dał jest prawidłowa. Ponieważ LPCWSTR
jest to po prostu typedef for const WCHAR*
, widestr
w przykładowym kodzie można go użyć wszędzie tam, gdzie LPWSTR
oczekiwano a lub LPCWSTR
oczekiwano.
Jedną drobną poprawką byłoby użycie std::vector<WCHAR>
zamiast ręcznie zarządzanej tablicy:
// using vector, buffer is deallocated when function ends
std::vector<WCHAR> widestr(bufferlen + 1);
::MultiByteToWideChar(CP_ACP, 0, instr.c_str(), instr.size(), &widestr[0], bufferlen);
// Ensure wide string is null terminated
widestr[bufferlen] = 0;
// no need to delete; handled by vector
Ponadto, jeśli na początku musisz pracować z szerokimi łańcuchami, możesz użyć std::wstring
zamiast std::string
. Jeśli chcesz pracować z TCHAR
typem Windows , możesz użyć std::basic_string<TCHAR>
. Konwersja z std::wstring
na LPCWSTR
lub z std::basic_string<TCHAR>
na LPCTSTR
to tylko kwestia powołania c_str
. Kiedy zmieniasz znaki ANSI i UTF-16, pojawia się MultiByteToWideChar
(i odwrotnie WideCharToMultiByte
).
Konwersja jest prosta:
std::string myString;
LPCSTR lpMyString = myString.c_str();
Jedną rzeczą, na którą należy uważać, jest to, że c_str nie zwraca kopii myString, ale tylko wskaźnik do ciągu znaków, który zawija std :: string. Jeśli chcesz / potrzebujesz kopii, musisz zrobić ją samodzielnie za pomocą strcpy.
Moim zdaniem najłatwiejszym sposobem konwersji a std::string
na a LPWSTR
jest:
std::string
do Astd::vector<wchar_t>
wchar_t
w wektorze.std::vector<wchar_t>
ma obiekt sterujący na podstawie szablonu, który będzie wymagał dwóch iteratorów, takich jak iteratory std::string.begin()
i .end()
. Spowoduje to jednak konwersję każdego znaku na znak wchar_t
. Jest to ważne tylko wtedy, gdy std::string
zawiera ASCII lub Latin-1, ze względu na sposób, w jaki wartości Unicode przypominają wartości Latin-1. Jeśli zawiera CP1252 lub znaki z innego kodowania, jest to bardziej skomplikowane. Będziesz wtedy musiał przekonwertować znaki.
std::wstring
?