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

How to do string operations with Win32 WCHAR

本文关键字:字符串 操作 执行 WCHAR 何使用 Win32      更新时间:2023-10-16

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

我知道这代表宽字符并且是 Unicode,但我并不完全掌握编码的工作原理。例如,我知道 UTF-8 也包含 Unicode,但它和 WCHAR 一样吗?

我以为字符串看起来像

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

对于复制,只需假设字符串的长度是两倍就可以了。但是,例如,在搜索字符时,我会收到错误,例如:

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

产生一些损坏的错误。我把这弄得太复杂了吗?我知道可能有很多函数可以做到这一点,但我想了解它是如何工作的,这样我就可以制作高效的代码。谢谢

较短的答案

您遇到的具体问题是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 上,宽字符是小端 UTF-16。 这不是便携式的,但是,WCHAR也不是。 在其他一些系统上,宽字符要么是大端 UTF-16,要么是大端或小端 UTF-32。 在 C 语言中,标准类型char16_tchar32_t<uchar.h>中定义。 在C++中,它们被内置到语言中。 如果您尝试将char16_t*传递给需要wchar_t*的函数,则如果没有强制转换,或者在Windows以外的目标上根本无法工作。

UTF-8 是一种存储 Unicode 码位的方法,它向后兼容七位 ASCII。 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.
*/