2007-12-31

点睛文本编码查询 D 语言版

关键字: D, phobos, DFL

  本软件用于将文本的字符串转换为 Text、Default、Unicode、UTF-8 之间的互相转换,用于文本查询。转换结果使用十六进制表示。

  D 语言版不需要特殊的运行库支持。相对于 VB5 版增加了允许输入十六进制的功能,相对于 .net 版减少了一些功能。

  对于我自己来说,这是练习使用 D 语言的一个副产品。

  程序使用 D 1.015, phobos 和 dfl 开发。

  在这一次练习中,发现 D 语言使用上可以和 c# 很类似,比如我写的 HexStringCoding 类,从 c# 复制过来,只修改了几个小地方(如增加 cast,去除 unsafe),就可以正常编译并且正常运行。另外,和 c/dll 的集成也不错,使用 WideCharToMultiByte 之类的系统函数还是很方便的。dfl 大体模仿 .net,所以使用起来很方便。

  不过,问题也不少。

  比如 bool 类型可以和任何可以转换为 0 和 1 的值进行隐式转换,就是一个语言方面的缺陷。

  另外,D 语言选择 char[] 当作字符串来处理,也是一个非常不可理解的事情。char[] 被定义为 utf8,所以如果要对它进行随机检索的话,就需要更多的代码和更差的运行效率,在我看来,utf8 根本不适合作为程序内部处理字符串的编码方案。utf16 才适合。另外,没有 string 类,而用数组来代替 string 的做法也问题多多,除了强类型检测之外,string 类还应该提供相应的字符串处理函数,而不是使用全局函数处理字符串。在我做这个程序的时候,是都使用 utf16 的 wchar[] 来做中间的字符串代替品的,不过,dfl 遵循使用 char[] 的方案,所以,和界面交互的部分也做了转换处理。也许以后可以修改一下 dfl 的代码,使之直接使用 utf16 吧。

  另一个问题是,无法使用 obj == null 来判断一个实例是否为空,这个问题不知道别人有没有遇到,或者有什么别的解决方案,我是通过 try catch 的方式处理了,不过感觉很不爽。

  另外,还遇到一个问题,基类定义了 abstract 的函数,子类实现了,但是没有使用 override 关键字,编译通过,但是运行结果莫名其妙,加上 override 之后就正常了。这个问题可能造成错误的几率要比上面说的问题大的多,本来,D 应该在这种情况下编译出错才是。

  再者,D 的 module 组织方式,感觉是在鼓励大家把所有的类写入一个文件中,实在不是一个好的方式。

  对于 dfl,也稍微说一下,它使用了首字母小写的方式,在我看来,既然模仿 .net,就不如模仿个彻底,让大家把 .net 的程序复制过来后,做最少的修改就能编译运行才好 —— 所有首字母改成小写,也是一个不小的工程啊。

  Tango 的安装步骤很罗嗦,我还没有试过,不过,嗯,回头还是应该试一下的。

评论
梁利锋 2008-01-05
@oldrev

1 判断指针难道不应该用 &p == null 么?那么 &p == null 和 p == null 什么区别?

2 utf16的问题,用 phobos(D1.015) 写一个简单的程序:
char[] s = "世界,你好";
writef(s);
代码保存成 utf8 带标志的格式,运行结果是:
涓栫晫锛屼綘濂
如果用 readln 获取输入的话:
char[] s = readln();
writef(s);
输入“世界,你好”,结果是:
Error: 4invalid UTF-8 sequence
当然,这可以看作 phobos 的一个 bug,同样缺省使用 utf8 的 tango(D1.024) 就可以正确处理中文。
utf8 是一种适合于保存(对于英语世界来说)的格式,而不是一个适合于处理的格式,任何的字符串处理函数在处理 utf8 的时候都会非常麻烦 —— 如果它真的把它当作 utf8,而不是纯英文在处理的话。所以我认为,使用 utf8 作为内码只是使得英语世界的人,更容易的写出不支持多语言的程序却不自知。
我至今没有发现什么需要转换成 utf32 才能操作的文本,也许以后会有吧。

3 用 c++ 不多,不知道 std::string 成员函数太多而广受批评是什么意思。ruby 里面对于数组,连 first 和 last 都各自是一个函数,也没见有人批评,反而是赞誉居多。不过 D 也支持“扩展方法”倒是挺好的。

4 c# 也是一定要写 override 关键字的,否则编译器会抱怨说“如果你想隐藏一个父类成员,请使用 new 关键字进行隐藏”。我只是觉得奇怪,为什么 D 里面不写 override 关键字可以编译通过,特别是,父类里的是一个 abstract 的函数,根本没有缺省实现,而编译器却没有任何抱怨?

5 标准库的问题,似乎也很多人说了。tango 我也试了一下,感觉好一点,毕竟 phobos 里面,基本上连个“类”都很难找到,大都是裸函数。其实,我觉得,“标准库”只是提供一组 interface 都是好的,这样才更体现“标准”之意。

6 首字母小写只是个人习惯问题了
oldrev 2008-01-03
几个小问题:

1. utf16只是 ms 的一厢情愿而已,除nt外绝大多数系统都是 utf-8,真要到操纵文本的时候都得转换成 utf32。

2. 尽量用外部函数而不是成员函数这更有利于封装,C++ 的 std::string 就是因为成员函数太多而广受批评。D里对数组有个“扩展方法”的语法糖:定义了 void foo(T)(T[] array); 就可以用 array.foo() 的形式来调用了。

3. 跟 C# 不一样的地方,凡是涉及到 override 都要写 override 关键字。

4. D 的 module 官方走的是小而专的路子,就像 Ruby和Python的标准库那样,反之, tango 想重新成为 .net/java 标准库

5. 首字小写是官方推荐标准,个人感觉比较合理,比如构造函数就是 this(),天生的 camelcase,呵呵。如果说类型首字大写的话那些内置属性比如 int.Sizeof 会很难看
oldrev 2008-01-03
判断指针可以用 p == null,而对象引用一定要用 obj is null
梁利锋 2008-01-01
又试了一下,判断 obj 是否为 null 可以使用 obj is null,只是不理解为什么 obj == null 不会造成编译错误。
发表评论

您还没有登录,请登录后发表评论

梁利锋
搜索本博客
博客分类
存档
最新评论