拆解中文字.. |
尚未結案
|
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
想請各位大大為小弟解惑一下..
though已看過站內文章..不過還是無法解惑..
...........
ex.
有一個edit限制輸入20個byte
可有全形、半形混雜..
以下是我參考站上的範例..
......................
for i:=0 to 2 do
if i=0 then //first time
begin
test[i]:=copy(sl.text,1,20);
if (length(test[1])>=20) and (IsDBCSLeadByte(Byte(sl.text[20]))) then
test[i]:=copy(test[i],1,19)
else
test[i]:=copy(test[i],1,20);
Edit1.text:=test[i];
end ; .................
我是疑問是如果我輸入這樣的"我1e和我的我的和我的"(=20BYTE)..我的
可是如果依上述範例..這樣"的"這個字就會被載掉了
最後結果:edit1.text反而少了一個字...變成了length(18)
...請問該怎麼解決...??
thx..大大解惑.. .................................
新手多加油,加油努力中
< >< >
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
|
speedup
資深會員 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
因為MBCS系統中,中文字用兩個Byte,如果是中文字第一個Byte用IsDBCSLeadByte測試一定傳回true,但第二個Byte就不一定了
要解決這問題的笨方法就是從頭算過去,就可避免切到中文字的第二個Byte
function LimitSrtLength20(s:string):string; var i :integer; begin if length(s) > 20 then begin i := 1; while i < 20 do if IsDBCSLeadByte(Byte(s[i])) then i := i 2 else i := i 1; if (i = 20) and IsDBCSLeadByte(Byte(s[i])) then result := Copy(s,1,19) else result := Copy(s,1,20); end else result := s; end;混心雜欲 棄修身~唉 發表人 - speedup 於 2004/07/30 09:23:59
------
唉~ |
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
謝謝兩位大大的回答..
不過似乎還是有問題..
1.站長大大說用widestring..那就是把全、半形字都當作一個完整的全形字
可是我的edit(多個)每次限定一定要輸滿20個byte,除了有遇到避免切到一半全形字時才會有19個byte出現的情況..
ex."若您發表的文章中需要"(20)
"$您發表的文章中需要"(19)
2.speedup大大說的..有點不懂..
(B.)
if (i = 20) and IsDBCSLeadByte(Byte(s[i])) then
result := Copy(s,1,19)
else result := Copy(s,1,20); 上面那一段是在看i如果是全形就把i:=i 2,可是下面又設當i=20,這樣不是等於上面的就沒有作用了嗎?..還是我的理解有誤,煩請大大解惑..
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
|
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
引言: 站長大大您好.. 就像是一個跑馬燈.. 有好幾幕(好幾個edit)可以輸入.. 現在就是要開啟user已編的檔案(ex文字檔.).. 然後將文字拆解成固定長度..依序填入edit中.. thx...!這樣我就瞭解您的需求了 我覺得我還是會用WideString來寫 如 var ts:TStringList; S,s0:String; ws:widestring; i:integer; begin ts:=TStringList.create; s:='我1e和我的我的和我的我1e和我的我的和我的'; ws:=s; s0:=''; for i:=1 to length(ws) do begin if length(s0 ws[i])>20 then begin ts.add(s0); s0:=ws[i]; end else s0:=s0 ws[i]; end; ts.add(s0); ts.free; end;~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
speedup
資深會員 發表:19 回覆:259 積分:280 註冊:2003-07-04 發送簡訊給我 |
引言: if (i = 20) and IsDBCSLeadByte(Byte(s[i])) then result := Copy(s,1,19) else result := Copy(s,1,20); 上面那一段是在看i如果是全形就把i:=i 2,可是下面又設當i=20,這樣不是等於上面的就沒有作用了嗎?..還是我的理解有誤,煩請大大解惑..while 迴圈跑完後i可能為20或21(因為不管中英文i一定會切到字的第一個Byte) 如果i=21那直接Copy前20回去 如果i=20那要判斷第20位置上到底是否為中文字,若是則捨去(因為要和第21個BYTE 合併才能算是完整的中文字 MBCS系統麻煩的地方就是英文字用1Byte,中文用2Byte(含全型英文),如果處理時由前往後沒啥問題碰到IsDBCSLeadByte就往後跳兩個byte 但如果隨變中間找一個Byte,如果剛好切到中文字的第二Byte就會很難判斷 混心雜欲 棄修身~唉
------
唉~ |
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
不好意思..附上一小段我自已寫的程式.
sl.text(要拆解的來源檔)
for i:=0 to 2 do
if i=0 then //first time
test[0]:=copy(sl.text,1,20);
if (length(test[1])>=20) and (IsDBCSLeadByte(Byte(sl.text[20]))) then
test[0]:=copy(test[0],1,19)
else
test[0]:=copy(test[0],1,20);
Edit1.text:=test[0];
if i=1 then//second time
if (length(test[0]))=19 then//我想說依test[0]的長度,給予起始的位置
test[1]:=copy(sl.text,20,20); //結束的位置也會不同
if (length(test[1])>=20) and (IsDBCSLeadByte(Byte(sl.text[39]))) then
test[1]:=copy(test[1],1,19);
else
test[1]:=copy(test[1],1,20);
edit2.text:=test[1];
else if (length(test[0])=20) then//當test[0]長度是20
test[1]:=copy(sl.text,21,20);//則從21開始當edit2的開頭
if (length(test[1])>=20) and (IsDBCSLeadByte(Byte(sl.text[40]))) then
test[1]:=copy(test[1],1,19)
else
test[1]:=copy(test[1],1,20);
edit2.text:=test[1]; .............................
就是切secondtime的時候如果最後一個是全形,就會被切掉..
結果edit2就變成少一個全形字了..
so煩請大大解惑(不好意思佔版面了)
thx..
.......................
新手多加油,加油努力中
|
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
|
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
引言: 不好意思...我是個魯肉腳.. 就是 if length(s0)=20 then memo3.lines.add(s0); 這樣就可以了.. ................................. 謝謝各位大大解惑..感激不盡... ................................. 新手多加油,加油努力中 < >< > >>< face="Verdana, Arial, Helvetica"> 很好 您自己也有努力喔 if length(s0)=20 then 這樣還是會有問題 有時候一個Edit可能只能裝19個Byte因為下一個是中文 只得輸出到下一個Edit 我想您應該如此寫比較好var ts:TStringList; S,s0:String; ws:widestring; i:integer; begin ts:=TStringList.create; s:='我1e和我的我的和我的我1e和我的我的和我的'; ws:=s; s0:=''; for i:=1 to length(ws) do begin if length(s0 ws[i])>20 then begin ts.add(s0); s0:=ws[i]; end else s0:=s0 ws[i]; end; ts.add(s0); edit1.text:=ts[0]; edit2.text:=ts[1]; edit3.text:=ts[2]; ts.free; end;~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
rest
一般會員 發表:5 回覆:23 積分:5 註冊:2004-05-12 發送簡訊給我 |
哈..真地太謝謝站長大大熱心地幫我解惑..(speedup大大也是..)
.........
我本來還想說把19和20的都先存在陣列裡,
然後如果20有出現過(和19一樣的,只有最後一個字不一樣)
再把19的那個delete...
和站長大大的比起來..實在是太..< >..
..........................................
哈..真的太謝謝各位前輩了.. .............................................
新手多努力,努力加油中
< >< >< >
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |