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

如何从含多字节字符的字符串中截取6字节内的完整字符?

如何安全截取UTF-8字符串(不超过指定字节数且不截断字符)

这个问题我之前也踩过坑——直接用strncpy这类按字节截断的函数,很容易把多字节字符从中间劈开,导致出现乱码或者无效字符。核心原因是UTF-8编码中,非ASCII字符是由2-4个字节组成的,我们必须保证截取的位置刚好是某个字符的起始字节。

解决思路

要实现这个需求,关键是遍历字符串时,先判断每个字符的字节长度,再判断累计长度是否超过限制:

  1. 从字符串起始位置开始,逐个字符检查
  2. 对每个字符,根据UTF-8编码规则计算它的总字节数
  3. 如果把这个字符的字节数加到累计长度后不超过目标值,就保留它;否则停止遍历,不包含这个字符

UTF-8编码规则回顾

判断一个字符的字节长度很简单,看首字节的二进制前缀:

  • 单字节字符(ASCII):首字节以0开头(范围0~127),长度1字节
  • 双字节字符:首字节以110开头(范围192~223),后面跟1个以10开头的续字节
  • 三字节字符:首字节以1110开头(范围224~239),后面跟2个续字节
  • 四字节字符:首字节以11110开头(范围240~247),后面跟3个续字节

C语言实现代码

针对你的示例,我写了一个可直接使用的实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 获取单个UTF-8字符的字节长度
int get_utf8_char_len(const char *char_ptr) {
    unsigned char first_byte = (unsigned char)*char_ptr;
    
    if (first_byte < 0x80) {
        return 1; // ASCII单字节
    } else if (first_byte < 0xE0) {
        return 2; // 双字节字符
    } else if (first_byte < 0xF0) {
        return 3; // 三字节字符
    } else if (first_byte < 0xF8) {
        return 4; // 四字节字符
    }
    // 处理无效UTF-8编码,这里默认返回1,实际可根据需求添加错误处理
    return 1;
}

// 截取UTF-8字符串,确保不超过max_bytes字节,且不截断字符
char *truncate_utf8_string(const char *input, size_t max_bytes) {
    if (input == NULL || max_bytes == 0) {
        return NULL;
    }
    
    size_t total_bytes = 0;
    const char *current_ptr = input;
    
    while (*current_ptr != '\0') {
        int char_len = get_utf8_char_len(current_ptr);
        // 如果加上当前字符会超过限制,就停止
        if (total_bytes + char_len > max_bytes) {
            break;
        }
        total_bytes += char_len;
        current_ptr += char_len;
    }
    
    // 分配内存存储截取后的字符串(包含终止符)
    char *result = (char *)malloc(total_bytes + 1);
    if (result == NULL) {
        return NULL;
    }
    
    // 复制指定字节数,并添加字符串终止符
    memcpy(result, input, total_bytes);
    result[total_bytes] = '\0';
    
    return result;
}

int main() {
    const char *input = "aadđ€€¢¢";
    size_t target_bytes = 6;
    
    char *truncated_str = truncate_utf8_string(input, target_bytes);
    if (truncated_str != NULL) {
        printf("原字符串:%s\n", input);
        printf("截取后(最多%zu字节):%s\n", target_bytes, truncated_str);
        printf("截取后的实际字节数:%zu\n", strlen(truncated_str));
        free(truncated_str); // 记得释放内存
    }
    
    return 0;
}

代码说明

  • get_utf8_char_len:根据UTF-8编码规则,快速判断当前字符的字节长度
  • truncate_utf8_string:遍历字符串,累计字节数,确保不超过目标值,同时保证每个字符都被完整截取
  • 测试示例中,aad是3字节,đ是2字节,累计5字节(未超过6),而€是3字节,5+3=8>6,所以最终截取结果是aadđ,完全符合你的需求

注意事项

  • 这个实现假设输入是有效的UTF-8编码,如果输入包含无效的UTF-8序列,你可以添加额外的错误处理逻辑
  • 记得手动释放truncate_utf8_string返回的内存,避免内存泄漏
  • 如果是其他编程语言(比如Python、Java),都有现成的UTF-8字符串处理工具,核心思路都是一样的:不要直接按字节截断,要按完整字符处理

内容的提问来源于stack exchange,提问作者An Phong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:56:22