如何在arduino中将十六进制UTF-16字符转换为字符串
How to convert hex UTF-16 char to string in arduino
我正在开发一个在 display/LCD 上正确显示阿拉伯语单词的功能。 (阿拉伯字母有四种不同的模式。)
我有一组不同状态的阿拉伯字母 (Map array
)。
识别阿拉伯语字母表后,我需要重新对齐字母。
我的问题是如何将 Unicode 字符通过 table (Map Table
) 放入 String variable
(pBuffer)?
例如:要写单词 باب
,您需要 select 来自 Map table
的信件并将其放在 String
中以发送到 display/LCD.
...
const unsigned char Map[][5] PROGMEM = {
/* code, isolated, initial, medial, final */
{0x0621, 0xFE80, 0x0000, 0x0000, 0x0000 }, //1 /* HAMZA ء*/
{0x0622, 0xFE81, 0x0000, 0x0000, 0xFE82 }, //2/* ALEF_MADDA آ*/
{0x0623, 0xFE83, 0x0000, 0x0000, 0xFE84 }, //3/* ALEF_HAMZA_ABOVE أ*/
{0x0624, 0xFE85, 0x0000, 0x0000, 0xFE86 }, //4/* WAW_HAMZA ؤ*/
{0x0625, 0xFE87, 0x0000, 0x0000, 0xFE88 }, //5/* ALEF_HAMZA_BELOW إ*/
{0x0626, 0xFE89, 0xFE8B, 0xFE8C, 0xFE8A }, //6/* YEH_HAMZA ئ*/
{0x0627, 0xFE8D, 0x0000, 0x0000, 0xFE8E }, //7/* ALEF ا*/
{0x0628, 0xFE8F, 0xFE91, 0xFE92, 0xFE90 } //8/* BEH ب*/
};
String pBuffer;
pBuffer += ((char)(Map[7][4]));
pBuffer += ((char)(Map[6][6]));
pBuffer += ((char)(Map[7][3]));
u8g2.setCursor(5, 20);
u8g2.print(pBuffer);
...
很遗憾,上面使用的方法不起作用。
如何将上面 "Map" table 中的 select 个字符放在一个 String
变量中?
首先,我必须建议您查找那些阿拉伯字符的 UTF-8 值。 Arduino 和 u8g2 都支持 UTF-8 编码,但不支持 UTF-16。从 UTF-8 值数组开始解决这个问题要简单得多。
对于 UTF-8 字符,编译器可以为您将 代码点 转换为字符串文字:
String character = u8"\u0628"; // ب
在内部,该字符串将包含两个字节,表示 UTF-8 中的“Ø”。
对于 UTF-8 或 UTF-16 中的 任何 阿拉伯字符,单个 char
的存储空间 space 不够,因此您必须使用数组 (char*
) 或 String
.
Arduino IDE 也允许您直接在代码中编写 Unicode 字符文字:
String character = "ب";
只要将源代码保存为UTF-8格式,字符串将与上面相同u8"\u0628"
值。
您可以重写您的字符映射表以使用 String
,然后只需按字面输入阿拉伯字符或使用代码点方法:(例如,在此处使用带重音的拉丁字符)
const String Map[][5] PROGMEM = {
{"a", "à", "á", "A", "Á"},
{"e", "è", "é", "E", "É"}
};
当然 String
将使用超过 2 个字节来存储这些字符,因此您可以通过将字符存储为 16 位整数来节省 space,但是您将不得不做一些事先转换。
Unicode 代码点实际上并不是您将在字符缓冲区中看到的二进制表示形式。 U+0628 = ب
但实际的二进制表示是 0xD8A8
。 那这是您应该存储在地图中的值,而不是您已经拥有的代码点 (0x0628
)。
const uint16_t Map[][5] PROGMEM = {
{0xD8A8, ..., ..., ...},
...
};
如果您对地图使用 String
,您可以轻松地从中构建字符串:
String output = Map[i][2] + Map[j][3] + Map[k][4];
如果使用uint16_t
,则必须将整数值拆分为两个字节以添加一个字符:
uint16_t v = Map[i][j]; // v = 0xD8A8 for example
char lo = v & 0xFF; // The D8 part of 0xD8A8, lo = 0xD8
char hi = v >> 8; // The A8 part of 0xD8A8, hi = 0xA8
String output = String(hi) + String(lo); // output = {0xA8, 0xD8}
最后,您必须将 String
转换为 char*
缓冲区以便与 U8g2::drawUTF8()
一起使用。您可以通过使用 output.c_str()
获取基础 char*
缓冲区来做到这一点。
我正在开发一个在 display/LCD 上正确显示阿拉伯语单词的功能。 (阿拉伯字母有四种不同的模式。)
我有一组不同状态的阿拉伯字母 (Map array
)。
识别阿拉伯语字母表后,我需要重新对齐字母。
我的问题是如何将 Unicode 字符通过 table (Map Table
) 放入 String variable
(pBuffer)?
例如:要写单词 باب
,您需要 select 来自 Map table
的信件并将其放在 String
中以发送到 display/LCD.
...
const unsigned char Map[][5] PROGMEM = {
/* code, isolated, initial, medial, final */
{0x0621, 0xFE80, 0x0000, 0x0000, 0x0000 }, //1 /* HAMZA ء*/
{0x0622, 0xFE81, 0x0000, 0x0000, 0xFE82 }, //2/* ALEF_MADDA آ*/
{0x0623, 0xFE83, 0x0000, 0x0000, 0xFE84 }, //3/* ALEF_HAMZA_ABOVE أ*/
{0x0624, 0xFE85, 0x0000, 0x0000, 0xFE86 }, //4/* WAW_HAMZA ؤ*/
{0x0625, 0xFE87, 0x0000, 0x0000, 0xFE88 }, //5/* ALEF_HAMZA_BELOW إ*/
{0x0626, 0xFE89, 0xFE8B, 0xFE8C, 0xFE8A }, //6/* YEH_HAMZA ئ*/
{0x0627, 0xFE8D, 0x0000, 0x0000, 0xFE8E }, //7/* ALEF ا*/
{0x0628, 0xFE8F, 0xFE91, 0xFE92, 0xFE90 } //8/* BEH ب*/
};
String pBuffer;
pBuffer += ((char)(Map[7][4]));
pBuffer += ((char)(Map[6][6]));
pBuffer += ((char)(Map[7][3]));
u8g2.setCursor(5, 20);
u8g2.print(pBuffer);
...
很遗憾,上面使用的方法不起作用。
如何将上面 "Map" table 中的 select 个字符放在一个 String
变量中?
首先,我必须建议您查找那些阿拉伯字符的 UTF-8 值。 Arduino 和 u8g2 都支持 UTF-8 编码,但不支持 UTF-16。从 UTF-8 值数组开始解决这个问题要简单得多。
对于 UTF-8 字符,编译器可以为您将 代码点 转换为字符串文字:
String character = u8"\u0628"; // ب
在内部,该字符串将包含两个字节,表示 UTF-8 中的“Ø”。
对于 UTF-8 或 UTF-16 中的 任何 阿拉伯字符,单个 char
的存储空间 space 不够,因此您必须使用数组 (char*
) 或 String
.
Arduino IDE 也允许您直接在代码中编写 Unicode 字符文字:
String character = "ب";
只要将源代码保存为UTF-8格式,字符串将与上面相同u8"\u0628"
值。
您可以重写您的字符映射表以使用 String
,然后只需按字面输入阿拉伯字符或使用代码点方法:(例如,在此处使用带重音的拉丁字符)
const String Map[][5] PROGMEM = {
{"a", "à", "á", "A", "Á"},
{"e", "è", "é", "E", "É"}
};
当然 String
将使用超过 2 个字节来存储这些字符,因此您可以通过将字符存储为 16 位整数来节省 space,但是您将不得不做一些事先转换。
Unicode 代码点实际上并不是您将在字符缓冲区中看到的二进制表示形式。 U+0628 = ب
但实际的二进制表示是 0xD8A8
。 那这是您应该存储在地图中的值,而不是您已经拥有的代码点 (0x0628
)。
const uint16_t Map[][5] PROGMEM = {
{0xD8A8, ..., ..., ...},
...
};
如果您对地图使用 String
,您可以轻松地从中构建字符串:
String output = Map[i][2] + Map[j][3] + Map[k][4];
如果使用uint16_t
,则必须将整数值拆分为两个字节以添加一个字符:
uint16_t v = Map[i][j]; // v = 0xD8A8 for example
char lo = v & 0xFF; // The D8 part of 0xD8A8, lo = 0xD8
char hi = v >> 8; // The A8 part of 0xD8A8, hi = 0xA8
String output = String(hi) + String(lo); // output = {0xA8, 0xD8}
最后,您必须将 String
转换为 char*
缓冲区以便与 U8g2::drawUTF8()
一起使用。您可以通过使用 output.c_str()
获取基础 char*
缓冲区来做到这一点。