unicode 截取字串 |
答題得分者是:tick228
|
wangccw
一般會員 ![]() ![]() 發表:21 回覆:39 積分:17 註冊:2005-01-30 發送簡訊給我 |
在以前非 unicode 版本,我要取一個字串的前面幾個字,我會使用以下方式。
[code delphi] // @param strlength 字串長度(一個字算2byte) // @param i 0:取前半段 ,1:取後半段 function TForm1.cutMyString(str: string; strlength, i: integer): string; var frontStr: string; afterStr: string; index: integer; begin frontStr := ''; afterStr := ''; if (length(str) > 0) then begin index := 1; while (index <= length(str)) do begin if (isBig5(copy(str, index, 1)) = true) then begin if (index < strlength) then begin frontStr := frontStr + copy(str, index, 2); end else begin if (index < length(str)) then begin afterStr := afterStr + copy(str, index, 2); end; end; index := index + 2; end else begin if (index <= strlength) then frontStr := frontStr + copy(str, index, 1) else afterStr := afterStr + copy(str, index, 1); index := index + 1; end; end; end; if (i = 0) then result := frontstr; if (i = 1) then result := afterStr; end; function TForm1.isBig5(str: string): boolean; var i: integer; begin result := false; for i := 1 to length(str) do begin if (IsDBCSLeadByte(Byte(str[i])) = true) then begin result := true; break; end; end; end; procedure TForm1.Button1Click(Sender: TObject); var a : String; b : string; begin a := '住臺北市中山區八德路二段203號7樓'; b:=cutMyString(a,28,0); showmessage(b); //b 的內容 =住臺北市中山區八德路二段203 //第 28個 byte 是 "號" 的前半段,所以會不取 end; [/code] 請問到了 delphi xe 版本之後(unicode),該如何實現 cutString 同樣的結果。 是否能給個方向。 我試過使用先將 欲截取的字串轉成 ansiString 再使用 copy 方式取得,但指定取得的長度最後一個byte 若指到一半的中文字,則會變 ? 使用 System.SysUtils.ByteType 來判斷是否為中文字,總是回傳單字節,在此先謝謝各位了 備註: 1. 在 中文字一樣算 2byte。 2. 長度最後一個byte 若不是完整的中文字,就不取。 謝謝 編輯記錄
wangccw 重新編輯於 2018-01-31 03:25:57, 註解 無‧
|
tick228
高階會員 ![]() ![]() ![]() ![]() 發表:1 回覆:47 積分:104 註冊:2003-11-03 發送簡訊給我 |
unicode 裏, 不管中英數符, 每個 char 皆是兩個 byte,
所以 unicode 要取字段最簡單, 只需 Copy 就可. 例: Str := 'ABC1234中文中數字'; S := Copy(Str, 1, 4); => 'ABC1' S := Copy(Str, 6, 4); => '34中文' S := Copy(Str, 9, 4); => '文中數字' ===================引 用 wangccw 文 章=================== 在以前非 unicode 版本,我要取一個字串的前面幾個字,我會使用以下方式。 請問到了 delphi xe 版本之後(unicode),該如何實現 cutString 同樣的結果。 是否能給個方向。 我試過使用先將 欲截取的字串轉成 ansiString 再使用 copy 方式取得,但指定取得的長度最後一個byte 若指到一半的中文字,則會變 ? 使用 System.SysUtils.ByteType 來判斷是否為中文字,總是回傳單字節,在此先謝謝各位了 備註: 1. 在 中文字一樣算 2byte。 2. 長度最後一個byte 若不是完整的中文字,就不取。 謝謝 |
wangccw
一般會員 ![]() ![]() 發表:21 回覆:39 積分:17 註冊:2005-01-30 發送簡訊給我 |
謝謝 tick228 的回覆,你誤會我的意思了,我這樣問,是為了要做資料的排版。
或者說,在 unicode 下,該如何判斷每個字為"全型" 或 "半型",這樣我才能知道如何編排字串。 例如: Str := '中文字ABc數字1234夾雜其中'; 我要切成以下的結果,假設要切成每行 長度 6 ( 視覺上的每段"長度" 一致 ) 結果如下 '中文字' // ansiString 長度為 6 'ABc數' // ansiString 長度為 5 , 第6個 char為中文字 (字), 超出長度塞不進去,所以"字" 改填到第三行 '字1234' // ansiString 長度為 6 '夾雜其' //ansiString 長度為 6 '中' //ansiString 長度為 2 可以看到,我每行要 copy 的長度都不一樣,但 ansiString 長度會以 6 為主。 先謝謝了 ===================引 用 tick228 文 章=================== unicode 裏, 不管中英數符, 每個 char 皆是兩個 byte, 所以 unicode 要取字段最簡單, 只需 Copy 就可. 例: Str := 'ABC1234中文中數字'; S := Copy(Str, 1, 4); => 'ABC1' S := Copy(Str, 6, 4); => '34中文' S := Copy(Str, 9, 4); => '文中數字'
編輯記錄
wangccw 重新編輯於 2018-01-31 05:05:53, 註解 無‧
|
jcjroc
高階會員 ![]() ![]() ![]() ![]() 發表:21 回覆:279 積分:115 註冊:2002-09-18 發送簡訊給我 |
大於0xff絕對不會是英數字(ansi範圍)
===================引 用 wangccw 文 章=================== 謝謝 tick228 的回覆,你誤會我的意思了,我這樣問,是為了要做資料的排版。 或者說,在 unicode 下,該如何判斷每個字為"全型" 或 "半型",這樣我才能知道如何編排字串。 例如: Str := '中文字ABc數字1234夾雜其中'; 我要切成以下的結果,假設要切成每行 長度 6 ( 視覺上的每段"長度" 一致 ) 結果如下 '中文字' // ansiString 長度為 6 'ABc數' // ansiString 長度為 5 , 第6個 char為中文字 (字), 超出長度塞不進去,所以"字" 改填到第三行 '字1234' // ansiString 長度為 6 '夾雜其' //ansiString 長度為 6 '中' //ansiString 長度為 2 可以看到,我每行要 copy 的長度都不一樣,但 ansiString 長度會以 6 為主。 先謝謝了 ===================引 用 tick228 文 章=================== unicode 裏, 不管中英數符, 每個 char 皆是兩個 byte, 所以 unicode 要取字段最簡單, 只需 Copy 就可. 例: Str := 'ABC1234中文中數字'; S := Copy(Str, 1, 4); => 'ABC1' S := Copy(Str, 6, 4); => '34中文' S := Copy(Str, 9, 4); => '文中數字' |
tick228
高階會員 ![]() ![]() ![]() ![]() 發表:1 回覆:47 積分:104 註冊:2003-11-03 發送簡訊給我 |
原來是要列印排版, 真是誤會了~~
IsDBCSLeadByte() 只適用於 AnsiString 判斷, 要判斷 Unicode 是否為半型英數字, 可判斷 char 是否小於 #$0100, 即 if Str[i] < #$0100 then // 半型 else // 全型 ; 不過, 這種做法, 只能用於等寬字型(如 細明體, Courier New ..), 可考慮使用 Canvas.TextWidth() 一一判斷最適長度, 例: j := Length(Str); for i:= 1 to Length(Str) do if Canvas.TextWidth(Copy(Str,1,i)) > PrintWidth then begin j := i-1; Break; end; S := Copy(Str, 1, j); // 截取字串 這樣的方式, 就可不限字型. ===================引 用 wangccw 文 章=================== 謝謝 tick228 的回覆,你誤會我的意思了,我這樣問,是為了要做資料的排版。 或者說,在 unicode 下,該如何判斷每個字為"全型" 或 "半型",這樣我才能知道如何編排字串。 例如: Str := '中文字ABc數字1234夾雜其中'; 我要切成以下的結果,假設要切成每行 長度 6 ( 視覺上的每段"長度" 一致 ) 結果如下 '中文字' // ansiString 長度為 6 'ABc數' // ansiString 長度為 5 , 第6個 char為中文字 (字), 超出長度塞不進去,所以"字" 改填到第三行 '字1234' // ansiString 長度為 6 '夾雜其' //ansiString 長度為 6 '中' //ansiString 長度為 2 可以看到,我每行要 copy 的長度都不一樣,但 ansiString 長度會以 6 為主。 先謝謝了 |
wangccw
一般會員 ![]() ![]() 發表:21 回覆:39 積分:17 註冊:2005-01-30 發送簡訊給我 |
謝謝 tick228 和 jcjroc 大大的幫忙,以下是我以各位前輩說的方式作出來的簡單判斷方式
這樣即可解決我的困擾。(最主要只要知道每一個char不是英文,接下來就好好辦了) [code delphi] //判斷漢字 function TForm1.isHz(chr: wideChar): boolean; begin if ( ord(chr) > 127 ) then begin result := true; end else begin result := false; end; end; procedure TForm1.Button1Click(Sender: TObject); var str: String; i : integer; begin Str := '1,Q你好2@'; for i := 0 to Str.Length-1 do begin showmessage(booltostr( isHz(Str.Chars[i]) )); end; end; [/code] 再次謝謝各位先輩,解決我的問題 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |