字符串类型存在缺陷

原创 2013年12月05日 11:06:16

字符串类型存在缺陷

  

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

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

 

衡量字符串的实现

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

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字符数组,那么这些测试结果会比那些实现字符串类型的语言好得多。

相关文章推荐

循环体中用“+”拼接字符串-代码典型缺陷分析

java+拼接字符串 为什么+拼接性能低 代码缺陷+拼接字符串
  • QZC78
  • QZC78
  • 2015年07月09日 09:40
  • 361

0e开头MD5 python生成脚本 PHP哈希弱类型比较缺陷

MD5弱类型比较 在代码审计当中经常见到,所以写了一个python脚本,有事没事跑一下,积累一些字符串。 网上大多都是看到《0e开头MD5值小结》这篇文章,这里希望给大家一个可自定义字符的自动化脚本,...

软件测试类型/缺陷分类的获取

软件测试类型分析是进行细化软件测试用例条件的重要手段之一,通过测试类型的分类,软件测试人员可以将测试条件从不同的维度进行考虑,并发现不同的缺陷类型,从而提高测试的覆盖率。   测试类型并不是一个标准...

缺陷类型分类

  • 2014年05月28日 16:25
  • 1KB
  • 下载

Java 语言的几个缺陷之二: equals() 比较字符串

转载自:http://unmi.cc/java-language-defect-2-equals-compare-strings/ 对于面向对象的语言不知道除了 Java 还有没别的语言会拿怎么...

缺陷类型的小总结

1、从测试角度来看,所有缺陷的类型   兼容性问题:.net4.0安装包,在x86和64位系统上约有不同。Owc11的兼容性。更新包的兼容性问题。   分辨率的问题:某行多按钮时,在低分辨率下显示...

Objective-C弱类型的一个大缺陷

通常我们会想当然地认为,我们可以把任何想要的消息发送给代码中类型为“id”的变量,然后Objective-C的动态消息处理就会在运行时让这一调用正确地工作。但在某些罕见的情况下,这种假定是错误的。在本...

类型转换与字符串拆分

  • 2013年06月25日 12:33
  • 3.07MB
  • 下载

有缺陷的枚举类型 和 C++11中的强类型枚举

首先第一点,我们要弄清一个概念,那就是枚举类型的名字都在其父作用域空间 可见的。举个例子就一目了然了。 enum Type { General, Light, Medium, Heavy }; en...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字符串类型存在缺陷
举报原因:
原因补充:

(最多只允许输入30个字)