c - 终止(可能)多字节字符串?

标签 c substring multibyte null-terminated

我正在编写 C 代码并努力寻找一种在特定字符数后终止字符串的方法。例如,我需要在 3 个字符后终止字符串 data。如果它是一个普通的 ASCII 字符串,我可以做类似的事情

data[3] = 0;

但在我的例子中,任何字符都可以是多字节的,例如 È 或 À。在给定数量的字符之后终止此类字符串的最佳方法是什么?

更新:

基本上:

char s_mon[7];

setlocale(LC_ALL, "");
strftime(s_mon, 7, "%b", tick_time);

当前语言环境是法语。月份被存储为“févr.”。需要它是“fév”,但这需要是通用的,因此像“mars”这样的条目也可以减少到 3 个字符。

最佳答案

最终重用了这个 utf_str_to_upper功能。该函数正确处理多字节值。它还将字符串转换为大写字母(我也需要),但如果需要可以删除该功能。

我所做的唯一修改是传递第二个参数 limit,这是我需要剪切字符串的 characters 限制。该函数然后在正确的字节位置插入终止符并返回字节位置。完整代码如下:

uint8_t utf8_str_to_upper(char* s, uint8_t limit) {

    uint8_t char_no = 0;
    uint8_t* p;

    for (p = (uint8_t*)s; *p; ++p) {

        // (<128) ascii character
        // U+00000000 – U+0000007F: 0xxxxxxx
        if (*p < 0b10000000) {
            if (*p >= 0x61 && *p <= 0x7A) {
                *p = *p - 0x20; // a~z -> A~Z
            }

        // (<192) unexpected continuation byte
        } else if (*p < 0b11000000) {

        // (<224) 2 byte sequence
        // U+00000080 – U+000007FF: 110xxxxx 10xxxxxx
        } else if (*p < 0b11100000) {
            uint16_t code = ((uint16_t)(p[0] & 0b00011111) << 6) | (p[1] & 0b00111111);
            if (
                (code >= 0x00E0 && code <= 0x00F6) || // à~ö -> À~Ö
                (code >= 0x00F8 && code <= 0x00FE)    // ø~þ -> Ø~Þ
            ) {
                code -= 0x0020;
                p[0] = 0b11000000 | ((code >> 6) & 0b00011111);
                p[1] = 0b10000000 | ( code       & 0b00111111);
            }
            ++p;

        // (<240) 3 byte sequence
        // U+00000800 – U+0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
        } else if (*p < 0b11110000) {
            p += 2;

        // (<248) 4 byte sequence
        // U+00010000 – U+001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        } else if (*p < 0b11111000) {
            p += 3;

        // (<252) 5 byte sequence
        // U+00200000 – U+03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        } else if (*p < 0b11111100) {
            p += 4;

        // (<254) 6 byte sequence
        // U+04000000 – U+7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        } else if (*p < 0b11111110) {
            p += 5;
        }

        if (limit) {
            char_no++;

            if (char_no == limit) {
               *(p + 1) = 0;
               return p-(uint8_t*)s + 1;
               break;
            }

        }

    }

    return p-(uint8_t*)s + 1;
}

关于c - 终止(可能)多字节字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42210748/

相关文章:

PHP 阿拉伯文文本使用 strpos 进行比较

python - 有没有人能够使用 python 的 xlwt 写出 UTF-8 字符?

.net - 如何在 .NET 中的较大集合中定位一系列值(特别是字节)

c - Couchbase REST API 是否支持 NON-JSON 数据(二进制数据)

c - 使用GTK+2编译C代码调用octave函数时出现错误

javascript - 如何在字符串中使用反斜杠 (\)?

java - 是否可以反转子字符串的起点和终点?

c - 不同编译器的 sizeof(struct) 不同

c - 与不相等的字符串比较时,strcmp() 返回 0

substring - Databinder.Eval 和 Substring