首页 > 试题广场 >

UTF-8 编码验证

[编程题]UTF-8 编码验证
  • 热度指数:1108 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解

UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
1. 对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
2. 对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
这个是UTF-8编码的工作方式:

   Char. number range  |        UTF-8 octet sequence
      (hexadecimal)    |              (binary)
   --------------------+---------------------------------------------
   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
给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。
注意:
输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。




输入描述:
多行字符串,每行字符串包括整数数字以及数字之间分隔符英文逗号(,)。每个整数只有最低8个有效位来存储数据,这就意味着每个整数只表示一个字节的数据。


输出描述:
对输入的每行数据均进行验证,并输出true或者false。true代表有效的utf-8编码,false则是无效的。
示例1

输入

197,130,1

输出

true

说明

data = [197, 130, 1], 表示 8 位的序列: 11000101 10000010 00000001.
返回 true 。
这是有效的 utf-8 编码,为一个2字节字符,跟着一个1字节字符。
示例2

输入

235,140,4

输出

false

说明

data = [235, 140, 4], 表示 8 位的序列: 11101011 10001100 00000100.
返回 false 。
前 3 位都是 1 ,第 4 位为 0 表示它是一个3字节字符。
下一个字节是开头为 10 的延续字节,这是正确的。
但第二个延续字节不以 10 开头,所以是不符合规则的。
发表于 2019-11-15 15:19:14 回复(0)
//本地测试没有问题,但是AC=30%,望大佬改进下
//leetcode 393
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <limits.h>
#include <stdlib.h>

using namespace std;
//字符串转二进制
string stringToBinary(string temp) {
    string res = "";
    int num = stoi(temp);
    for (int i = 7; i >= 0; i--) {
        res += ((num >> i) & 1) + '0';
    }
    return res;
}

void utf8Coding(string s) {
    vector<string> vec;
    string temp;
    string str_bin;
    int len = s.size();
    for (int i = 0; i < len; i++) {
        if (s[i] != ',') {
            temp += s[i];
        }
        else {
            str_bin = stringToBinary(temp);
            vec.push_back(str_bin);
            temp = "";
        }
    }
    str_bin = stringToBinary(temp);
    vec.push_back(str_bin);
    string res = "true";
    int cnt = 0;
    int vec_len = vec.size();
    int pos = 0; //记录1字节字符在原字符串中出现的位置
    bool flag = false;
    //判断为几字节字符,并统计个数
    for (int i = 0; i < vec_len; i++) {
        if (vec[i][0] == '0') {
            pos = i;
            continue;
        }
        //只有前4位有效
        for (int j = 0; j < 4; j++) {
            if (vec[i][j] == '1') {
                cnt++;
            }
            else {
                flag = true;
                break;
            }
        }
        if (flag) {
            break;
        }
    }
    //分两部分判断,第一部分是1字节字符前边的
    for (int i = 0; i < pos; i++) {
        if (vec[i][0] == '1' && vec[i][1] == '0') {
            continue;
        }
        else {
            res = "false";
        }
    }
    //1字节字符后边的
    for (int i = pos + 2; i < cnt; i++) {
        if (vec[i][0] == '1' && vec[i][1] == '0') {
            continue;
        }
        else {
            res = "false";
        }
    }
    cout << res << endl;
}

int main(){
    string s;
    while(cin>>s) {
        utf8Coding(s);
    }
    return 0;
}

编辑于 2020-05-11 23:15:19 回复(0)
这题答案存在错误,举例,当utf码为四个字节时,首字节之后的任意一节为0xff,此时是非法的,但明显检测不出这个非法
发表于 2020-01-06 20:36:31 回复(0)
import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()) {

            String[] str = sc.next().split(",");
            short[] arr = new short[str.length];
            for (int i = 0; i < str.length; i++) {
                short n = Short.valueOf(str[i]);
                arr[i] = (short)(n & 0xFF);
            }

            boolean illegal = true;
            for (int i = 0; i < arr.length; i++) {
                short b = arr[i];
                if (b >= 0 && b < 128) {
                    continue;
                } else if (b >= 192 && b < 224) {
                    if (i + 1 >= arr.length) {
                        illegal = false;
                        break;
                    }

                    illegal = arr[i + 1] >= 128 && arr[i + 1] < 192;
                    if (!illegal)
                        break;

                    i += 1;
                } else if (b >= 224 && b < 240) {
                    if (i + 2 >= arr.length) {
                        illegal = false;
                        break;
                    }

                    illegal = arr[i + 1] >= 128 && arr[i + 1] < 192 && arr[i + 2] >= 128 && arr[i + 2] < 192;
                    if (!illegal)
                        break;

                    i += 2;
                } else if (b >= 240 && b < 248) {
                    if (i + 3 >= arr.length) {
                        illegal = false;
                        break;
                    }

                    illegal = arr[i + 1] >= 128 && arr[i + 1] < 192 && arr[i + 2] >= 128 && arr[i + 2] < 192 &&
                            arr[i + 3] >= 128 && arr[i + 3] < 192;

                    if (!illegal)
                        break;

                    i += 3;
                } else {
                    illegal = false;
                    break;
                }
            }

            System.out.println(illegal);
        }
    }
}


发表于 2019-08-15 14:26:30 回复(0)