Delphi处理汉字的问题求教!

JimmyBoy 2005-04-22 10:32:36
例如:
astr:string;
astr:='你好吗';
astr:=copy(astr,1,5);
结果astr有两个半汉字,怎么判断astr最后一个字节是半个汉字还是一个单字节字母呢?
请大侠们赐教!!!
...全文
424 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yaya82 2005-04-23
  • 打赏
  • 举报
回复
字母和数字包括一些键盘上的字符的ASCII编码都是和汉字编码有明显区别的!可以这样考虑
JimmyBoy 2005-04-23
  • 打赏
  • 举报
回复
继续请教。
SarahCla 2005-04-22
  • 打赏
  • 举报
回复
if (astr[length(astr)] and $80) then
最后一个字节就是汉字
jinjazz 2005-04-22
  • 打赏
  • 举报
回复
astr:=copy(widestring(astr),1,3);
dulei115 2005-04-22
  • 打赏
  • 举报
回复
ord(astr[length(astr)]) >= 128 最后一个字节是半个汉字
JimmyBoy 2005-04-22
  • 打赏
  • 举报
回复
多谢 unsigned(僵哥) 老大!老大留个QQ,以后常请教。

大侠的函数当Value的实参为完整的汉字字符串时没问题,但如果Value的实参最后一字节为汉字的高字节时,就会出问题。
比如这样调用,
-------------------------
var
iLen:Integer;
tmpStr:AnsiString;

tmpStr:=Copy('你好吗?',1,5);
iLen:=5;
tmpStr:=LimitStringCast(tmpStr,iLen,1);
----------------------------

则tmpStr经处理后仍未截掉最后的半个汉字。

---------------------------------------------------------------------------------------
function MyCopy(contst aStr:AnsiString;const StartPos:Integer;const StrLeng):AnsiString;
Var
wStr:WideString;
Begin
wStr:=Copy(aStr,StartPos,StrLeng)+' ';
wStr:=Copy(wStr,1,Length(wStr)-1);
Result:=AnsiString(wStr);
End;
------------------------------------------------------------------------------------
我写了上面的函数,如果字符串最后一个字节是汉字的高字节,就会跟单字节的空格组合成一个双字节的字符,然后把这个字符截掉。但不知是否一定会组合,所以不知道这个函数是否可靠。

请 unsigned(僵哥) 大侠指教。
僵哥 2005-04-22
  • 打赏
  • 举报
回复
既然不小心把C++的贴上了,那就再贴个VB的……^_^
=======================================
Private Sub Copy(ByRef Dst() As Byte, _
ByRef Src() As Byte, _
ByVal iStart As Integer, _
ByVal iLen As Integer)
Dim i As Integer
For i = 0 To iLen - 1
Dst(i) = Src(i + iStart - 1)
Next
End Sub

Function LimitStringCast(ByVal Value As String, _
ByRef LimitNum As Integer, _
Optional StartPos As Integer = 1) As String

Dim iPos As Integer
Dim iLen As Integer
Dim iLimitNum As Integer
Dim tmpStr() As Byte
Dim LimitString() As Byte

iPos = StartPos
iLen = LenB(StrConv(Value, vbFromUnicode))

If iPos > iLen Then
LimitString = ""
Exit Function
End If
If LimitNum > iLen - iPos + 1 Then LimitNum = iLen - iPos + 1
iLimitNum = LimitNum + 1
If iLimitNum > iLen - iPos + 1 Then iLimitNum = LimitNum
ReDim LimitString(LimitNum - 1)
//取得最大长度子串
Copy LimitString, StrConv(Value, vbFromUnicode), iPos, LimitNum
If iLimitNum <> LimitNum Then

ReDim tmpStr(iLimitNum - 1)
Copy tmpStr, StrConv(Value, vbFromUnicode), iPos, iLimitNum
//取得最大长度+1,用意在于判断是否最后取的是汉字的前一半
//下面是使用转换成Unicode后的字串长度来做判断的
If LenB(StrConv(tmpStr, vbUnicode)) = LenB(StrConv(LimitString, vbUnicode)) Then
//可能存在半个汉字
//最后一个是汉字的高字节,
//因为不能超最大长度,
//所以在这里宁可少取一个字符
If LimitNum > 1 Then
ReDim LimitString(LimitNum - 1)
Copy LimitString, StrConv(Value, vbFromUnicode), iPos, LimitNum - 1
End If
End If
End If
LimitStringCast = StrConv(LimitString, vbUnicode)
End Function
dongliu 2005-04-22
  • 打赏
  • 举报
回复
用midstr()取,它把汉字看成一个字符
僵哥 2005-04-22
  • 打赏
  • 举报
回复
function LimitStringCast(const Value:String;
var LimitNum:integer;
const StartPos:integer=1):string;
var
iPos:Integer;
iLen:Integer;
iLimitNum:Integer;
tmpStr:String;
begin
iPos:=StartPos;
iLen:=Length(Value);
if iPos>iLen then
begin
Result:= '';
exit;
end;
if LimitNum>iLen-iPos+1 then LimitNum:=iLen-iPos+1;
iLimitNum:=LimitNum+1;
if iLimitNum>iLen-iPos+1 then iLimitNum:=LimitNum;
Result:=Copy(Value,iPos,LimitNum);
if iLimitNum<>LimitNum then
Begin
tmpStr:=Copy(Value,iPos,iLimitNum);
if Length(WideString(tmpStr))=Length(WideString(Result)) then
begin
//¿ÉÄÜ´æÔÚ°ë¸öºº×Ö
if LimitNum>1 then Result:=Copy(Value,iPos,LimitNum-1);
end;
end;
end;
僵哥 2005-04-22
  • 打赏
  • 举报
回复
to jinjazz(近身剪(充电中...)) ( )

在处理折行时,有时是不得已而做如此断行的,当然这里面只讨论到汉字,而实际上还有标点、E文单词等等,汉字和标点(如……、——)的折行还好处理,E文单词倒需要点功夫了,在折行是用软件处理给E文单词加连接符号(-),那种处理,实在是一种难度问题。至于WideString来说,取字长度是好处,但是特别是在处理打印换行时,不得不考虑到一个E文半角字符占一个字符而汉字及全角字符占用两个字符宽度的问题。
僵哥 2005-04-22
  • 打赏
  • 举报
回复
AnsiString LimitStringCast(const AnsiString Value,int &LimitNum,const int StartPos=1)
{
AnsiString Result;
int iPos=StartPos;

int iLen=Value.Length();
if(iPos>iLen)
return "";
if(LimitNum>iLen-iPos+1)
LimitNum=iLen-iPos+1;
int iLimitNum=LimitNum+1;
if(iLimitNum>iLen-iPos+1)
iLimitNum=LimitNum;
//取得最大长度字符串
Result=Value.SubString(iPos,LimitNum);
if(iLimitNum!=LimitNum)
{
AnsiString tmpStr=Value.SubString(iPos,iLimitNum);
//取得最大长度+1,用意在于判断是否最后取的是汉字的前一半
//下面是使用转换成Unicode后的字串长度来做判断的
if(WideString(tmpStr).Length()==WideString(Result).Length())
{
//可能存在半个汉字
if(LimitNum>1)
//最后一个是汉字的高字节,
//因为不能超最大长度,
//所以在这里宁可少取一个字符
Result=Value.SubString(iPos,LimitNum-1);
}
}
return Result;
}
jinjazz 2005-04-22
  • 打赏
  • 举报
回复
为什么非要把它拆开,用widestring就可以一个个访问了
hhycqrm01 2005-04-22
  • 打赏
  • 举报
回复
先用上面的方法确定最后一个字符是汉字,再判断字符串中有多少个单个字符.
再用字符串的总长度减去字符个数除以2取余.
余数为0就是一个完整的汉字.否就是半个噻.
不过这样做有点烦麻.
JimmyBoy 2005-04-22
  • 打赏
  • 举报
回复
继续求教,
JimmyBoy 2005-04-22
  • 打赏
  • 举报
回复
谢谢楼上。但如何判断最后一个字节是汉字的第一个字节,还是第二个字节呢?
因为如果是第二个,说明汉字完整,不用处理;
如果是第一个,说明汉字只取了一半,不完整,我就把这半个汉字删掉。

继续求教!!
JimmyBoy 2005-04-22
  • 打赏
  • 举报
回复
谢谢楼上。但我如何判断最后一个字节是一个汉字的第一个字节,还是第二个字节呢?
因为如果是第二个,说明汉字完整,不用处理;
如果是第二个,说明汉字只取了一半,不完整,我就把这半个汉字删掉。

继续求教!!

16,749

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧