Як перетворити std :: string в LPCSTR?


111

Як я можу перетворити std::stringв LPCSTR? Крім того , як я можу перетворити std::stringв LPWSTR?

Я цілком плутаюсь із цими LPCSTR LPSTR LPWSTRта LPCWSTR.

Це LPWSTRі LPCWSTRте саме?

Відповіді:


114

str.c_str()дає вам const char *, що є LPCSTR(Довгий покажчик на постійне STRING) - означає, що це вказівник на 0завершений рядок символів. Wозначає широкий рядок (складається із wchar_tзамість char).


5
Незначна вибаглива точка: на x64 LPCSTR був би 64-бітовим вказівником на (постійний) нульовий кінець рядка.
Джоель

154

Зателефонуйте, c_str()щоб отримати const char *( LPCSTR) від а 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 типівdef, які відповідають:

LPCSTR: вказівник на нульовий завершений рядок const char

LPSTR: вказівник на нульовий завершений рядок char char(часто буфер передається і використовується як параметр 'output')

LPCWSTR: вказівник на нульовий завершений рядок const wchar_t

LPWSTR: вказівник на нульовий завершений рядок wchar_t(часто буфер передається і використовується як параметр 'output')

"Конвертувати" 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містить рядок, що використовує системне кодування за замовчуванням (якщо припустити, тут, тут), то ви можете знайти довжину необхідного буфера з широким символом та виконати перекодування за допомогою MultiByteToWideChar(API 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;
}

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очікується a або де LPCWSTRочікується a .

Одним незначним настроєм було б використовувати 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) входить у зображення.



3

Перетворення просте:

std::string myString;

LPCSTR lpMyString = myString.c_str();

Тут слід бути обережним, що c_str не повертає копію myString, а лише вказівник на рядок символів, який std :: string обгортає. Якщо ви хочете / потребуєте копії, вам потрібно зробити її самостійно, використовуючи strcpy.


1

На мою думку, найпростіший спосіб перетворити 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, однак, перетворить кожну таблицю в a . Це справедливо лише в тому випадку, якщо вони std::stringмістять ASCII або Latin-1, завдяки тому, що значення Unicode нагадують значення Latin-1. Якщо він містить CP1252 або символи будь-якого іншого кодування, це складніше. Потім вам потрібно буде перетворити символи.


Чому б не використовувати std::wstring?
Timmmm

@Timmmm: C ++ 11 посилив специфікацію, оскільки впровадження не скористалося старими правилами, сьогодні це було б нормально.
MSalters

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

myString - це вхідний рядок, а lpSTR - це еквівалент LPSTR .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.