유효한 수정 UTF-8입니까?


9

UTF-8 은 유니 코드 코드 포인트를 가변 너비 형식으로 인코딩하여 유니 코드를 인식하지 못하는 코드를 쉽게 혼동하지 않는 비교적 간단한 방법입니다.

UTF-8 개요

  • 1-0x7F 범위의 바이트는 일반적으로 유효합니다.
  • 비트 패턴을 10XX XXXX갖는 바이트는 연속 바이트로 간주되며 6 개의 최하위 비트는 코드 포인트의 일부를 인코딩하는 데 사용됩니다. 이들은 선행 바이트에 의해 예상되지 않는 한 나타나지 않아야합니다.
  • 패턴이 110X XXXX있는 바이트는 이후에 하나의 연속 바이트를 예상합니다.
  • 패턴이 1110 XXXX있는 바이트는 이후에 두 개의 연속 바이트를 예상합니다.
  • 패턴이 1111 0XXX있는 바이트는 이후에 3 개의 연속 바이트를 예상합니다.
  • 다른 모든 바이트는 유효하지 않으며 UTF-8 스트림의 어느 곳에도 나타나서는 안됩니다. 이론적으로 5, 6 및 7 바이트 클러스터가 가능하지만이 문제의 목적으로 허용되지 않습니다.

긴 인코딩

UTF-8에서는 코드 포인트를 최소 바이트 수로 표시해야합니다. 더 적은 바이트로 표시 될 수있는 바이트 시퀀스는 유효하지 않습니다. 수정 된 UTF-8은 널 문자 (U + 0000)에 대해 여기에 하나의 예외를 추가하고 C0 80(16 진 표현 으로 표시되어야 함 ) 대신 스트림의 어느 곳에 나 널 바이트가 나타나지 않도록합니다. (이것은 null로 끝나는 문자열과 호환됩니다)

도전

바이트 문자열이 제공 될 때 해당 문자열이 유효한 수정 UTF-8을 나타내는 지 판별하고 유효하면 거짓 값을, 그렇지 않으면 거짓 값을 리턴하는 프로그램을 작성해야합니다. 긴 인코딩 및 널 바이트 (이는 수정 UTF-8이므로)를 점검해야합니다. UTF-8 값을 디코딩 할 필요는 없습니다.

41 42 43  ==> yes (all bytes are in the 0-0x7F range)
00 01 02  ==> no (there is a null byte in the stream)
80 7F 41  ==> no (there is a continuation byte without a starter byte)
D9 84 10  ==> yes (the correct number of continuation bytes follow a starter byte)
F0 81 82 41  ==> no (there are not enough continuation bytes after F0)
EF 8A A7 91  ==> no (too many continuation bytes)
E1 E1 01  ==> no (starter byte where a continuation byte is expected)
E0 80 87  ==> no (overlong encoding)
41 C0 80  ==> yes (null byte encoded with the only legal overlong encoding)
F8 42 43  ==> no (invalid byte 'F8')

규칙

  • 표준 규칙 및 허점이 적용됩니다
  • 부호없는 바이트 범위 (0-255)의 모든 값을 읽을 수 있으면 입력 및 출력을 편리한 형식으로 지정할 수 있습니다.
    • null로 끝나는 문자열 대신 배열이나 파일을 사용해야 할 수도 있습니다. 널 바이트를 읽을 수 있어야합니다.
  • 최단 코드 승리!
  • 내장을 사용하여 UTF-8을 디코딩한다고해서 여기에 주어진 요구 사항을 준수하는 것은 아닙니다. 이를 해결하고 특별한 경우를 작성해야 할 수도 있습니다.

편집 : UTF-8을 디코딩하는 내장을 사용하지 않는 것에 대한 보너스 추가

EDIT2 : Rust 답변 만 자격이 주어지고 보너스를 정의하기 때문에 보너스가 제거되었습니다.


나는 이것을 기다리고 있었다.
Adám

0xF8-0xFF 범위의 잘못된 바이트로 테스트 사례를 추가 할 수 있습니다.
Arnauld 2019 년

2
"현대"UTF-8 사양과 달리 대리 (0xD800-0xDFFF) 및 0x10FFFF를 초과하는 코드 포인트가 허용되는 것 같습니다. 추가 테스트 사례로 이상적으로 설명해야한다고 생각합니다.
nwellnhof

더 많은 예제 도움이 될 것입니다
돈의 밝은

"0-0x7F 범위의 바이트는 일반적으로 유효합니다"는 1에서 0x7f 여야합니까?

답변:



1

APL (Dyalog Unicode) , 41 39 바이트 SBCS

익명의 암묵적 접두사 기능. 문자의 코드 포인트가 입력 바이트를 나타내는 유니 코드 문자열을 인수로 사용합니다.

{0::0⋄×⌊/'UTF-8'UCS2UCS⍵}'À\x80'RA

온라인으로 사용해보십시오!

'À\x80'⎕R⎕AR eplace C0 80의 대문자와 lphabet

{} 인수가 다음과 같은 익명 함수를 적용하십시오 .

0:: 오류가 발생하면 :

  0 제로를 돌려 주다

 시험:

  ⎕UCS⍵ 문자열을 코드 포인트로 변환

  'UTF-8'⎕UCS⍣2 UTF-8 바이트로 해석하고 결과 텍스트를 바이트로 다시 변환

  ⌊/ 가장 낮은 바이트 (널 바이트가있는 경우 0, 그렇지 않은 경우 양수, 빈 문자열 인 경우 "무한대")

  × 부호 (널 바이트가 존재하면 0, 그렇지 않으면 1)


이것에 대해 진실하지 D9 C0 80 84 C0 80 10않습니까?

@Neil 그것은 실제로 않습니다. 제거 C0 80하면 관련되지 않은 바이트가 유효한 방식으로 인접하게되어 있기 때문에 잘못 되었습니까? 별도의 경우 유효하지 않습니다. 편집 : 바이트 비용없이 수정하도록 업데이트되었습니다.
Adám

일부 문자가 사각형이나 상자처럼 화면에 표시되는 것이 정상입니까? 리눅스의 파이어 폭스에서 메신저. APL은 매우 흥미로운 언어입니다.
밝게 하지마

@donbright 내 경험에 따르면 APL 문자는 때로는 아름답 지 않은 경우에도 항상 올바르게 렌더링되므로 해당 상자는 아마도 Quad 코드 일뿐 이며 주 코드에는 4 개가 있어야합니다. 다음과 같이 렌더링해야 합니다 . 그렇습니다. APL은 놀랍고 재미 있습니다. 쉽고 빠르게 배울 수도 있습니다 . APL 오차드 에서 다시 시작 하십시오 .
Adám

네, 쿼드입니다. 감사.
돈을


0

-191 바이트 313 바이트

원본 아래의 주석 당 제대로 작동하지 않았습니다. 새롭고 개선 된 버전. Mighty Rust에는 사용자와 라이브러리가 필요하지 않기 때문에 라이브러리가 사용되지 않습니다. 이 코드는 상태 머신과 패턴 일치를 사용합니다. Jon Skeet의 참조와 토론을 통해 UTF8 스펙뻔뻔스럽게 추출 함으로써 문자의 스펙을 거의 녹 문자 패턴 일치 블록에 복사 할 수 있습니다. 결국, 우리는 C0 80이 유효한 것으로 간주되기 위해 Beefster의 특별한 Mutf8 요건을 추가합니다. 언 골프 드 :

/* http://www.unicode.org/versions/corrigendum1.html
 Code Points        1st Byte    2nd Byte    3rd Byte    4th Byte
U+0000..U+007F      00..7F           
U+0080..U+07FF      C2..DF      80..BF           
U+0800..U+0FFF      E0          A0..BF      80..BF       
U+1000..U+FFFF      E1..EF      80..BF      80..BF       
U+10000..U+3FFFF    F0          90..BF      80..BF      80..BF
U+40000..U+FFFFF    F1..F3      80..BF      80..BF      80..BF
U+100000..U+10FFFF  F4          80..8F      80..BF      80..BF
*/

let m=|v:&Vec<u8>|v.iter().fold(0, |s, b| match (s, b) {
        (0, 0x01..=0x7F) => 0,
        (0, 0xc2..=0xdf) => 1,
        (0, 0xe0) => 2,
        (0, 0xe1..=0xef) => 4,
        (0, 0xf0) => 5,
        (0, 0xf1..=0xf3) => 6,
        (0, 0xf4) => 7,
        (1, 0x80..=0xbf) => 0,
        (2, 0xa0..=0xbf) => 1,
        (4, 0x80..=0xbf) => 1,
        (5, 0x90..=0xbf) => 4,
        (6, 0x80..=0xbf) => 4,
        (7, 0x80..=0x8f) => 4,
        (0, 0xc0) => 8, // beefster mutf8 null
        (8, 0x80) => 0, // beefster mutf8 null
        _ => -1,
    })==0;

녹 운동장에서 사용해보십시오


수동으로 수행하기위한 소품이지만 장기 점검이 잘못되었다고 생각합니다.
Beefster

귀하의 도전, 친애하는 각하, 모방에 저를 유발하고, 좀 더 직설적으로 (질문을 노출하는 사람에 해결하기 위해, 내 차례, 당신을 도전으로이 편지를 체결 bit.ly/2T8tXhO )
밝은 돈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.