Geçerli Modifiye UTF-8 mi?


9

UTF-8 , Unicode kod noktalarını Unicode farkında olmayan kodu kolayca karıştırmayacak şekilde değişken genişlikli bir formatta kodlamanın nispeten basit bir yoludur.

UTF-8'e genel bakış

  • 1-0x7F aralığındaki baytlar (dahil) normalde geçerlidir
  • Bit örüntüsüne 10XX XXXXsahip baytlar, bir kod noktasının bir kısmını kodlamak için en az altı önemli bit kullanıldığında devam baytları olarak kabul edilir. Önceki bir bayt tarafından beklenmedikçe bunlar görünmemelidir.
  • Desenli baytlar 110X XXXXdaha sonra bir devam baytını bekler
  • Desenli 1110 XXXXbaytlar daha sonra iki devam baytı bekler
  • Desenli 1111 0XXXbaytlar daha sonra üç devam bayt bekler
  • Diğer tüm baytlar geçersizdir ve UTF-8 akışında hiçbir yerde görünmemelidir. Teoride 5, 6 ve 7 bayt kümeleri mümkündür, ancak bu meydan okuma için izin verilmez.

Uzun kodlamalar

UTF-8 ayrıca bir kod noktasının minimum bayt sayısıyla temsil edilmesini gerektirir. Daha az bayt ile temsil edilebilecek bayt dizileri geçerli değildir. Değiştirilmiş UTF-8, boş karakterler (U + 0000) için C0 80(onaltılık gösterim) olarak temsil edilmesi gereken bir istisna ekler ve bunun yerine, boş baytların akışta herhangi bir yerde görünmesine izin vermez. (Bu, boş sonlandırılmış dizelerle uyumlu olmasını sağlar)

Meydan okuma

Bir bayt dizesi verildiğinde, bu dizenin geçerli Değiştirilmiş UTF-8'i temsil edip etmediğini belirleyecek ve geçerliyse bir doğruluk değeri ve aksi takdirde bir falsy değeri döndürecek bir program yapacaksınız. Uzun kodlamaları ve boş baytları kontrol etmeniz gerektiğini unutmayın (çünkü bu Modifiye UTF-8'dir). UTF-8 değerlerini deşifre etmenize gerek yoktur.

Örnekler

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')

kurallar

  • Standart kurallar ve boşluklar geçerlidir
  • İşaretsiz bayt aralığındaki (0-255) tüm değerler okunabildiği sürece giriş ve çıkış herhangi bir uygun biçimde olabilir.
    • Boş sonlandırılmış bir dize yerine bir dizi veya dosya kullanmanız gerekebilir. Boş baytları okuyabilmeniz gerekir.
  • En kısa kod kazanır!
  • UTF-8'in kodunu çözmek için yerleşiklerin kullanılmasının, burada verilen gereksinimlere uygunluğu garanti edilmediğini unutmayın. Etrafında çalışmanız ve özel durumlar oluşturmanız gerekebilir.

EDIT: UTF-8 kodunu çözen yerleşikleri kullanmamanız için bonus eklendi

EDIT2: yalnızca Rust yanıtı nitelikli olduğu ve tanımlanması garip olduğu için bonus kaldırıldı.


Bunu bekliyordum.
Adam

0xF8-0xFF aralığında geçersiz bir bayt içeren bir test durumu eklemek isteyebilirsiniz.
Arnauld

2
"Modern" UTF-8 spesifikasyonunun aksine, taşıyıcılara (0xD800 - 0xDFFF) ve 0x10FFFF dışındaki kod noktalarına izin verildiği görülmektedir. Bunun ideal olarak ek test durumları ile netleştirilmesi gerektiğini düşünüyorum.
nwellnhof

daha fazla örnek yardımcı olacaktır
don parlak

"0-0x7F aralığındaki baytlar, normalde geçerlidir" 1 ile 0x7f arasında olması gerekir mi?
don parlak

Yanıtlar:



1

APL (Dyalog Unicode) , 41 39 bayt SBCS

Anonim zımni önek fonksiyonu. Karakterlerin kod noktalarının girdi baytlarını temsil ettiği bir Unicode dizesini bağımsız değişken olarak alır.

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

Çevrimiçi deneyin!

'À\x80'⎕R⎕AR harfi C0 80büyük A lafabet ile

{} Argümanın olduğu aşağıdaki anonim işlevi uygulayın :

0:: herhangi bir hata olursa:

  0 sıfır döndür

 Deneyin:

  ⎕UCS⍵ dizeyi kod noktalarına dönüştür

  'UTF-8'⎕UCS⍣2 UTF-8 bayt olarak yorumlama ve elde edilen metni tekrar bayta dönüştürme

  ⌊/ en düşük bayt (boş bir bayt varsa sıfır, yoksa pozitif, boş dize "sonsuz")

  × işareti (boş bayt varsa sıfır, yoksa bir tane)


Bu doğruluk için dönmez D9 C0 80 84 C0 80 10mi?
Neil

@Neil Gerçekten de öyle. Bu yanlış mıdır C0 80? Düzenleme: Bayt maliyeti olmadan düzeltmek için güncellendi.
Adam

Bazı karakterler sadece dikdörtgenler veya kutular gibi ekranımda geliyor, bu normal mi? linux üzerinde firefox im. APL çok ilginç bir dildir.
Parlak don

bu kutular muhtemelen sadece bu yüzden @donbright Benim durumumda, APL karakterleri hep, hatta bazen daha az ise güzelce daha doğru bir şekilde oluşturulması Quad ana kod dört olmalıdır hangi. Sanki oluşturması gerektiğini bu . Ve evet, APL inanılmaz ve çok eğlenceli. Kolayca ve hızlı bir şekilde öğrenebilirsiniz - sadece APL Orchard'a gelin .
Adam

evet onlar dörtlü. Teşekkürler.
Parlak don

0

Python 2 , 104102 bayt

''.join(chr(int(c,16))for c in input().replace('00','-').replace('C0 80','0').split()).decode('utf-8')

Çevrimiçi deneyin!

Çıkış kodu üzerinden çıkışlar


0

Pas - 191 bayt 313 bayt

Orijinalin altındaki yorum başına düzgün çalışmadı. Yeni ve geliştirilmiş sürüm. Hiçbir kütüphane kullanılmaz, çünkü Mighty Rust'in Sizin ve Kütüphanelerinize İhtiyacı Yoktur. Bu kod, bir durum makinesiyle desen eşleşmesini kullanır. By utanmadan UTF8 spec parçalamakla aracılığıyla bulduktan sonra, Jon Skeet tarafından referans ve tartışma , bir pas Maç desen maç bloğuna karakter için neredeyse karakter spec kopyalayabilirsiniz. Sonunda, Beefster'ın C0 80'in geçerli sayılması için özel Mutf8 gereksinimini ekliyoruz. Ungolfed:

/* 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;

pas oyun alanında dene


Manuel olarak yapmak için sahne, ama bence aşırı kontrol yanlış.
Beefster

Zorluğun, sevgili efendim, taklit etmeye beni kışkırtıyor ve bu mektubu, sırayla, sorunuzu daha açık bir şekilde ortaya çıkaracak bir adamı düzeltmek için size meydan okuyarak bitirdim ( bit.ly/2T8tXhO )
don parlak
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.