Как конвертировать std :: string в LPCSTR? - PullRequest
105 голосов
/ 29 июля 2009

Как я могу преобразовать std::string в LPCSTR? Кроме того, как я могу преобразовать std::string в LPWSTR?

Я полностью запутался с этими LPCSTR LPSTR LPWSTR и LPCWSTR.

LPWSTR и LPCWSTR одинаковы?

Ответы [ 8 ]

145 голосов
/ 29 июля 2009

Позвоните c_str(), чтобы получить const char * (LPCSTR) от std::string.

Это все во имя:

LPSTR - (длинный) указатель на строку - char *

LPCSTR - (длинный) указатель на постоянную строку - const char *

LPWSTR - (длинный) указатель на строку в Юникоде (широкая) - wchar_t *

LPCWSTR - (длинный) указатель на постоянную строку Unicode (широкий) - const wchar_t *

LPTSTR - (длинный) указатель на строку TCHAR (Unicode, если определен UNICODE, ANSI, если нет) - TCHAR *

LPCTSTR - (длинный) указатель на постоянную строку TCHAR - const TCHAR *

Вы можете игнорировать L (длинную) часть имен - это удержание от 16-битной Windows.

107 голосов
/ 29 июля 2009

str.c_str() дает вам const char *, то есть LPCSTR (Long Pointer to Constant STRing) - означает, что это указатель на завершенную строку символов 0. W означает широкую строку (составленную из wchar_t вместо char).

32 голосов
/ 29 июля 2009

Это определенные Microsoft определения типов, которые соответствуют:

LPCSTR: указатель на константную строку с нулевым символом в конце char

LPSTR: указатель на символьную строку с нулевым символом в конце char (часто буфер передается и используется в качестве параметра вывода)

LPCWSTR: указатель на завершенную нулем строку const wchar_t

LPWSTR: указатель на строку с нулевым символом в конце wchar_t (часто буфер передается и используется в качестве выходного параметра)

Чтобы "преобразовать" std::string в LPCSTR, зависит от точного контекста, но обычно достаточно вызова .c_str().

Это работает.

void TakesString(LPCSTR param);

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

Обратите внимание, что вы не должны пытаться делать что-то подобное.

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

Буфер, возвращаемый .c_str(), принадлежит экземпляру std::string и будет действителен только до следующего изменения или уничтожения строки.

Преобразовать std::string в LPWSTR сложнее. Желание LPWSTR подразумевает, что вам нужен модифицируемый буфер, и вы также должны быть уверены, что понимаете, какую кодировку символов использует std::string. Если std::string содержит строку, использующую системную кодировку по умолчанию (здесь предполагается, что окна), тогда вы можете найти длину требуемого буфера широких символов и выполнить транскодирование, используя MultiByteToWideChar (функция Win32 API).

* * Например, одна тысяча тридцать восемь
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;
}
17 голосов
/ 29 июля 2009

Используя LPWSTR, вы можете изменить содержимое строки, на которое оно указывает. Используя LPCWSTR, вы не можете изменить содержимое строки там, где оно указывает.

std::string s = SOME_STRING;
// get <i>temporary</i> LPSTR (not really safe)
LPSTR pst = &s[0];
// get <i>temporary</i> LPCSTR (pretty safe)
LPCSTR pcstr = s.c_str();
// convert to std::wstring
std::wstring ws; 
ws.assign( s.begin(), s.end() );
// get <i>temporary</i> LPWSTR (not really safe)
LPWSTR pwst = &ws[0];
// get <i>temporary</i> LPCWSTR (pretty safe)
LPCWSTR pcwstr = ws.c_str();

LPWSTR это просто указатель на исходную строку. Вы не должны возвращать его из функции, используя пример выше. Чтобы получить не временный LPWSTR, вы должны сделать копию оригинальной строки в куче. Проверьте образец ниже:

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 голосов
/ 29 июля 2009

Ответ MultiByteToWideChar, который дал Чарльз Бэйли, правильный. Поскольку LPCWSTR - это просто определение типа для const WCHAR*, widestr в примере кода можно использовать везде, где ожидается LPWSTR или где LPCWSTR.

Один незначительный трюк будет использовать std::vector<WCHAR> вместо массива, управляемого вручную:

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

Также, если для начала вам нужно работать с широкими строками, вы можете использовать std::wstring вместо std::string. Если вы хотите работать с типом Windows TCHAR, вы можете использовать std::basic_string<TCHAR>. Преобразование из std::wstring в LPCWSTR или из std::basic_string<TCHAR> в LPCTSTR - это всего лишь вызов c_str. Когда вы переключаетесь между символами ANSI и UTF-16, MultiByteToWideChar (и его обратное WideCharToMultiByte) входит в картинку.

2 голосов
/ 29 июля 2009

Преобразование просто:

std::string myString;

LPCSTR lpMyString = myString.c_str();

Здесь следует быть осторожным: c_str не возвращает копию myString, а просто указывает на строку символов, которую переносит std :: string. Если вы хотите / нуждаетесь в копии, вам нужно сделать ее самостоятельно, используя strcpy.

1 голос
/ 29 июля 2009

Самый простой способ конвертировать std::string в LPWSTR, на мой взгляд:

  1. Преобразование std::string в std::vector<wchar_t>
  2. Взять адрес первого wchar_t в векторе.

std::vector<wchar_t> имеет шаблонный ctor, который будет принимать два итератора, например, итераторы std::string.begin() и .end(). Это преобразует каждый символ в wchar_t. Это верно только в том случае, если std::string содержит ASCII или Latin-1, из-за того, что значения Unicode похожи на значения Latin-1. Если он содержит CP1252 или символы из любой другой кодировки, это более сложно. Затем вам нужно будет преобразовать символы.

1 голос
/ 29 июля 2009

Преобразование простое:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...