字符串类型存在缺陷

字符串类型存在缺陷

  

我的前一篇文章《我们不需要字符串类型》引起了不少争议,反馈带来了许多不同的观点,通常大家都认为字符串类型是一个有用的特性。经过更多地研究,我可以确定一个事情:目前大多数的字符串类型实现都存在缺陷。

大家都有种错觉:字符串能处理比它自身提供得多的功能。我们使用它的时候,并没有深究它是否可靠。这会导致使用这些字符串编程的程序出现问题,尤其是在国际化的问题上。大多情况,如果我们不是依赖字符串类型,我们可以做到更好(避免这些问题)。

 

衡量字符串的实现

我考察了一下字符串在一些常用场合的表现。我会阐述各种场合下,期望的返回和一些实际返回值。我原本想使用一个表格来展示这些不同结果,不过所有测试的语言表现都很糟糕,使得这样的对比缺乏意义。

noël

当我使用一个编码为“noe\u0308l”的unicode字符串代表“noël”,我测试了如下内容:

  1. 是否打印正确?是的,大多数语言都能正确处理这个打印。不过ideone.com在这个问题上处理有些问题(所以,应该仔细地测试你的字符串类型)。
  2. 字符串反转是什么值?“lëon”,对吗?大多数语言都处理失败。得到的结果通常都是“l̈eon”(双引号在‘I’上,而不是在‘e’上)。由于没有使用特定的字符串处理类,仅仅是对编码字符数组进行了反转。
  3. 前三个字符是什么?多数语言的得到的是”noe”,这和期望的“noë”是不同的。这容易导致在确定字符时出现大问题,我想大多数人都不希望得到这个结果。这再次表明字符串类型仅仅只是被当作编码元素数组处理。
  4. 字符串长度是多少?基本上返回都是5。再一次,显示字符串类型仅仅只是把它当成数组处理,而不是真正的字符串文本。

上述的这些问题,试想你正在你喜欢的编辑器中编写这些文本会出现什么现象。我期望‘ë’被当作一个字符来处理。我不喜欢当我进行回退/删除操作时,仅仅删除了其部分字符。我希望拷贝前三个字符的时候应该包含’e’上的双点。

 

□□

(译注:由于WordPress系统的原因,原文中的小标题表情在本站也无法显示,所以干脆就用两个□替代了)

上面的字符在unicode码中比较少见,显示示两只猫(我希望你有相关的字体——如果没有看到的话,上面的标题时一只开心的猫和一只不高兴的猫,是unicode表情字符的一部分。)挑出上面的字符是因为这些字符在基本多语言之外(BMP)。而这会导致那些使用UTF-16字符编码的语言出现问题(Java,C#,JavaScript)

  1. 长度?Python使用unicode返回正确的2,其他UTF-16语言都返回4:这些字符需要使用字符代理。
  2. 减去第一个字符是什么?Python正确返回伤心的猫表情,其他UTF-16语言返回一个无效字符和伤心的猫字符的一半。
  3. 反转字符。Python返回正常的猫表情,其他UTF-16语言返回错误的字符串,在ideone中我可能发现了C#的一个缺陷,它甚至都没有返回乱码,而是是什么也没输出。([ideone defect])

其他使用字符串函数库的语言,像C++,perl和Python2字符串库也处理失败。它们都假定只是一个字符数组,而忽略了字符编码。Python3使用了unicode作为内置编码,所以解决了该问题。Perl使用UTF-8模式可以正确处理这两只猫,不过在前面的例子却处理失败(“noël”字符串)。

 

baffle

这个字符串包含了一个叠加字符,“ffl”是单个的Unicode字符,存在主要是为了兼容性。但是这个例子可以很好测试字符转换。

变换大小写产生的是什么?我没有找到一个语言的打印不是“BAfflE”。请注意这里的叠加字符还是保持小写,而期望的值应该是“BAFFLE”。

Unicod有一个特殊的大小写转换:这个叠加字符被处理为三个编码元素。由于没有准守这个额外的规则,语言处理大写转换函数导致了一个有趣的现象:字符串被大写仍然保留了小写的字符。

 

再测试一下noël

让我们测试一下两个逻辑上相同的字符的不同组合形式。这里“noël”使用了预构字符“ë”。

  1. 预构字符串是否和非预构字符串相等?所有的测试都是失败的。不过有些语言提供了Unicode标准化处理函数库。在这些语言中,字符串的标准化结果是相等的。JavaScript没有这样的函数库,这显得有些诧异,因为它是一门专门为UI准备的语言,而这更需要处理Unicode编码。

尽管人们会认为这些规范化处理和字符串操作不是典型的基本字符,但是这些基本操作都包含在文字处理中,如果这些内容不被包含,那么我们需要字符串的目的是什么呢?

 

字符串存在缺陷

我期望你们去测试一下你常用的语言。如果你的工作和国际化相关,那么这就对你很重要了,你需要知道你的字符串类型怎么工作的。一旦你测试了,你就会认识到字符串类型究竟是怎么处理的。在我看来这些实现都存在缺陷。

我承认这些问题并不明显,字符串处理是个复杂的主题,不过最低限度我们应该包含相关的字符集(一些字符串类型会提供相关的功能函数,比如Perl的GCString)。不过这不在这篇文章的讨论范围。不过这是一个很好的相关字符串类型。

我前述文章的观点显得更为深刻了。我宁愿使用字符数组而不是一个存在缺陷的字符串类型。我不会假定字符数组会有一些错误的返回:上述结果的测试返回对于字符数组都是逻辑上合理的。事实上,如果使用unicode字符数组,那么这些测试结果会比那些实现字符串类型的语言好得多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值