Как преобразовать std :: string в LPCSTR?

111

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

Я совершенно запутался в этих LPCSTR LPSTR LPWSTRи LPCWSTR.

Есть LPWSTRи LPCWSTRто же?

Милый
источник

Ответы:

114

str.c_str()дает вам const char *, что является LPCSTR(Длинный указатель на постоянную строку) - означает, что это указатель на 0завершенную строку символов. Wозначает широкую строку (составленную из wchar_tвместо char).

Лу Франко
источник
5
Незначительный придирчивый момент: на x64 LPCSTR будет 64-битным указателем на (константу) строку с завершающим нулем.
Joel
154

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

Все дело в названии:

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

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

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

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

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

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

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

Ник Мейер
источник
32

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

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

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

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

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

«Преобразование» a 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экземпляру и будет действителен только до следующего изменения или уничтожения строки.

Преобразовать a std::stringв a LPWSTRсложнее. Хотеть LPWSTRозначает , что вам нужно изменяемый буфер , и вы также должны быть уверены , что вы понимаете , что кодировка символовstd::string используется. Если std::stringсодержит строку с использованием системной кодировки по умолчанию (здесь предполагается Windows), то вы можете найти длину требуемого буфера широких символов и выполнить перекодирование с помощью 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;
}
CB Bailey
источник
18

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

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это просто указатель на исходную строку. Вы не должны возвращать его из функции, используя пример выше. Чтобы не получить временное, 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

MultiByteToWideCharОтвет , что Чарльз Бейли дал правильный один. Поскольку LPCWSTRэто просто typedef для 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. Если вы хотите работать с TCHARтипом Windows , вы можете использовать std::basic_string<TCHAR>. Преобразование из std::wstringв LPCWSTRили из std::basic_string<TCHAR>в LPCTSTR- это просто вопрос звонка c_str. Когда вы переключаетесь между символами ANSI и UTF-16, это MultiByteToWideChar(и его обратное WideCharToMultiByte) появляется на картинке.

Joel
источник
3

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

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

Timbo
источник
3

Конвертировать просто:

std::string myString;

LPCSTR lpMyString = myString.c_str();

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

Ник Хаддад
источник
1

На мой взгляд, самый простой способ преобразовать a std::stringв a 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 или символы из любой другой кодировки, все сложнее. Затем вам нужно будет преобразовать символы.

MSalters
источник
Почему бы не использовать std::wstring?
Timmmm
@Timmmm: C ++ 11 ужесточил спецификацию, поскольку реализации не использовали старые правила, сегодня это было бы нормально.
MSalters
1
std::string myString("SomeValue");
LPSTR lpSTR = const_cast<char*>(myString.c_str());

myString - это входная строка, а lpSTR - это эквивалент LPSTR .

Нани
источник