我在Linux上工作。我必须从控制台读取到char16_t缓冲区。目前我的代码看起来像这样:
char tempBuf[1024] = {0};
int readBytes = read(STDIN_FILENO, tempBuf, 1024);
char16_t* buf = convertToChar16(tempBuf, readBytes);
字符串
在转换函数中,我使用mbrtoc16
标准库函数分别转换每个字符。这是从控制台读取到char16_t buf的唯一方法吗?你知道其他解决方案吗?
1条答案
按热度按时间eiee3dmh1#
多字节字符
在阅读到固定长度缓冲区时,您需要小心的主要事情是意外截断“多字节字符串”中的“多字节字符”
你问什么是多字节字符?在我的环境中,它们是UTF-8字符。例如,如果我运行
echo $LANG
,我会得到en_US.UTF-8
。这些就是它们的发音,它们是可以存储在多个字节上的字符。7位字节集以外的任何字符都存储在2个或更多个字节中,这些字节顺序排列。如果您只读取多个字节中的一部分,字节字符(截断它),那么你最终会在读取的两边都有垃圾。让我们看一个具体的例子:
示例代码
在下面完整的可运行文件中,我特意将缓冲区缩短到只有5个字符宽,这样我就可以轻松地容纳一个完整的4字节UTF-8多字节字符和一个空终止符。
字符串
运行示例
利用上面的代码,我可以构造一个输入,我知道它会故意打断(截断)一个字符,就像这样,看看发生了什么。
型
发生了什么?
在上面的例子中,我故意定位了UTF-8字符“é",它扩展为两个字节
0xC3
,0xA9
,这样它就会被你的read调用切断。然后我使用ungetc
将0xC3
放回标准输入,然后再和它的搭档0xA9
一起读一遍。只有当它们彼此相邻时,它们才有意义。你会看到一个0x0a
跟在它后面,我们知道并喜欢它是'\n'
,因为读者也抓住了我的回归。