如何使用Win32 WCHAR执行字符串操作

时间:2017-04-28 16:53:45

标签: c++ unicode unicode-string wchar-t

我有一个win32项目,我尝试使用自定义函数编辑WCHAR字符串的字符。

我知道这代表宽字符并且是Unicode,但是我不完全掌握编码的工作原理。例如,我知道UTF-8也拥有Unicode,但它与WCHAR相同吗?

我认为字符串看起来像

00 43 00 4f 00 44 00 45 00 00
    C     O     D     E    \0

对于复制它可以很好地假设字符串是两倍长。但是,当我搜索一个角色时,我会遇到错误,例如:

for(int i = wcslen(inStr) - 2; i >= 0; i--) {
    WCHAR current[] = {inStr[i], inStr[i + 1], 0, 0};
    if(current == _T("/")) {
        pos = i;
        break;
    }
}

产生一些损坏的错误。我这太复杂了吗?我知道这可能有很多功能,但我想了解它是如何工作的,所以我可以制作高效的代码。感谢

1 个答案:

答案 0 :(得分:1)

更短的答案

您遇到的具体问题是current[n]是数组中的第n个元素,而不是数组的第n个字节。像current + n这样的指针运算也可以在current指向的后面找到第n个元素。如果您声明一个intdouble,某些struct或其他任何内容的数组,情况也是如此。

因此,当你声明一个数组wchar_t a[] = L"!",然后取wcslen(a)时,你会得到数组中宽字符的数量,1。如果你试图设置i = wcslen(a) - 2;然后取a[i]i将为-1,这是一个严重的错误。

更长的解释

在Windows上,WCHAR是标准类型wchar_t的别名。你不是说你是用C还是C ++写的。 C标准库中有许多函数可以在<wchar.h><wctype.h>中处理宽字符串。 C ++标准库包含所有这些内容,以及std::wstring中的<string>和包含std::wcoutstd::wcinstd::wcerr的宽字符流(尽管Windows不不完全支持他们)。大多数Windows API函数也可以接受宽字符串。宽字符串的标准类型为wchar_t*,但WCHAR*LPWSTR以及默认情况下在Visual Studio的现代版本中,TCHAR*LPTSTR也是工作

在Windows上,宽字符是little-endian UTF-16。这不是便携式的,但是WCHAR也不是。在其他一些系统中,宽字符可以是big-endian UTF-16,也可以是big-little-endian UTF-32。在C中,标准类型char16_tchar32_t<uchar.h>中定义。在C ++中,它们内置于语言中。如果您尝试将char16_t*传递给期望wchar_t*的函数,则在没有强制转换的情况下或在除Windows之外的其他目标上都无法正常工作。

UTF-8是一种存储与7位ASCII向后兼容的Unicode代码点的方法。 UTF-8是UTF-16或UTF-32的替代表示。 UTF-8字符串将存储在unsigned charchar的数组中,其中一个Unicode代码点可能需要几个字节来存储它。实际上,由于代理对,Unicode代码点可能还需要两个UTF-16对象来对其进行编码。有时候使用不同的表示很方便(UTF-16LE是Windows ABI所期望的,有些像ICU和QT这样的库在内部使用,而UTF-32是唯一保证所有Unicode字符都适合的表示形式。单个元素),但我的建议是随时使用UTF-8和其他编码。

可能的解决方案

如果您想通过宽字符串向后阅读,可以试试这个:

int i = wcslen(inStr); // Could be 0.

if (i > 0) { // Don't read one element past the start of the array.
  do {
    --i;
  } while ( i > 0 && inStr[i] != L'/' );
}

/* When we reach this line, i is either 0 or the index of the last slash
 * in inStr, which could also be 0.  We can test whether inStr[i] == L'/' or
 * write an if() within our loop to do something more complicated.
 */