它是经过有效修改的UTF-8吗?


9

UTF-8是一种以可变宽度格式编码Unicode代码点的相对简单的方法,这样它就不会轻易混淆不了解Unicode的代码。

UTF-8概述

  • 字节通常在1-0x7F(含)范围内
  • 具有位模式10XX XXXX的字节被视为连续字节,其中六个最低有效位用于编码部分代码点。除非前一个字节期望它们出现,否则它们不得出现。
  • 具有模式的110X XXXX字节之后需要一个连续字节
  • 具有模式的1110 XXXX字节之后需要两个连续字节
  • 具有模式的1111 0XXX字节之后需要三个连续字节
  • 所有其他字节均无效,并且不应出现在UTF-8流中的任何位置。5、6和7字节的簇在理论上是可能的,但出于此挑战的目的而不允许。

超长编码

UTF-8还要求用最少的字节数表示一个代码点。可以用更少的字节表示的任何字节序列都是无效的。修改后的UTF-8向其中添加了一个例外,即空字符(U + 0000),应将其表示为C0 80(十六进制表示),并且不允许空字节出现在流中的任何位置。(这使其与以null终止的字符串兼容)

挑战

您将要编写一个程序,当给定一个字节字符串时,该程序将确定该字符串是否表示有效的Modified UTF-8,如果有效,则返回真实值,否则返回假值。请注意,您必须检查超长编码和空字节(因为这是Modified 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)中的所有值即可。
    • 您可能需要使用数组或文件,而不是使用以空字符结尾的字符串。您需要能够读取空字节。
  • 最短的代码胜出!
  • 请注意,不能保证使用内置函数解码UTF-8符合此处给出的要求。您可能需要解决它并创建特殊情况。

编辑:由于不使用解码UTF-8的内置函数而增加了奖励

EDIT2:删除了奖金,因为只有Rust答案合格,并且定义起来很尴尬。


我一直在等待这个。
亚当

您可能想添加一个测试用例,其无效字节的范围为0xF8-0xFF。
Arnauld

2
似乎允许代理(0xD800-0xDFFF)和超出0x10FFFF的代码点,这与“现代” UTF-8规范相反。我认为应该澄清这一点,理想情况下应使用其他测试用例。
nwellnhof

更多示例将对您有所帮助
明亮的

“通常在0-0x7F(包括0-0x7F)范围内的字节是有效的”,是否应该是1到0x7f?
唐•唐(Don

Answers:



1

APL(Dyalog Unicode)41 39 字节SBCS

匿名默认前缀功能。以Unicode字符串作为参数,其中字符的代码点表示输入字节。

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

在线尝试!

'À\x80'⎕R⎕A[R E放置C0 80s的大写 lphabet

{} 应用以下匿名函数,其中参数为

0:: 如果发生任何错误:

  0 返回零

 尝试:

  ⎕UCS⍵ 将字符串转换为代码点

  'UTF-8'⎕UCS⍣2 解释为UTF-8字节并将结果文本转换回字节

  ⌊/ 最低字节(如果存在一个空字节,则为零;如果不存在,则为正;如果为空字符串,则为“无穷大”)

  × 符号(如果存在空字节则为零,否则为一个)


这不是真的D9 C0 80 84 C0 80 10吗?
尼尔,

@Neil 确实如此。这是错误的,因为删除C0 80使无关的字节以有效的方式相邻,尽管它们分开时是无效的吗?编辑:更新以免费解决此问题。
亚当

屏幕上出现的某些字符只是矩形或方框,这正常吗?我在Linux上的Firefox中。APL是一种非常有趣的语言。
明亮的

@donbright以我的经验,即使有时效果不佳,APL字符也始终可以正确呈现,因此这些框可能只是Quad,在主代码中应该有四个。它应该呈现像这样。是的,APL非常棒,而且很有趣。您也可以轻松,快速地学习它-只需在APL Orchard中进行即可
亚当

是的,它们是四边形。谢谢。
唐明亮

0

Python 2中104个 102字节

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

在线尝试!

通过退出代码输出


0

Rust- 191字节 313字节

以下原始注释中的每个注释均无法正常运行。新的和改进的版本。不使用任何库,因为The Mighty Rust不需要您和您的库。此代码使用状态机进行模式匹配。通过无耻地撕下UTF8规范,在通过Jon Skeet的参考和讨论找到它之后,我们可以将几乎每个字符的规范复制到一个生锈的Match模式匹配块中。最后,我们添加了Beefster对C0 80的特殊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
穿上鲜艳的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.