我有一个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;
}
}
产生一些损坏的错误。我这太复杂了吗?我知道这可能有很多功能,但我想了解它是如何工作的,所以我可以制作高效的代码。感谢
答案 0 :(得分:1)
您遇到的具体问题是current[n]
是数组中的第n个元素,而不是数组的第n个字节。像current + n
这样的指针运算也可以在current
指向的后面找到第n个元素。如果您声明一个int
,double
,某些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::wcout
,std::wcin
和std::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_t
和char32_t
在<uchar.h>
中定义。在C ++中,它们内置于语言中。如果您尝试将char16_t*
传递给期望wchar_t*
的函数,则在没有强制转换的情况下或在除Windows之外的其他目标上都无法正常工作。
UTF-8是一种存储与7位ASCII向后兼容的Unicode代码点的方法。 UTF-8是UTF-16或UTF-32的替代表示。 UTF-8字符串将存储在unsigned char
或char
的数组中,其中一个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.
*/