• 过滤4字节及以上的字符c++实现


    这个是根据php的一个版本改的,用来处理utf-8编码的多字节字符,比如中文,俄文等等。

    #include <iostream>
    #include <string>
    
    int strip4ByteChars(const std::string str, std::string &ot);
    unsigned char ord(int ch);
    
    int main() {
        std::string str = "Esto es una prueba lalalala así que la llenaré de ÑÑÑÑÑÑ así y también de ÇÇÇÇÇÇÇÇ y algunos acentos en francés del tipo télévision, évenement, ouvrière, même, hôpital, juïf o âge.";
    //    std::string str = "abcdefg АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩъыьЭЮЯ 你好世界!";
        std::string ret;
        if( strip4ByteChars(str, ret) == 0 ) {
            std::cout << str << std::endl << std::endl;
            std::cout << ret << std::endl;
        } else {
            std::cout << "error!" << std::endl;
        }
        return 0;
    }
    
    /**
     * 处理特殊字符串
     * @param string $str
     */
    int strip4ByteChars(const std::string str, std::string &ot) {
        int len = str.length();
        unsigned char v,v2,v3;
        for (int i = 0; i < len; ) {
            v = ord(str[i]);
            if (v == 0x09 || v == 0x0A || (v < 0x80 && v >= 0x20)) { // 单字节
                ot += v;
                i += 1;
            } else if (v >= 0xC2 && v <= 0xDF) { // 双字节
                v2 = ord(str[i + 1]);
                if (v2 >= 80 && v2 <= 0xBF) {
                    ot += v;
                    ot += v2;
                    i += 2;
                } else {
                    ++i;
                }
            } else if (v == 0xE0) { // 三字节
                v2 = ord(str[i + 1]);
                v3 = ord(str[i + 2]);
                if (v2 >= 0xA0 && v2 <= 0xBF && v3 >= 0x80 && v3 <= 0xBF) {
                    ot += v;
                    ot += v2;
                    ot += v3;
                    i += 3;
                } else {
                    ++i;
                }
            } else if (v == 0xED) { // 三字节
                v2 = ord(str[i + 1]);
                v3 = ord(str[i + 2]);
                if (v2 >= 0x80 && v2 <= 0x9F && v3 >= 0x80 && v3 <= 0xBF) {
                    ot += v;
                    ot += v2;
                    ot += v3;
                    i += 3;
                } else {
                    i ++;
                }
            } else if (v >= 0xE1 && v <= 0xEF && v != 0xED) { // 三字节
                v2 = ord(str[i + 1]);
                v3 = ord(str[i + 2]);
                if (v2 >= 0x80 && v2 <= 0xBF && v3 >= 0x80 && v3 <= 0xBF) {
                    ot += v;
                    ot += v2;
                    ot += v3;
                    i += 3;
                } else {
                    i ++;
                }
            } else if (v >= 0xF1 && v <= 0xF4) { // 四字节
                i += 4;
            } else { // 四字节以上
                i ++;
            }
        }
    
        return 0;
    }
    // 字符转ascii码,返回值为无符号int
    unsigned char ord(int ch) {
        unsigned char ret;
        ret = ch & 0xff;
        return ret;
    }

    多字节字符的二进制表示如下:

    Unicode符号范围      | UTF-8编码方式
    (十六进制)           | (二进制)
    --------------------+---------------------------------------------
    0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    以双字节字符为例110xxxxx 10xxxxxx

    使用下标访问时每次访问一个字节,这时候双字节字符会被分开访问,如上的双字节将会分为110xxxxx和10xxxxxx,使用int保存时,单字节会自动补齐为当前系统中int需要的字节数,补齐规则跟系统有关,带符号数通常是按照符号位的值补齐,由于这两个字节的最高位都是1,以int为4字节为例,这两个字节在实际访问时就会变成:

    11111111 11111111 11111111 110xxxxx 和 11111111 11111111 11111111 10xxxxxx

    这样如果直接使用这两个值就会得到一个负数,而且远远超出了ascii码的表示范围,而我们真正需要的只是这两个int的地8位,所以使用

    ret = ch & 0xff;

    取出低8位,又因为ascii码没有负数,所以应该用unsigned char表示。

    参考文件:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

  • 相关阅读:
    MySQL--CREATE INDEX在各版本的优化
    MySQL--各版本DDL 操作总结
    MySQL--事务隔离级别RR和RC的异同
    MySQL--运维内参中的binlog_summary脚本
    认知:人性
    诉衷情
    初中生读物
    DTO和Entity转换
    layui开发常用插件列表
    mongodb配置
  • 原文地址:https://www.cnblogs.com/lrxing/p/6423097.html
Copyright © 2020-2023  润新知