如何将std::string转换为LPCSTR?

134

如何将std::string转换为LPCSTR?此外,如何将std::string转换为LPWSTR

我对这些 LPCSTRLPSTRLPWSTRLPCWSTR 完全感到困惑。

LPWSTRLPCWSTR是一样的吗?

9个回答

176

使用c_str()函数从std::string中获取一个const char * (LPCSTR)。

名称已经说明了一切:

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(long)部分——这是16位Windows的遗留物。


127

str.c_str()会给你一个const char *,它是一个LPCSTR(指向常量字符串的长指针),这意味着它是一个指向以0结尾的字符字符串的指针。W表示宽字符串(由wchar_t而不是char组成)。


5
在 x64 架构下,LPCSTR 是一个指向(常量)以 null 结尾的字符串的 64 位指针。 - Joel

35

这些是由 Microsoft 定义的 typedef,对应于:

LPCSTR:指向以 char 结尾的常量字符串的指针

LPSTR:指向以 char 结尾的字符串的指针(通常传递一个缓冲区,并将其用作“输出”参数)

LPCWSTR:指向以 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 包含使用系统默认编码(假设是 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;
}

24

使用 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
}

5
MultiByteToWideChar 的答案是 Charles Bailey 给出的正确答案。因为 LPCWSTR 只是 const WCHAR* 的一个 typedef,所以在示例代码中的 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)。

5

转换很简单:

std::string myString;

LPCSTR lpMyString = myString.c_str();

这里需要注意的一点是,c_str() 不会返回 myString 的副本,而只是一个指向 std::string 包装的字符字符串的指针。如果你想要/需要一个副本,你需要使用 strcpy 自己创建一个。


3
转换很简单:
std::string str;
LPCSTR lpcstr = str.c_str();

2

我认为将 std::string 转换为 LPWSTR 最简单的方法是:

  1. std::string 转换为 std::vector<wchar_t>
  2. 获取向量中的第一个 wchar_t 的地址。

std::vector<wchar_t> 有一个模板化构造函数,它可以接受两个迭代器,例如 std::string.begin().end() 迭代器。这将把每个字符转换为 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等效形式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接