You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:27:41