UnicodeString 在所有平台上都是 UTF-16 编码的字符串。但是,wchar_t 是一种 16 位类型,仅在 Windows 上用于 UTF-16 数据。在其他平台上,wchar_t 是用于 UTF-32 数据的 32 位类型。
这在 Embarcadero 的 DocWiki 中有记录:
String Literals char16_t and wchar_t on macOS and iOS
(Android 也包括在内)
在 macOS 和 iOS 上,char16_t 不等同于 wchar_t(就像在 Windows 上一样):
- 在 Windows 上,
wchar_t 和 char16_t 都是双字节字符。
- 但在
macOS、iOS、和 Android 上,wchar_t 是一个 4 字节字符。
因此,要声明 UTF-16 常量字符串,在 Windows 上使用 L 或 u 前缀,而在 macOS、iOS、和 Android 上,使用 u 前缀.
Windows 上的示例:
UnicodeString(L"Text"), UnicodeString(u"Text")
macOS、iOS、和 Android 上的示例:
UnicodeString(u"Text")
但是,在 macOS、iOS、 和 Android 上对字符串文字使用 L 前缀并没有错。在这种情况下,UTF-32 常量字符串被转换为 UTF-16 字符串。
为了便于移植,请使用_D 宏来编写相应前缀为L 或u 的常量字符串。示例:
UnicodeString(_D("Text"))
为确保在所有平台上使用 UTF-16,System::WideChar 类型是 Windows 上 wchar_t 和其他平台上 char16_t 的别名。 UnicodeString 是 WideChar 元素的容器。
因此,如果您对数组使用 wchar_t,那么在非 Windows 平台上,您需要先在运行时将 UnicodeString 转换为 UTF-32,例如使用 RTL 的 UnicodeStringToUCS4String() 函数,然后再使用然后可以将该数据复制到您的数组中,例如:
typedef struct recordstruct
{
bool shop;
bool bought;
wchar_t description[80];
} recordtype;
recordtype MasterItems[MAXITEMS]=
{
false,false,L"Apples",
false,false,L"Apricots",
false,false,L"Avocado",
...
};
...
#if defined(WIDECHAR_IS_WCHAR) // WideChar = wchar_t = 2 bytes
StrLCopy(MasterItems[index].description, Edit1->Text.c_str(), std::size(MasterItems[index].description)-1); // -1 for null terminator
/* or:
UnicodeString s = Edit1->Text;
size_t len = std::min(s.Length(), std::size(MasterItems[index].destination)-1); // -1 for null terminator
std::copy_n(s.c_str(), len, MasterItems[index].destination);
MasterItems[index].destination[len] = L'\0';
*/
#elif defined(WIDECHAR_IS_CHAR16) // WideChar = char16_t, wchar_t = 4 bytes
UCS4String s = UnicodeStringToUCS4String(Edit1->Text);
size_t len = std::min(s.Length-1, std::size(MasterItems[index].destination)-1); // UCS4String::Length includes the null terminator!
std::copy_n(&s[0], len, MasterItems[index].destination);
MasterItems[index].destination[len] = L'\0';
#else
// unsupported wchar_t size!
#endif
否则,如果您想确保您的阵列在所有平台上始终为 16 位 UTF-16,那么您需要在阵列中使用 char16_t 或 WideChar 而不是 wchar_t。 u 前缀创建一个基于char16_t 的文字,而RTL 的_D() 宏创建一个基于WideChar 的文字(根据平台使用L 或u),例如:
typedef struct recordstruct
{
bool shop;
bool bought;
char16_t description[80]; // or: System::WideChar
} recordtype;
recordtype MasterItems[MAXITEMS]=
{
false,false,u"Apples", // or: _D("Apples")
false,false,u"Apricots", // or: _D("Apricots")
false,false,u"Avocado", // or: _D("Avocado")
...
};
...
StrLCopy(MasterItems[index].description, Edit1->Text.c_str(), std::size(MasterItems[index].description)-1); // -1 for null terminator
/* or:
UnicodeString s = Edit1->Text;
size_t len = std::min(s.Length(), std::size(MasterItems[index].description)-1); // -1 for null terminator
std::copy_n(s.c_str(), len, MasterItems[index].description);
MasterItems[index].description[len] = u'\0'; // or: _D('\0')
*/