| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 1187 人关注过本帖
标题:判断一个字符是否纯汉字(非标点符号、英数等)的函数
只看楼主 加入收藏
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:544
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-11-19 09:52:39的发言:

RETURN (lnUnicodeBE >= 0x4E00 AND lnUnicodeBE <= 0x9FFF)
RETURN BETWEEN(tcChar,0hE4B880,0hE9BFBF)
这两句有本质上的差别吗?


大佬啊,区别不在这一句!区别在:
lcUnicodeLE = strconv(tcChar, 12)
输入的3字节字符(它有可能是正确的 utf-8 ,也有可能是乱码,或别的任意东东……)尝试转换至 unicode ,那么,无效字符、伪UTF-8字符会在此处被自动过滤,转换不出 0x4E00--0x9FFF 之间的纯汉字 Unicode 来。
这也就是我所说的“其主要副作用是,自动验证utf-8字符参数的有效性”含义。
若自己写,在函数最前边可能应逐字节验证一下掩码,确保输入的参数是正确的 UTF-8 编码:

lnByte1 = ASC(SUBSTR(tcChar, 1, 1))
lnByte2 = ASC(SUBSTR(tcChar, 2, 1))
lnByte3 = ASC(SUBSTR(tcChar, 3, 1))

* 验证UTF-8编码有效性
IF (lnByte1 >= 0xE4 AND lnByte1 <= 0xE9) AND ;
   (lnByte2 >= 0x80 AND lnByte2 <= 0xBF) AND ;
   (lnByte3 >= 0x80 AND lnByte3 <= 0xBF)
   ...

10 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
回复 31楼 cssnet
你睇D吾睇D,我说的是有前提的:RETURN BETWEEN(tcChar,0hE4B880,0hE9BFBF)    && 假设tcChar是3字节UTF-8字符
“假设tcChar是3字节UTF-8字符”就是省略了判断UTF-8的汉字前提条件,本质上与strconv(tcChar, 12)一样,只是省略了。
因为重点是说 RETURN BETWEEN(tcChar,0hE4B880,0hE9BFBF) 这句,不用从机内码(0h)到字符码(0x)转来转去。
直接从机内码(0h)判断是否为3字节UTF-8也不麻烦。

9 小时前
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:544
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-11-19 10:47:37的发言:

你睇D吾睇D,我说的是有前提的:RETURN BETWEEN(tcChar,0hE4B880,0hE9BFBF)    && 假设tcChar是3字节UTF-8字符
“假设tcChar是3字节UTF-8字符”就是省略了判断UTF-8的汉字前提条件,本质上与strconv(tcChar, 12)一样,只是省略了。
因为重点是说 RETURN BETWEEN(tcChar,0hE4B880,0hE9BFBF) 这句,不用从机内码(0h)到字符码(0x)转来转去。
直接从机内码(0h)判断是否为3字节UTF-8也不麻烦。


回到顶楼:

    CASE LEN(lcChar) >= 3    && 可能是UTF-8编码
        RETURN IsUTF8Chinese(lcChar)

按你的代码简洁性喜好,甚至还可以缩减为:

    CASE LEN(lcChar) >= 3    && 可能是UTF-8编码
        RETURN BETWEEN(lcChar,0hE4B880,0hE9BFBF)  && c1 = 0hE5FFF0,它也return .T.啊!

可是——重点是这个可是——我们只是在数字节,数到3,猜测它有可能是UTF-8编码,接下来,似乎有必要确认一下,验证一下:它“确实是、肯定是”,而非“可能是”;你这是完全寄希望于调用者的人品啊?




[此贴子已经被作者于2025-11-19 11:14编辑过]

9 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
IF (lnByte1 >= 0xE4 AND lnByte1 <= 0xE9) AND ;
   (lnByte2 >= 0x80 AND lnByte2 <= 0xBF) AND ;
   (lnByte3 >= 0x80 AND lnByte3 <= 0xBF)
这个不就是“纯汉字”的3bytes的UTF-8吗?

lcUnicodeLE = strconv(tcChar, 12)    && 将 UTF-8 转换为 Unicode
lcUnicodeBE = RIGHT(lcUnicodeLE, 1) + LEFT(lcUnicodeLE, 1)
这两句是将整个字符串转为Unicode,再取首尾字节。
问题:整个UTF-8字符串中含有不是“汉字”(如常见的NULL或换行等)需要考虑吗?是否有一定的局限性。
8 小时前
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:544
专家分:380
注 册:2013-10-4
收藏
得分:0 
哈哈哈哈,这个小问题,讨论到此,有些钻牛角尖啦。打住打住。
VFP在0h与字符之间转换,始终需借助函数STRCONV(C, 15)和EVALUATE();另,0h还有个大、小端序的问题,这可能会是一个陷阱。
若确实不想在0h与0x之间反复切换,或许我们也可以尝试强行直接进行0h比较:

* UTF-8编码汉字判断
FUNCTION IsUTF8Chinese(tcChar)
lcUnicodeLE = strconv(tcChar, 12)    && 将 UTF-8 转换为 Unicode
lcUnicodeBE = substr(lcUnicodeLE, 2, 1) + LEFT(lcUnicodeLE, 1)
l0hUnicodeBE = EVALUATE("0h" + STRCONV(lcUnicodeBE, 15))
RETURN BETWEEN(lcUnicodeBE, 0h4E00, 0h9FFF)
ENDFUNC


[此贴子已经被作者于2025-11-19 12:52编辑过]

7 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
大端小端,如果不是跨平台跨设备的数据处理,一般0h是相对固定的。
如果没必要,0h与0x之间不用切换。
如:
内码形式:0h4E00, 0h9FFF
数值形式:0x004E, 0xFF9F
这不是大端小端问题,是同一数据的不同表达形式,实质是一样的。
如果同一数据有两种表现情况:0h4E00 或 0h004E,就有可能是大端小端问题。



6 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
以下是引用cssnet在2025-11-19 12:49:31的发言:

* UTF-8编码汉字判断
FUNCTION IsUTF8Chinese(tcChar)
lcUnicodeLE = strconv(tcChar, 12)    && 将 UTF-8 转换为 Unicode
lcUnicodeBE = substr(lcUnicodeLE, 2, 1) + LEFT(lcUnicodeLE, 1)
l0hUnicodeBE = EVALUATE("0h" + STRCONV(lcUnicodeBE, 15))
RETURN BETWEEN(lcUnicodeBE, 0h4E00, 0h9FFF)
ENDFUNC

lcUnicodeBE = substr(lcUnicodeLE, 2, 1) + LEFT(lcUnicodeLE, 1)
这一句实质就是只考虑字符串转为Unicode后的前两个字节,为何要转换整个字符串?
vfp的 ISLEADBYTE() 也只是考虑第一个字符的第一个字节。UTF-8汉字应是第一个字符的3个字节。

[此贴子已经被作者于2025-11-19 14:27编辑过]

5 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
以下是引用cssnet在2025-11-19 12:49:31的发言:

VFP在0h与字符之间转换,始终需借助函数STRCONV(C, 15)和EVALUATE();
若确实不想在0h与0x之间反复切换,或许我们也可以尝试强行直接进行0h比较:


试试:
程序代码:
FUNCTION IsUTF8Chinese(tcChar)
    LOCAL bytes
    bytes = LEFT(tcChar,3)
    RETURN LEN(bytes)==3 AND;
        BETWEEN(SUBSTR(bytes,1,1),0hE4,0hE9) AND;
        BETWEEN(SUBSTR(bytes,2,1),0h80,0hBF) AND;
        BETWEEN(SUBSTR(bytes,3,1),0h80,0hBF) 
ENDFUNC
5 小时前
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:451
帖 子:10882
专家分:43494
注 册:2014-5-20
收藏
得分:0 
以下是引用吹水佬在2025-11-19 14:38:43的发言:


试试:

FUNCTION IsUTF8Chinese(tcChar)
    LOCAL bytes
    bytes = LEFT(tcChar,3)
    RETURN LEN(bytes)==3 AND;
        BETWEEN(SUBSTR(bytes,1,1),0hE4,0hE9) AND;
        BETWEEN(SUBSTR(bytes,2,1),0h80,0hBF) AND;
        BETWEEN(SUBSTR(bytes,3,1),0h80,0hBF)
ENDFUNC

UTF-16 汉字编码机内码核心范围是 0h004E ~ 0hFF9F,转UTF-8应该是 0hE4B880 ~ 0hE9BFBF
程序代码:
FUNCTION IsUTF8Chinese(tcChar)
    LOCAL bytes
    bytes = LEFT(tcChar,3)
    RETURN LEN(bytes)==3 AND;
        BETWEEN(SUBSTR(bytes,1,1),0hE4,0hE9) AND;
        BETWEEN(SUBSTR(bytes,2,1),0hB8,0hBF) AND;
        BETWEEN(SUBSTR(bytes,3,1),0h80,0hBF) 
ENDFUNC


5 小时前
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:544
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-11-19 14:58:54的发言:
UTF-16 汉字编码机内码核心范围是 0h004E ~ 0hFF9F...


我老人家算术唔好,可你也不带这样子糊弄我噻!

0x9FFF - 0x4E00 = 0x51FF = 20991
0xFF9F - 0x004E = 0xFF51 = 65361

相差3倍有多咧,大佬!
5 小时前
快速回复:判断一个字符是否纯汉字(非标点符号、英数等)的函数
数据加载中...
 
   



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

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019425 second(s), 10 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved