【问题标题】:Visual C++: Convert data type PCSTR to LPCWSTRVisual C++:将数据类型 PCSTR 转换为 LPCWSTR
【发布时间】:2016-06-21 14:47:25
【问题描述】:

我有以下从 HttpContext 实例检索标头请求信息的 C++ 代码:

public:
REQUEST_NOTIFICATION_STATUS
    OnBeginRequest(
    IN IHttpContext * pHttpContext,
    IN IHttpEventProvider * pProvider
    )
    {

        UNREFERENCED_PARAMETER(pHttpContext);
        UNREFERENCED_PARAMETER(pProvider);

        PCSTR header = pHttpContext->GetRequest()->GetHeader("Accept", NULL);
        WriteEventViewerLog(header);

如你所见,调用:

pHttpContext->GetRequest()->GetHeader("Accept", NULL)** 

返回 PCSTR 数据类型。

但我需要将带有标题的 WriteEventViewerLog 作为“LPCWSTR”提供,因为我在方法中使用的函数之一只接受该格式的字符串。

来自https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx,关于这些字符串定义:

指向 8 位 Windows 的常量空终止字符串的指针 (ANSI) 字符。有关详细信息,请参阅使用的字符集 字体。

此类型在 WinNT.h 中声明如下:

typedef CONST CHAR *PCSTR;

和 LPCWSTR:

指向 16 位 Unicode 的以空字符结尾的常量字符串的指针 人物。有关详细信息,请参阅字体使用的字符集。

此类型在 WinNT.h 中声明如下:

typedef CONST WCHAR *LPCWSTR;

我没有找到从这两种数据类型转换的方法。我尝试将 header 转换为 char*,然后使用下面的函数从 char* 移动到 LPCWSTR

LPWSTR charArrayToLPWSTR(char *source)
    {
        // Get required buffer size in 'wide characters'
        int nSize = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0);

        LPWSTR outString = new WCHAR[nSize];

        // Make conversion
        MultiByteToWideChar(CP_ACP, 0, source, -1, outString, nSize);
        return outString;
    }

但这返回给我一个无效的字符串(我没有完整的输入,但 Accept 标头值被修剪为“x;ih”)。

【问题讨论】:

  • 该功能应该可以工作。检查调试器中发生了什么。
  • 从外观上看,charArrayToLPWSTR() 应该可以工作,尽管我会让const char *source 匹配PCSTR 的类型:LPWSTR wszHeader = charArrayToLPWSTR(header); /* Code using wszHeader. */ delete[] wszHeader;。您是否有更多信息,例如有效或无效的示例输入和输出,以及可能需要使用 LPWSTR 的实际代码部分?
  • 试试CP_UTF8 而不是CP_ACP
  • 我建议在 MultiByteToWideChar() 周围使用方便的 ATL 转换助手,或者编写一些返回 CStringstd::wstring 的函数,但不要返回原始拥有在函数体内分配有new[] 的指针。如果调用者不太注意解除分配返回的字符串,这可能是 leaktrocity。它是 C++不是 C.
  • 该函数不检查返回值。请显示导致错误输出的输入示例。另请注意,该函数需要调用者正确释放缓冲区,否则会泄漏。

标签: c++ string winapi lpcstr lpcwstr


【解决方案1】:
pHttpContext->GetRequest()->GetHeader("Accept", NULL);   

返回一个PCSTR 数据类型。

但我需要将标题作为 WriteEventViewerLog LPCWSTR,因为我在方法中使用的函数之一 只接受该格式的字符串。

首先,让我们澄清一下这些“晦涩”的Windows API字符串typedefs的含义:

PCSTR:   const char *    
LPCWSTR: const wchar_t *

因此,两者都是指向只读 NUL 终止的 C 样式字符串的指针

区别在于PCSTR指向一个基于char的字符串; LPCWSTR 指向基于 wchar_t 的字符串。

char-based 字符串可以是多个“形式”(或编码),例如简单的 ASCII,或 Unicode UTF-8,或其他“多字节”编码。

如果是您的标头字符串,我假设它可以是简单的 ASCII 或 UTF-8(注意 ASCII 是 UTF-8 的真子集)。

Visual C++ 中基于wchar_t 的字符串是Unicode UTF-16 字符串(这是大多数 Win32 API 使用的“本机”Unicode 编码)。

所以,您要做的就是从基于char 的字符串转换为基于wchar_t 的字符串。假设您的基于char 的字符串代表一个Unicode UTF-8 字符串(纯ASCII 是其真子集),您可以使用MultiByteToWideChar() Win32 API 进行转换。 p>

或者您可以使用一些帮助类来简化转换任务,例如ATL conversion helpers。特别是,带有CP_UTF8 转换标志的 CA2W 助手可以在您的情况下派上用场:

#include <atlconv.h>  // for CA2W
...

// Get the header string in Unicode UTF-8
PCSTR header = pHttpContext->GetRequest()->GetHeader("Accept", nullptr);

// Convert the header string from UTF-8 to Unicode UTF-16
WriteEventViewerLog( CA2W(header, CP_UTF8) );

【讨论】:

  • 使用 CA2W 解决了这个问题。除了 atlconv.h 之外,我只需要 #include &lt;atlbase.h&gt; #include &lt;atlstr.h&gt; 就可以使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
相关资源
最近更新 更多