标题:Strconv(C, N)的第2个参数N是5或12时,我一看就有点儿头大!
只看楼主
cssnet
Rank: 4
等 级:业余侠客
威 望:4
帖 子:317
专家分:203
注 册:2013-10-4
结帖率:100%
 问题点数:0 回复次数:12 
Strconv(C, N)的第2个参数N是5或12时,我一看就有点儿头大!
讲真,遇到Unicode字符,应尽量地转换至UTF-8来处理,而尽量不要转换至Unicode(UCS-2)。
原因很简单:
UTF-8的英文字符,完全兼容ANSI,这样一来,许多涉及字符串的代码,几乎不需改动或改动很小,即可升迁至UTF-8;而UCS-2则很麻烦,英文的0h00就搞得人肝肠寸断、梨花带雨的。
搜索更多相关主题的帖子: 代码 参数 兼容 字符串 转换 
2022-11-16 22:23
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
如果不清楚原因,肯定会头大

首先,windows 所有涉及字符串的 api 函数,都实现了 A 和 W 两套,其中的 W 系列只认 utf-16 编码,没有认 utf-8 的第三套
其次,vfp ide 只认 ansi 字符,因此传递给 W 系列的 win32api 函数时,ansi 字符串必须用 strconv(ANSI字符串, 5) 转换成 utf-16 编码
同理,对于 utf-8 编码的字符串,vfp 必须用 strconv(UTF-8字符串, 12) 转成 utf-16 编码再交给 W 函数去处理

是否“应该尽量地转换至UTF-8来处理”?不尽然!首先你得搞清楚这些英文缩写的含义
unicode:是一种标准,包括字符集和编码方案,unicode 13 标准定义了 143859 个字符、符号的庞大字符集,最新的 14 版又增加了一些 Emoji 表情
utf-8:是 unicode 的一种编码方案, 采用 1-6字节的变长编码格式, 常用字符在 1-3 字节之间,例如:ascii 字符都是一字节,中文通常是三字节。
ucs-2,同样是一种编码方案,采用固定两字节编码,也就限制了只能有 65536 种可能性,因此它无法完整包含所有 unicode 字符,已被废弃不用
utf-16,它是 ucs-2 的扩充方案,对于 BMP 平面内的字符,与 ucs-2 完全兼容,对于非 BMP 字符,采用四字节来表示,Windows 使用此方案

由于英语的霸主地位,网络上大量的文本(包括网页源代码)都是 ascii 字符,从而 utf-8 的 ascii 单字节表示法优势尽显,因此网络上 utf-8 为王
但在本机上处理字符串时,这种多字节编码导致的解析复杂度就成为了缺点,而 utf-16 的定长编码成为优势。Windows 使用 utf-16 来表示 unicode 不可能是比尔靠拍脑袋做出的决定

网络上充斥着大量将这些名词混为一谈的文章,甚至在 vfp help、msdn 等文档中,微软也将 unicode 与 utf-16 划等号!前者可能是本身概念不清导致,后者则是由于其 unicode 是采用 utf-16 来现实的而有意为之,帝国主义永远都用自己的标准来做国际标准的野蛮由此可见一斑

至于用什么编码来存储数据,要依使用场景来决定
把【A 啊 𠅤】这三个字符用记事本分别保存为 utf-8 和 utf-16 (当然,你找不到 utf-16,原因见上一行)格式的文本文件,如果要你自己写一个函数来判断有几个字符,你认为那种编码方案更简单?
2022-11-17 17:08
cssnet
Rank: 4
等 级:业余侠客
威 望:4
帖 子:317
专家分:203
注 册:2013-10-4
得分:0 
自Windows NT开始采用Unicode(UCS-2)编码,大约是在15~20年前;再稍过一些时日,Java诞生,也采用了Unicode(UCS-2)编码。

这其实是个悲剧!鬼佬让中国人给骗了。呵呵。

那时,天还很蓝,草地还很绿,PM 2.5还远远不曾超标……鬼佬们天真地以为,只要用2字节16位65536种字符,就能包含地球上一切字符,于是欣然采用了Unicode(UCS-2)编码。

后来,他们才发觉自己好傻好天真!单单是中文字符,总数就已远超十万个!然后,这才亡羊补牢地搞什么utf-16、utf-32之类古里古怪的编码方案,说实话,大错已铸成,积重难返了。

相比utf-16,其实utf-8优势相当明显,特别是针对英语而言尤其如此。用在网络传输,utf-8也非常优秀、安全、方便,可称得上舍我其谁!

Windows API的W系列采用utf-16编码,其实是相当不智的。
2022-11-17 17:38
cssnet
Rank: 4
等 级:业余侠客
威 望:4
帖 子:317
专家分:203
注 册:2013-10-4
得分:0 
UTF-8编码,最优雅、也最最令人喜爱之处是:

UTF-8不会主动插入“硬编码字符”0x00和0xFF,这意味着,即使是调用年代最远古的C代码字符处理函数,也不会遇到特别麻烦;而至于UCS-2、utf-16、utf-32则不成的,到处是0x00,一切字符处理函数,只要遇到utf-16,就必须统统推倒重来!所以说,Windows API的W系列采用utf-16编码,那纯粹是自寻烦恼!自找不痛快!!

2022-11-17 18:00
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
帖子最后我列举了一个例子,自己用 vfp 代码实现原生函数 LenC 的 unicode 版,分别用 utf-8 和 utf-16 作为输入参数测试一下,哪种编码格式更有优势?要在 vfp 端处理 unicode 字符,有很大可能需要自己来实现这些功能

另一方面,Windows 使用 utf-16 编码格式是既定的事实,数据存储为 utf-8,调用 win32api 前就不可避免的要转换一次才可以使用,这岂不是又成了“自找不痛快”?

[此贴子已经被作者于2022-11-17 18:23编辑过]

2022-11-17 18:18
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
windows unicode字符串最常用到的是 WideCharToMultiByte、MultiByteToWideChar,可以 UTF16、UTF8 与 ANSI 互换、获取unicode字符数等
windows 的 unicode字符串 通常是用 0h0000 作结束字,但好多时是同时给出字符串buffer的size。
2022-11-17 19:28
csyx
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:29
帖 子:484
专家分:1827
注 册:2018-3-13
得分:0 
以下是引用吹水佬在2022-11-17 19:28:26的发言:

windows unicode字符串最常用到的是 WideCharToMultiByte、MultiByteToWideChar,可以 UTF16、UTF8 与 ANSI 互换、获取unicode字符数等
windows 的 unicode字符串 通常是用 0h0000 作结束字,但好多时是同时给出字符串buffer的size。

这就没意思了,如果仅为了计算unicode字符串的长度,还不如直接调用lstrlen这个api,甚至直接调用C函数库的wcslen来得更直接,又何必依赖编码转换这一对函数的副产品。但是追根究底,底层必须有支持计算字符串长度的算法,除非有一条机器指令可以完成这件事。没人会认为变长字节的编码会比定长字节编码更容易处理吧?
我只是对楼主提出的“遇到Unicode字符,应尽量地转换至UTF-8来处理”这点提出置疑。排除 web 应用,对 WinForm 的 unicode 应用来说,我认为 utf-16 就比 utf-8 更合适

其实在 vfp 板块谈论处理 unicode 本身就是费力不讨好的事,工欲善其事必先利其器,大把原生支持 unicode 的语言,咱又何必费那事儿!
2022-11-17 21:08
倦猫1973
Rank: 2
等 级:论坛游民
威 望:1
帖 子:68
专家分:28
注 册:2022-11-17
得分:0 
其实从名字就应该看得出来是什么意思了。一夜之间全面转投 unicode 是不现实的估计全世界都疯了,因此需要一个阶段慢慢平滑过渡。就以记事本为例吧,xp 还有 BOM 头,Win10 下就己经没了。
2022-11-17 21:37
cssnet
Rank: 4
等 级:业余侠客
威 望:4
帖 子:317
专家分:203
注 册:2013-10-4
得分:0 
以下是引用csyx在2022-11-17 18:18:40的发言:
用 vfp 代码实现原生函数 LenC 的 unicode 版,分别用 utf-8 和 utf-16 作为输入参数测试一下,哪种编码格式更有优势?要在 vfp 端处理 unicode 字符,有很大可能需要自己来实现这些功能


实战中,我比较偷懒,一般直接调用C库函数来处理Unicode字符。
至于传递参数,那当然是转为UTF-8更安全、更优胜!
具体到你提及的uniLenC()函数,我查了一下函数库,C实现非常简单,只是一个静态查找表和一个宏:
//-----------------------------
//定义查找表,长度256,表中的数值表示以此为起始字节的utf8字符长度
static uchar utable[] =
{
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
};
#define Ulength(x) utable[(x)]
//-----------------------------
这个C实现,可直接翻译成VFP原生代码,无任何问题的。

utf-8编码最诱人的好处是:绝不会让你遇上?? —— 但凡用VFP处理过Unicode字符的同学,相信能够明白我说的是什么。只要你传递的参数是utf-8,无论是传入还是传出,都不必担心??问题。
2022-11-17 21:38
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 7楼 csyx
WideCharToMultiByte、MultiByteToWideChar 主要是用来互相转换,同时也能返回字数,注意,是字数,不是字节数。
通式的话,就算返回给你UTF8的字数,字节数也不好猜测,只求长度什么API都不用吧。
2022-11-17 23:36



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-510673-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.070307 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved