| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
共有 438 人关注过本帖
标题:判断一个字符是否纯汉字(非标点符号、英数等)的函数
取消只看楼主 加入收藏
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
结帖率:100%
收藏
 问题点数:0 回复次数:7 
判断一个字符是否纯汉字(非标点符号、英数等)的函数
类似这种基础函数,现在习惯交给DeepSeek来写了。
不知有无遗漏?——

FUNCTION IsPureChinese(tcChar)
* 判断输入参数是否为纯汉字?
* 注:只预设两种输入参数编码:GBK或UTF-8。
LOCAL llResult, lcChar

lcChar = ALLTRIM(tcChar)

IF EMPTY(tcChar)
    RETURN .F.
ENDIF

* 自动检测编码并调用相应函数
DO CASE
    CASE LEN(lcChar) = 1    && 单字节,肯定不是汉字
        RETURN .F.
        
    CASE LEN(lcChar) = 2    && 可能是GBK编码
        lcChar = strconv(lcChar, 9)    && 将双字节字符也转换为 UTF-8
        RETURN IsUTF8Chinese(lcChar)
        
    CASE LEN(lcChar) >= 3    && 可能是UTF-8编码
        RETURN IsUTF8Chinese(lcChar)
        
    OTHERWISE
        RETURN .F.
ENDCASE
ENDFUNC

* UTF-8编码汉字判断
FUNCTION IsUTF8Chinese(tcChar)
LOCAL lnByte1, lnByte2, lnByte3, lnLen, lnUnicode

lcUnicode = strconv(tcChar, 12)    && 将 UTF-8 转换为 Unicode
* 小端序:低位在前,高位在后
lnLow = ASC(SUBSTR(tcUnicodeStr, 1, 1))
lnHigh = ASC(SUBSTR(tcUnicodeStr, 2, 1))
lnUnicode = lnHigh * 256 + lnLow
* 汉字Unicode范围:0x4E00-0x9FFF
RETURN (lnUnicode >= 0x4E00 AND lnUnicode <= 0x9FFF)
ENDFUNC



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

搜索更多相关主题的帖子: RETURN 判断 汉字 函数 编码 
昨天 14:52
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-11-17 15:11:21的发言:
汉字Unicode范围:0x4E00-0x9FFF
这个是 UTF16,不是 UTF-8 ?


没错!Deepseek在一开头偷了个懒:
lcUnicode = strconv(tcChar, 12)
其实这样是有风险的:事关,超出3字节的UTF-8,在转换成Unicode的过程中会有损。
只不过平时我也不太可能处理到4字节以上的UTF-8,睁一只眼闭一只眼,当睇唔见啦。
昨天 15:36
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用csyx在2025-11-17 16:35:56的发言:

不知你这是从哪位误人子弟的学者处抄来的
瞧瞧不用大字体都看不出差别的这哥俩,符合这扯蛋的编码范围不
? '丢',IsLeadByte('丢'), trans('丢', '@0')
? '丟',IsLeadByte('丟'), trans('丟', '@0')

大概率是把 GBK 和 GB2312 搞混了,但 GB2312 的首字节范围(0xA1-0xF7)也比它大


感谢指正!确实是我的疏忽!
代码是 DeepSeek 给的,我只看了 UTF-8(Unicode)部分,没留意到 GBK 有Bug。
当然,这函数只能针对常用汉字(即 Unicode 编码 0x4E00 ~ 0x9FA5 的20902个汉字),至于后来 Unicode 不断扩展的罕用字,搞得比较复杂,无兴致逐一去枚举。
其实 GBK 编码的Bug,解决方案也简单:

    CASE LEN(lcChar) = 2    && 可能是GBK编码
        lcChar = strconv(lcChar, 9)    && 将双字节字符也转换为 UTF-8
        RETURN IsUTF8Chinese(lcChar)
   
统一用 UTF-8(准确地说,最终是转换为Unicode)去判断即可。

补充一点:未提供容错处理,无法通用。比如说:若输入的字符参数本身就是2字节的 Unicode LE/BE,这么strconv()转来转去,全乱套了!从这一点也可以看出 UTF-8 相比 UTF-16 的优势了:
UTF-16有大尾和小尾(BE/LE)的区别;你随便输入一个2字节的字符参数,根本无法精准地确认:它究竟是ANSI?或者是 UTF-16 LE?或者是UTF-16 BE?然而,你随便输入一个 UTF-8 ,傻瓜都能立刻确认它是且仅是 UTF-8 !
昨晚 21:27
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用kangss在2025-11-17 17:22:15的发言:

“判断一个字符是否纯汉字(非标点符号、英数等)的函数”的意图是什么呢?


原本我跟 DeepSeek 讨论的是另一个问题:
输入一个汉字字符串,如何判断它是一句话,或是一段话(有两句或以上)?
考虑以下例外的情形:

我的天哪!!!
我的天哪!!!……
你难道不惭愧吗?!
你难道不惭愧吗!?

单纯依靠 OCCURS( [句末标志符号(。!?.!?)] ) ,无法准确判断汉字字符串是否有两句话以上;必须确认:在一个[句末标志符号]后边,又出现了至少一个纯汉字,才可断定它有两句或以上。
昨晚 21:47
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用csyx在2025-11-17 16:35:56的发言:
? '丢',IsLeadByte('丢'), trans('丢', '@0')
? '丟',IsLeadByte('丟'), trans('丟', '@0')


遇到一个有趣的问题——

? '丢' = 0hB6AA   && 返回值 .T.
? '丢' == 0hB6AA   && 返回值 .T.
? TRANSFORM(0hB6AA, "@0")   && 返回值 "B6AA"
? TRANSFORM('丢', "@0")   && 返回值 "丢"

这是什么原因?有没有办法,让 TRANSFORM('丢', "@0") 也返回 "B6AA" ?


翻了一下 VFP 帮助文档,原来如此——

? STRCONV('丢', 15)   && 返回值 "B6AA"
? TRANSFORM(STRCONV('丢', 15), "@0")   && 返回值 "B6AA"




[此贴子已经被作者于2025-11-17 22:47编辑过]

昨晚 22:20
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
以下是引用吹水佬在2025-11-17 22:46:19的发言:

"@0"格式对字符串?


"@0"格式对字符串,据说会直接返回原字符,不出错。

昨晚 22:49
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
有些迷乱!
试试这个:

ANSI = "丢"
Hex = STRCONV(ANSI, 15)
? Hex   && 返回:B6AA

UTF8 = STRCONV(ANSI, 9)
Hex = STRCONV(UTF8, 15)
? Hex   && 返回:E4B8A2

UNICODE = STRCONV(ANSI, 5)
Hex = STRCONV(UNICODE, 15)
? Hex   && 返回:224E

最后一个 UNICODE 的转换比较晕!因"丢"的Unicode编码是U+4E22,这大尾、小尾搞得人很迷糊;而前边两个倒是符合日常使用习惯的。
昨晚 23:35
cssnet
Rank: 5Rank: 5
等 级:职业侠客
威 望:5
帖 子:533
专家分:380
注 册:2013-10-4
收藏
得分:0 
之前我一直把 0hB6AA 当作是有些特殊的字符串,Deepseek提醒说,它是 Varbinary 类型(二进制数据),这引起了我的兴趣。一直以来,都希望能像C语言那样,可随时将字符当作数值那样处理,也就是将 0hB6AA 与 0xB6AA 互换着玩。这下子,Varbinary 类型似乎满足了我的需求!嘿嘿。
4 小时前
快速回复:判断一个字符是否纯汉字(非标点符号、英数等)的函数
数据加载中...
 
   



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

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