0

我正在使用 C++Builder 10.3 Rio 为 Android 开发一个多平台应用程序。

我有一个数据数组如下:

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",
...
...
};

我已将其复制到 aTEdit中,并希望将值返回到MasterItems数组中。

我曾经使用c_str()mbstowcs()strcpy()/wcscpy()等。

请问我该怎么做?

4

1 回答 1

1

UnicodeString是所有平台上的 UTF-16 编码字符串。但是,wchar_t它是一种 16 位类型,仅在 Windows 上用于 UTF-16 数据。在其他平台上,wchar_t是用于 UTF-32 数据的 32 位类型。

这记录在 Embarcadero 的 DocWiki 中:

macOS 和 iOS 上的字符串文字 char16_t 和 wchar_t
(也包括 Android)

在 macOS 和 iOS 上,char16_t不等同于wchar_t(就像在 Windows 上一样):

  • 在 Windows 上,wchar_tchar16_t都是双字节字符。
  • 然而,在macOS和 Android上, a是一个 4 字节字符。iOSwchar_t

因此,要声明 UTF-16 常量字符串,在 Windows 上使用Lu前缀,而在 macOS、iOS和 Android上,使用u前缀。

Windows 上的示例:

UnicodeString(L"Text"), UnicodeString(u"Text")

macOS、iOS和 Android上的示例:

UnicodeString(u"Text")

L但是,在 macOS、iOS和 Android上使用字符串字面量前缀并没有错。在这种情况下,UTF-32 常量字符串被转换为 UTF-16 字符串。

为了可移植性,使用_D宏来编写以Lor为前缀的常量字符串u。例子:

UnicodeString(_D("Text"))

为确保在所有平台上使用 UTF-16,该System::WideChar类型是wchar_tWindows 和char16_t其他平台上的别名。 UnicodeStringWideChar元素的容器。

因此,如果您使用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_torWideChar而不是。前缀创建基于wchar_t-的文字,而 RTL 的宏创建基于 - 的文字(使用或根据平台),例如:uchar16_t_D()WideCharLu

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')
*/
于 2020-06-03T19:15:22.583 回答