Linux下如何将控制台输入读取到char16_t缓冲区?有无替代方案?
将Linux控制台输入读取到char16_t缓冲区的替代方案
你当前用mbrtoc16逐字符转换的方法可行,但并非唯一方案,以下是几种常用替代方式:
1. 使用iconv库进行批量转换
iconv是Linux系统中处理字符编码转换的标准工具,支持批量转换,效率比逐字符处理更高。示例代码如下:
#include <iconv.h> #include <stdlib.h> #include <unistd.h> char16_t* convertToChar16_iconv(const char* src, size_t src_len) { // 打开UTF-8到UTF-16LE的转换句柄(char16_t通常对应UTF-16,注意字节序) iconv_t cd = iconv_open("UTF-16LE", "UTF-8"); if (cd == (iconv_t)-1) { return NULL; } // 计算目标缓冲区大小:UTF-8转UTF-16,每个字符最多占2字节,预留额外空间 size_t dest_size = src_len * 2 + 2; char16_t* dest = malloc(dest_size); if (!dest) { iconv_close(cd); return NULL; } char* in_buf = (char*)src; char* out_buf = (char*)dest; size_t in_left = src_len; size_t out_left = dest_size; // 执行转换 if (iconv(cd, &in_buf, &in_left, &out_buf, &out_left) == (size_t)-1) { free(dest); dest = NULL; } iconv_close(cd); return dest; } // 使用示例 char tempBuf[1024] = {0}; int readBytes = read(STDIN_FILENO, tempBuf, 1024); char16_t* buf = convertToChar16_iconv(tempBuf, readBytes);
注意:需要根据系统的char16_t字节序选择UTF-16LE或UTF-16BE,大部分Linux系统是小端序,用UTF-16LE即可。
2. 借助宽字符输入函数中转
Linux下的wchar_t是4字节(对应UTF-32),可以先通过宽字符IO读取输入,再转换为char16_t:
#include <wchar.h> #include <locale.h> #include <stdlib.h> char16_t* wchar_to_char16(const wchar_t* src, size_t src_len) { size_t dest_size = src_len * 2 + 2; char16_t* dest = malloc(dest_size); if (!dest) return NULL; size_t idx = 0; for (size_t i = 0; i < src_len; i++) { wchar_t wc = src[i]; if (wc <= 0xFFFF) { // 基本多语言平面字符,直接存储 dest[idx++] = (char16_t)wc; } else { // 辅助平面字符,拆分为代理对 wc -= 0x10000; dest[idx++] = (char16_t)((wc >> 10) + 0xD800); dest[idx++] = (char16_t)((wc & 0x3FF) + 0xDC00); } } dest[idx] = 0; // 终止符 return dest; } // 使用示例 setlocale(LC_ALL, ""); // 必须设置locale,否则宽字符IO无法正确工作 wchar_t wbuf[512] = {0}; if (fgetws(wbuf, sizeof(wbuf)/sizeof(wchar_t), stdin) != NULL) { char16_t* buf = wchar_to_char16(wbuf, wcslen(wbuf)); // 使用buf... free(buf); }
这种方式省去了手动处理多字节序列的麻烦,但依赖locale的正确设置,且需要处理UTF-32到UTF-16的代理对转换。
3. C标准库的std::wstring_convert(若使用C)
如果你的项目允许使用C++,可以利用标准库的编码转换工具,代码更简洁:
#include <codecvt> #include <string> #include <fstream> std::u16string convert_to_char16(const std::string& src) { std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; return converter.from_bytes(src); } // 使用示例 char tempBuf[1024] = {0}; int readBytes = read(STDIN_FILENO, tempBuf, 1024); std::string src_str(tempBuf, readBytes); std::u16string u16_str = convert_to_char16(src_str); // u16_str即为char16_t类型的缓冲区(可通过u16_str.data()获取指针)
注意:部分编译器(如GCC)可能需要链接-lstdc++fs或启用特定C标准(如C11及以上)才能使用std::wstring_convert。
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

