Jak przekonwertować std :: string na LPCSTR?


111

Jak mogę przekonwertować plik std::stringna LPCSTR? Jak mogę przekonwertować plik std::stringna LPWSTR?

Jestem całkowicie zdezorientowany z tymi LPCSTR LPSTR LPWSTRi LPCWSTR.

Czy LPWSTRi LPCWSTRto samo?

Odpowiedzi:


114

str.c_str()daje const char *, czyli LPCSTR(Long Pointer to Constant STRing) - oznacza, że ​​jest to wskaźnik do 0zakończonego ciągu znaków. Woznacza szeroki ciąg (złożony z wchar_tzamiast char).


5
Drobna wskazówka: na 64-bitowym LPCSTR byłby 64-bitowy wskaźnik do (stałego) łańcucha zakończonego znakiem null.
Joel

154

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.


32

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::stringna 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::stringinstancji i będzie ważny tylko do następnej modyfikacji lub zniszczenia ciągu.

Konwersja a std::stringna a LPWSTRjest bardziej skomplikowana. Chcących LPWSTRoznacza, że trzeba modyfikowalna bufor i trzeba także mieć pewność, że wiesz, co postać kodowaniastd::string korzysta. Jeśli std::stringzawiera 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;
}

18

Za pomocą LPWSTRmożna zmienić zawartość ciągu, w którym wskazuje. Używanie LPCWSTRyou 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();

LPWSTRjest 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
}

4

MultiByteToWideCharOdpowiedź, że Charles Bailey dał jest prawidłowa. Ponieważ LPCWSTRjest to po prostu typedef for const WCHAR*, widestrw przykładowym kodzie można go użyć wszędzie tam, gdzie LPWSTRoczekiwano a lub LPCWSTRoczekiwano.

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::wstringzamiast std::string. Jeśli chcesz pracować z TCHARtypem Windows , możesz użyć std::basic_string<TCHAR>. Konwersja z std::wstringna LPCWSTRlub z std::basic_string<TCHAR>na LPCTSTRto tylko kwestia powołania c_str. Kiedy zmieniasz znaki ANSI i UTF-16, pojawia się MultiByteToWideChar(i odwrotnie WideCharToMultiByte).


3

Konwersja jest prosta:

std :: string str; LPCSTR lpcstr = str.c_str ();


3

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.


1

Moim zdaniem najłatwiejszym sposobem konwersji a std::stringna a LPWSTRjest:

  1. Przekonwertować std::stringdo Astd::vector<wchar_t>
  2. Weź adres pierwszego wchar_tw 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::stringzawiera 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.


Dlaczego nie używać std::wstring?
Timmmm

@Timmmm: C ++ 11 zaostrzył specyfikację, ponieważ implementacje nie wykorzystywały starych reguł, dziś byłoby to w porządku.
MSalters

1
std::string myString("SomeValue");
LPSTR lpSTR = const_cast<char*>(myString.c_str());

myString jest ciągiem wejściowym, a lpSTR jest odpowiednikiem LPSTR .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.