¿Cómo convertir std :: string a LPCSTR?

111

¿Cómo puedo convertir un std::stringa LPCSTR? Además, ¿cómo puedo convertir un std::stringa LPWSTR?

Estoy totalmente confundido con estos LPCSTR LPSTR LPWSTRy LPCWSTR.

Son LPWSTRy LPCWSTRlo mismo?

Lindo
fuente

Respuestas:

114

str.c_str()le da a const char *, que es un LPCSTR(Long Pointer to Constant STRing) - significa que es un puntero a una 0cadena de caracteres terminada. Wsignifica cadena ancha (compuesta de en wchar_tlugar de char).

Lou Franco
fuente
5
Punto delicado menor: en x64 LPCSTR sería un puntero de 64 bits a una cadena (constante) terminada en nulo.
Joel
154

Llame c_str()para obtener un const char *( LPCSTR) de un std::string.

Todo está en el nombre:

LPSTR - (largo) puntero a cadena - char *

LPCSTR - puntero (largo) a cadena constante - const char *

LPWSTR - puntero (largo) a la cadena Unicode (ancho) - wchar_t *

LPCWSTR - puntero (largo) a una cadena Unicode (ancha) constante - const wchar_t *

LPTSTR - puntero (largo) a TCHAR (Unicode si se define UNICODE, ANSI si no) cadena - TCHAR *

LPCTSTR - puntero (largo) a una cadena TCHAR constante - const TCHAR *

Puede ignorar la parte L (larga) de los nombres; es un vestigio de Windows de 16 bits.

Nick Meyer
fuente
32

Estos son typedefs definidos por Microsoft que corresponden a:

LPCSTR: puntero a una cadena constante terminada en nulo de char

LPSTR: puntero a una cadena de caracteres terminada en nulo de char(a menudo se pasa un búfer y se usa como un parámetro de 'salida')

LPCWSTR: puntero a una cadena de const terminada en nulo wchar_t

LPWSTR: puntero a una cadena terminada en nulo de wchar_t(a menudo se pasa un búfer y se usa como un parámetro de 'salida')

Para "convertir" std::stringa en LPCSTR depende del contexto exacto, pero normalmente llamar .c_str()es suficiente.

Esto funciona.

void TakesString(LPCSTR param);

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

Tenga en cuenta que no debe intentar hacer algo como esto.

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

El búfer devuelto por .c_str()es propiedad de la std::stringinstancia y solo será válido hasta que la cadena se modifique o destruya a continuación.

Convertir a en std::stringa LPWSTRes más complicado. Queriendo un LPWSTRimplica que se necesita un búfer modificable y también es necesario para asegurarse de que entiende lo que la codificación de caracteres de la std::stringestá utilizando. Si std::stringcontiene una cadena que usa la codificación predeterminada del sistema (asumiendo windows, aquí), entonces puede encontrar la longitud del búfer de caracteres anchos requerido y realizar la transcodificación usando MultiByteToWideChar(una función de API de Win32).

p.ej

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
fuente
18

Al LPWSTRusarlo, podría cambiar el contenido de la cadena a donde apunta. El uso LPCWSTRno pudo cambiar el contenido de la cadena a donde apunta.

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

LPWSTRes solo un puntero a la cadena original. No debe devolverlo desde la función usando el ejemplo anterior. Para que no sea temporal LPWSTR, debe hacer una copia de la cadena original en el montón. Verifique la muestra a continuación:

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
fuente
4

La MultiByteToWideCharrespuesta que dio Charles Bailey es la correcta. Debido a que LPCWSTRes solo un typedef para const WCHAR*, widestren el código de ejemplo se puede usar donde LPWSTRse espere a o donde LPCWSTRse espere a.

Un pequeño ajuste sería usar en std::vector<WCHAR>lugar de una matriz administrada manualmente:

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

Además, si necesita trabajar con cadenas anchas para empezar, puede usar en std::wstringlugar de std::string. Si desea trabajar con el TCHARtipo de Windows , puede usar std::basic_string<TCHAR>. La conversión de std::wstringa LPCWSTRo de std::basic_string<TCHAR>a LPCTSTRes solo una cuestión de llamada c_str. Es cuando estás cambiando entre caracteres ANSI y UTF-16 que MultiByteToWideChar(y su inverso WideCharToMultiByte) entra en escena.

Joel
fuente
3

La conversión es simple:

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

Timbo
fuente
3

La conversión es simple:

std::string myString;

LPCSTR lpMyString = myString.c_str();

Una cosa a tener en cuenta aquí es que c_str no devuelve una copia de myString, sino solo un puntero a la cadena de caracteres que std :: string envuelve. Si desea / necesita una copia, deberá hacer una usted mismo usando strcpy.

Nick Haddad
fuente
1

En mi opinión, la forma más sencilla de convertir std::stringa en a LPWSTRes:

  1. Convierta el std::stringastd::vector<wchar_t>
  2. Toma la dirección del primero wchar_ten el vector.

std::vector<wchar_t>tiene un ctor con plantilla que tomará dos iteradores, como los iteradores std::string.begin()y .end(). Sin wchar_tembargo, esto convertirá cada carácter en un . Eso solo es válido si std::stringcontiene ASCII o Latin-1, debido a la forma en que los valores Unicode se parecen a los valores Latin-1. Si contiene CP1252 o caracteres de cualquier otra codificación, es más complicado. Luego, deberá convertir los caracteres.

MSalters
fuente
¿Por qué no usar std::wstring?
Timmmm
@Timmmm: C ++ 11 ajustó la especificación ya que las implementaciones no aprovecharon las reglas anteriores, hoy estaría bien.
MSalters
1
std::string myString("SomeValue");
LPSTR lpSTR = const_cast<char*>(myString.c_str());

myString es la cadena de entrada y lpSTR es su equivalente a LPSTR .

Nani
fuente