วิธีแปลง std :: string เป็น LPCSTR


111

ฉันสามารถแปลงstd::stringไปLPCSTR? นอกจากนี้วิธีการที่ฉันสามารถแปลงstd::stringไปLPWSTR?

ฉันสับสนกับสิ่งเหล่านี้LPCSTR LPSTR LPWSTRและLPCWSTR.

เป็นLPWSTRและLPCWSTRเหมือนกันหรือไม่?

คำตอบ:


114

str.c_str()ให้คุณconst char *ซึ่งเป็นLPCSTR(Long Pointer to Constant STRing) - หมายความว่าเป็นตัวชี้ไปยัง0สตริงอักขระที่สิ้นสุด Wหมายถึงสตริงกว้าง (ประกอบด้วยwchar_tแทนchar)


5
จุดจู้จี้จุกจิกเล็กน้อย: บน x64 LPCSTR จะเป็นตัวชี้ 64 บิตไปยังสตริงที่สิ้นสุดด้วย null (ค่าคงที่)
Joel

154

โทรc_str()เพื่อรับ a 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 (ยาว) ของชื่อ - เป็นการระงับจาก Windows 16 บิต


32

นี่คือ typedefs ที่ Microsoft กำหนดซึ่งสอดคล้องกับ:

LPCSTR: ตัวชี้ไปยังสตริง const ที่สิ้นสุดด้วย null ของ char

LPSTR: ตัวชี้ไปยังสตริงอักขระที่สิ้นสุดด้วย null ของchar(โดยมากบัฟเฟอร์จะถูกส่งผ่านและใช้เป็นพารามิเตอร์ 'เอาต์พุต')

LPCWSTR: ตัวชี้ไปยังสตริงที่สิ้นสุดด้วย null ของ const 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::stringa 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;
}

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) เข้ามาในภาพ



3

การแปลงเป็นเรื่องง่าย:

std::string myString;

LPCSTR lpMyString = myString.c_str();

สิ่งหนึ่งที่ต้องระวังคือ c_str ไม่ส่งคืนสำเนา myString แต่เป็นเพียงตัวชี้ไปยังสตริงอักขระที่ std :: string wraps หากคุณต้องการ / ต้องการสำเนาคุณจะต้องทำด้วยตัวเองโดยใช้ 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()ซ้ำ สิ่งนี้จะแปลงถ่านแต่ละตัวเป็น a wchar_tแม้ว่า ใช้ได้เฉพาะในกรณีที่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เทียบเท่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.