先从一段代码开始吧。这段代码来自于某个版本的灵图天行者,由于年代久远,所以我并不能保证它完全一致。不过,代码的用意和精髓我还是能够保证忠实还原的。
1 2 3 4 5 6 7 8 9 10 | int __cdecl foo(const void* p1, const void* p2) { PCWSTR pwz1 = (PCWSTR)p1; PCWSTR pwz2 = (PCWSTR)p2; if (0 == wcscmp(pwz1, L"重庆")) pwz1 = L"冲庆"; if (0 == wcscmp(pwz2, L"重庆")) pwz2 = L"冲庆"; return wcscmp(pwz1, pwz2); } |
简单解释一下,这是一个回调函数,被传递给 CRT 的 qsort 函数,用于对省级行政区进行名称排序。代码的用意也很简单,当传入的字符串参数是“重庆”时,以“冲庆”代替之进行比较。
因为“重庆”的“重”是多音字。在普通的字符串之中,被按“zhong”处理了,如果直接排序的话,最后得到的结果将是错误的。考虑如下代码:
int x = wcscmp(L"重庆", L"河北"); // wcscmp returns 1
在我看来,虽然 foo 这个函数可以完成正确的排序,但未免不够优雅。但似乎又没有什么更好的解决方案,于是 foo 的做法保留了很长时间——2009 年后也许有了更好的处理方法,不过我不知道。而且由于我后来离开了 GIS 这个行业,所以逐渐淡忘了这个事情。
不过,一个偶然的机会,iOS 的通讯录给了我一个更好的答案。

如上图所示,一名曾姓童鞋被归入了 C 的索引,有如重庆之于 zhong 庆。不过,通讯录却为用户提供了一个解决方案:

简单来说,为记录增加了一个排序参考字段。如果该字段非空,则以该字段为排序标准,否则以名称为排序标准。问题得以解决。





