Comment convertir std :: string en LPCSTR?

111

Comment puis-je convertir un std::stringen LPCSTR? Aussi, comment puis-je convertir un std::stringen LPWSTR?

Je suis totalement confus avec ceux LPCSTR LPSTR LPWSTR- ci et LPCWSTR.

Sont LPWSTRet LPCWSTRles mêmes?

Mignonne
la source

Réponses:

114

str.c_str()vous donne un const char *, qui est un LPCSTR(Long Pointer to Constant STRing) - signifie qu'il s'agit d'un pointeur vers une 0chaîne de caractères terminée. Wsignifie chaîne large (composée de wchar_tau lieu de char).

Lou Franco
la source
5
Point difficile mineur: sur x64 LPCSTR serait un pointeur 64 bits vers une chaîne (constante) terminée par un zéro.
Joel
154

Appelez c_str()pour obtenir un const char *( LPCSTR) d'un std::string.

Tout est dans le nom:

LPSTR - (long) pointeur vers la chaîne - char *

LPCSTR - (long) pointeur vers une chaîne constante - const char *

LPWSTR - (long) pointeur vers la chaîne Unicode (large) - wchar_t *

LPCWSTR - (long) pointeur vers une chaîne Unicode (large) constante - const wchar_t *

LPTSTR - (long) pointeur vers TCHAR (Unicode si UNICODE est défini, ANSI sinon) chaîne - TCHAR *

LPCTSTR - (long) pointeur vers la chaîne TCHAR constante - const TCHAR *

Vous pouvez ignorer la partie L (longue) des noms - c'est un héritage de Windows 16 bits.

Nick Meyer
la source
32

Ce sont des typedefs définis par Microsoft qui correspondent à:

LPCSTR: pointeur vers la chaîne const terminée par null de char

LPSTR: pointeur vers la chaîne de caractères terminée par null de char(souvent un tampon est passé et utilisé comme paramètre de 'sortie')

LPCWSTR: pointeur vers la chaîne terminée par null de const wchar_t

LPWSTR: pointeur vers la chaîne terminée par null de wchar_t(souvent un tampon est passé et utilisé comme paramètre de 'sortie')

La "conversion" std::stringde a en LPCSTR dépend du contexte exact, mais il .c_str()suffit généralement d'appeler .

Cela marche.

void TakesString(LPCSTR param);

void f(const std::string& param)
{
    TakesString(param.c_str());
}

Notez que vous ne devriez pas essayer de faire quelque chose comme ça.

LPCSTR GetString()
{
    std::string tmp("temporary");
    return tmp.c_str();
}

Le tampon renvoyé par .c_str()appartient à l' std::stringinstance et ne sera valide que jusqu'à ce que la chaîne soit modifiée ou détruite.

Convertir a std::stringen a LPWSTRest plus compliqué. Vouloir une LPWSTRimplique que vous avez besoin d' un tampon modifiable et vous devez également être sûr que vous comprenez ce que l' encodage des caractères l' std::stringutilise. Si le std::stringcontient une chaîne utilisant le codage par défaut du système (en supposant que Windows, ici), vous pouvez trouver la longueur du tampon de caractères larges requis et effectuer le transcodage en utilisant MultiByteToWideChar(une fonction API Win32).

par exemple

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;
}
CB Bailey
la source
18

En utilisant, LPWSTRvous pouvez modifier le contenu de la chaîne vers laquelle elle pointe. En utilisant, LPCWSTRvous ne pouvez pas modifier le contenu de la chaîne vers laquelle elle pointe.

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();

LPWSTRest juste un pointeur vers la chaîne d'origine. Vous ne devez pas le renvoyer à partir de la fonction en utilisant l'exemple ci-dessus. Pour ne pas être temporaire, LPWSTRvous devez faire une copie de la chaîne d'origine sur le tas. Vérifiez l'exemple ci-dessous:

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
}
Kirill V. Lyadvinsky
la source
4

La MultiByteToWideCharréponse que Charles Bailey a donnée est la bonne. Comme il LPCWSTRs'agit simplement d'un typedef pour const WCHAR*, widestrdans l'exemple de code, il peut être utilisé partout où a LPWSTRest attendu ou où a LPCWSTRest attendu.

Un ajustement mineur serait d'utiliser std::vector<WCHAR>au lieu d'un tableau géré manuellement:

// 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

De plus, si vous avez besoin de travailler avec des chaînes larges pour commencer, vous pouvez utiliser à la std::wstringplace de std::string. Si vous souhaitez travailler avec le TCHARtype Windows , vous pouvez utiliser std::basic_string<TCHAR>. La conversion de std::wstringvers LPCWSTRou de std::basic_string<TCHAR>vers LPCTSTRest juste une question d'appels c_str. C'est lorsque vous changez entre les caractères ANSI et UTF-16 qui MultiByteToWideChar(et son inverse WideCharToMultiByte) entre en jeu.

Joël
la source
3

La conversion est simple:

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

Timbo
la source
3

La conversion est simple:

std::string myString;

LPCSTR lpMyString = myString.c_str();

Une chose à faire attention ici est que c_str ne renvoie pas une copie de myString, mais juste un pointeur vers la chaîne de caractères que std :: string encapsule. Si vous voulez / avez besoin d'une copie, vous devrez en créer une vous-même en utilisant strcpy.

Nick Haddad
la source
1

Le moyen le plus simple de convertir un std::stringen un LPWSTRest à mon avis:

  1. Convertissez le std::stringenstd::vector<wchar_t>
  2. Prenez l'adresse du premier wchar_tdans le vecteur.

std::vector<wchar_t>a un ctor basé sur un modèle qui prendra deux itérateurs, tels que les itérateurs std::string.begin()et .end(). Cela convertira chaque caractère en a wchar_t, cependant. Ce n'est valable que si le std::stringcontient ASCII ou Latin-1, en raison de la façon dont les valeurs Unicode ressemblent aux valeurs Latin-1. S'il contient du CP1252 ou des caractères d'un autre encodage, c'est plus compliqué. Vous devrez ensuite convertir les personnages.

MSalters
la source
Pourquoi ne pas l'utiliser std::wstring?
Timmmm
@Timmmm: C ++ 11 a resserré la spécification car les implémentations ne tiraient pas parti des anciennes règles, aujourd'hui ce serait OK.
MSalters
1
std::string myString("SomeValue");
LPSTR lpSTR = const_cast<char*>(myString.c_str());

myString est la chaîne d'entrée et lpSTR est son équivalent LPSTR .

Nani
la source