【问题标题】:Convert char * to LPWSTR将 char * 转换为 LPWSTR
【发布时间】:2011-10-15 01:41:20
【问题描述】:

我正在尝试将多字节字符的程序转换为 Unicode。

我已经完成了这个程序,并在字符串文字前面加上了L,所以它们看起来像L"string"

这已经奏效,但我现在留下了一个不符合要求的 C 样式字符串。我已经尝试了L 并将其放入TEXT(),但L 被添加到变量名中——而不是字符串——如果我使用TEXT()

我尝试将其设为TCHAR,但随后它抱怨无法将TCHAR 转换为char *

我还有什么选择?

我知道 C 和 C++ 是不同的。它是一个古老的内部 C 库,已经在 C++ 项目中使用了好几年了。

【问题讨论】:

  • 有人会否决的主要原因更多是,恕我直言,您的问题中缺少源代码。一张图片值一千字,一段代码也是如此。即使是微不足道的。
  • 无论编译器设置如何,您绝对可以编写与TCHAR 一起使用的代码,您只需要创建正确的基础架构即可。在 C++ 中,重载为您完成所有繁重的工作。

标签: c++ c string


【解决方案1】:

std::mbstowcs 函数正是您要寻找的:

 char text[] = "something";
 wchar_t wtext[20];
 mbstowcs(wtext, text, strlen(text)+1);//Plus null
 LPWSTR ptr = wtext;

对于strings,

 string text = "something";
 wchar_t wtext[20];
 mbstowcs(wtext, text.c_str(), text.length());//includes null
 LPWSTR ptr = wtext;

--> ED:“L”前缀仅适用于字符串文字,不适用于变量。

【讨论】:

  • 已弃用,您应该使用mbstowcs_s()
  • @Olipro:这仅在 Windows 世界中被“弃用”。 OP 没有说明他针对的是哪个平台。
  • 平台是 Windows 是相当隐含的,但如果您不这么认为,请继续证明我错了。
  • @Olipro:_s 版本的优势是什么?据我所知,您传递了另一个计数参数,该参数指示您最多要写出多少个字符,但这有什么帮助呢?您已经在另一个参数中指定了输出缓冲区的大小,这仅仅是为了终止零吗?
  • 我是否理解正确,只有知道char* 的长度才能将char* 转换为LPWSTR?如果不是,为什么假设 20 个字符就足够了?
【解决方案2】:

我在 VC++ 中使用了以下内容,它对我来说就像一个魅力。

CA2CT(charText)

【讨论】:

  • 记得包含那个宏#include
【解决方案3】:

您可以使用CStringCStringACStringW 进行自动转换,并在这些类型之间进行转换。此外,您还可以使用CStrBufCStrBufACStrBufW 来获取 RAII 模式可修改字符串

【讨论】:

  • 但是请注意,它们是 ATL/MFC 特定的。
  • @JBES,是的。我在 6 年多前回答了这个问题,主要使用了 ATL/MFC。现在,即使是 C++ 语言也有用于转换的库功能。
【解决方案4】:

使用mbstowcs 的简洁方法是调用它两次以查找结果的长度:

  const char * cs = <your input char*>
  size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);

  // error if wn == size_t(-1)

  wchar_t * buf = new wchar_t[wn + 1]();  // value-initialize to 0 (see below)

  wn = mbsrtowcs(buf, &cs, wn + 1, NULL);

  // error if wn == size_t(-1)

  assert(cs == NULL); // successful conversion

  // result now in buf, return e.g. as std::wstring

  delete[] buf;

不要忘记在程序开始时调用setlocale(LC_CTYPE, "");

相对于 Windows MultiByteToWideChar 的优势在于它完全是标准 C,尽管在 Windows 上您可能更喜欢 Windows API 函数。

我通常将这个方法与相反的方法一起包装在两个转换函数string->wstringwstring->string 中。如果您还添加了简单的重载 string->stringwstring->wstring,您可以轻松编写在任何设置下使用 Winapi TCHAR typedef 编译的代码。

[编辑:] 我在buf 中添加了零初始化,以防您打算直接使用 C 数组。不过,我通常会将结果返回为std::wstring(buf, wn),但如果您打算使用 C 风格的空终止数组,请务必小心。[/]

在多线程环境中,您应该将线程本地转换状态作为函数的最终(当前不可见)参数传递给函数。

这是我关于这个主题的small rant

【讨论】:

  • +1 用于展示如何调用该函数两次以获取输出缓冲区的长度
  • 干杯。根据我自己的想法,我实际上为buf 使用了一个可变长度数组,但我想根据 SO 审查避免这种情况:-)
  • 更新:现在我会寻找codecvt,它包含mbsrtowcs/wcsrtombs
【解决方案5】:

此版本使用 Windows API 函数 MultiByteToWideChar() 处理任意长输入字符串的内存分配。

int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW>0)
{
    output = new wchar_t[lenW];
    ::MultiByteToWideChar(CP_ACP, 0, input, lenA, output, lenW);
} 

【讨论】:

  • @Kerrek 为了简洁起见,我省略了调用 free 的代码 ;-)
  • 我宁愿你保持原样也不要打电话给free()!这绝对是著名的delete[] 表达式的一个例子:-)
  • @kerrek 确实!很难跟踪 C 和 C++ 的问题。
  • 似乎没有必要在 'lstrlenA(input)' 调用中。见MSDNcbMultiByte : lpMultiByteStr 参数指示的字符串的大小,以字节为单位。或者,如果字符串以 null 结尾,则可以将此参数设置为 -1。 只需使用 -1 而不是 lenA。
  • @Alan 可以这样做,但另一方面,这种方式意味着长度计算一次而不是两次。我猜是个人选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
  • 2016-06-07
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
相关资源
最近更新 更多