V
vfphome
Unregistered / Unconfirmed
GUEST, unregistred user!
假如沒有中文應用組件的朋友, Win32 中有一個 IsDBCSLeadByte 這個 API 可用, 在 Delphi 的使用示例如下:
Windows.IsDBCSLeadByte(byte(sTest[1]));
(中文應用組件中的 IsLeadByte 其實也只是呼叫這個 API 而已)
就連是不是中文字這樣簡單的問題可能都並不單純喔...., 這個問題之前被我想得有點鑽牛à尖了.... 也許原發問者寬達可以將 C 的程式借我看一下...
先來看這個例子:
procedure TForm1.Button5Click(Sender: TObject);
var
sTest: string;
begin
sTest := '中文字';
// 沒有應用組件的請用這個: Windows.IsDBCSLeadByte(byte(sTest[1]));
if IsLeadByte(@sTest[1]) then
ShowMessage('Yes 1');
if IsLeadByte(@sTest[2]) then
ShowMessage('Yes 2 ???');
end;
Yes1 顯示出來是對的, 可是 Yes2 也跑出來, 就..., 看來, 這個IsDBCSLeadByte可能只比對了一下內碼表就給結果了. 所以, 以下的程式:
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
i: integer;
begin
s := '中文字';
for i := 1 to Length(s) do
if Windows.IsDBCSLeadByte(byte(s)) then
ShowMessage(IntToStr(i) + '*' + IntToStr(Ord(s)));
end;
1. 2. 3. 4. 5. 都是 Leadbyte, 連 TrailByte 也是..., 哈哈!
當然, 這牽到中文字是 do
uble-byte, 既然只判斷一個位置不準, 就有人利用兩個字元指標, 除了本身之外, 還比較參考另一個位置的字元, 然後得出一個比較準確的結果. 有興趣的朋友可以參考中文應用組件的以下兩個函數:
function IsMBSLead( p1, p2: pchar ) : Boolean;
function IsMBSTrail( p1, p2: pchar ) : Boolean;
它們可能比較準一些.
大家可能曾注意過, Windows 95 的 EditBox 並無法以滑鼠對半個中文字作出反白選擇標記, 所以, 我自以為找到一個很慢但準確的方法, 可是以下的情形呢?
procedure TForm1.Button2Click(Sender: TObject);
{$h-}
var
sTest: string;
begin
sTest := '中文字';
ShowMessage(Copy(sTest, 2, 2));
with TEdit.Create(Self) do
begin
Parent := Self;
// Text := Copy(sTest, 2, 2);
// 1. 中?? bug
Text := sTest[2] + sTest[3];
// 2. 中?? bug
// 不要懷疑, TrailByte + 另一個字的 Leadbyte 正好是 '中'
// 不是 Copy 函數有問題
SelStart := 0;
SelLength := 2;
if SelLength = 0 then
ShowMessage('Not Chinese')
else
ShowMessage('Yes, Chinese word');
Free;
end;
end;
沒錯啦! 結果是'中'字, 判斷'中'字是中文字也對, 但是各拆一個字的前後出來組出來的結果再判斷其一個字元是不是Leadbyte, 簡直是GIGO (Garbage In Garbage Out)的典型.
說了半天, 問題被我複雜化了, 簡單的說,
1. IsDBCSLeadByte 不是一可完全可靠的函數, 中文是 do
uble-byte, 只以一個傳入字元值作判斷常常不準.
2. 要正確將各個中文字斷開的程式可能很複雜. 用兩個 pchar 來作比較, 準確性會提高一點.
只是提高一點而已, 有中文應用組件的朋友可以試試:
var
sOrigin, sTest: string;
begin
sOrigin := '中文字';
sTest := Copy(sOrigin, 4, 2);
// 變成 憒 這個怪字
if IsMBSLead(@sTest[1], @sTest[1]) then
Showmessage('Leadbyte');
end;
對的, 我又故意切開中文, 所以有人會講, 應該是 Copy(..., 3, 2)才是, 嗯! ê我怎麼知道該從哪裏開始呢?(哪裏是中文字)? 唉! 我腦筋又不清楚了...
中文應用組件有 AnsiCopy() 視中文字為一個單位, ê以下的程式呢?
var
sTest: string;
begin
sTest := '中文字';
ShowMessage(AnsiCopy(sTest, 2, 2));
sTest := #156 + '中文字';
ShowMessage(AnsiCopy(sTest, 2, 2));
// ??中憒..
end;
講了這麼多, 我的意見是: 回到原點, 除非有人故意搗蛋或者傳入的字串已經有問題, 或者ê個內碼根本沒有字, 否則只用IsDBCSLeadByte()就可以了吧.
Windows.IsDBCSLeadByte(byte(sTest[1]));
(中文應用組件中的 IsLeadByte 其實也只是呼叫這個 API 而已)
就連是不是中文字這樣簡單的問題可能都並不單純喔...., 這個問題之前被我想得有點鑽牛à尖了.... 也許原發問者寬達可以將 C 的程式借我看一下...
先來看這個例子:
procedure TForm1.Button5Click(Sender: TObject);
var
sTest: string;
begin
sTest := '中文字';
// 沒有應用組件的請用這個: Windows.IsDBCSLeadByte(byte(sTest[1]));
if IsLeadByte(@sTest[1]) then
ShowMessage('Yes 1');
if IsLeadByte(@sTest[2]) then
ShowMessage('Yes 2 ???');
end;
Yes1 顯示出來是對的, 可是 Yes2 也跑出來, 就..., 看來, 這個IsDBCSLeadByte可能只比對了一下內碼表就給結果了. 所以, 以下的程式:
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
i: integer;
begin
s := '中文字';
for i := 1 to Length(s) do
if Windows.IsDBCSLeadByte(byte(s)) then
ShowMessage(IntToStr(i) + '*' + IntToStr(Ord(s)));
end;
1. 2. 3. 4. 5. 都是 Leadbyte, 連 TrailByte 也是..., 哈哈!
當然, 這牽到中文字是 do
uble-byte, 既然只判斷一個位置不準, 就有人利用兩個字元指標, 除了本身之外, 還比較參考另一個位置的字元, 然後得出一個比較準確的結果. 有興趣的朋友可以參考中文應用組件的以下兩個函數:
function IsMBSLead( p1, p2: pchar ) : Boolean;
function IsMBSTrail( p1, p2: pchar ) : Boolean;
它們可能比較準一些.
大家可能曾注意過, Windows 95 的 EditBox 並無法以滑鼠對半個中文字作出反白選擇標記, 所以, 我自以為找到一個很慢但準確的方法, 可是以下的情形呢?
procedure TForm1.Button2Click(Sender: TObject);
{$h-}
var
sTest: string;
begin
sTest := '中文字';
ShowMessage(Copy(sTest, 2, 2));
with TEdit.Create(Self) do
begin
Parent := Self;
// Text := Copy(sTest, 2, 2);
// 1. 中?? bug
Text := sTest[2] + sTest[3];
// 2. 中?? bug
// 不要懷疑, TrailByte + 另一個字的 Leadbyte 正好是 '中'
// 不是 Copy 函數有問題
SelStart := 0;
SelLength := 2;
if SelLength = 0 then
ShowMessage('Not Chinese')
else
ShowMessage('Yes, Chinese word');
Free;
end;
end;
沒錯啦! 結果是'中'字, 判斷'中'字是中文字也對, 但是各拆一個字的前後出來組出來的結果再判斷其一個字元是不是Leadbyte, 簡直是GIGO (Garbage In Garbage Out)的典型.
說了半天, 問題被我複雜化了, 簡單的說,
1. IsDBCSLeadByte 不是一可完全可靠的函數, 中文是 do
uble-byte, 只以一個傳入字元值作判斷常常不準.
2. 要正確將各個中文字斷開的程式可能很複雜. 用兩個 pchar 來作比較, 準確性會提高一點.
只是提高一點而已, 有中文應用組件的朋友可以試試:
var
sOrigin, sTest: string;
begin
sOrigin := '中文字';
sTest := Copy(sOrigin, 4, 2);
// 變成 憒 這個怪字
if IsMBSLead(@sTest[1], @sTest[1]) then
Showmessage('Leadbyte');
end;
對的, 我又故意切開中文, 所以有人會講, 應該是 Copy(..., 3, 2)才是, 嗯! ê我怎麼知道該從哪裏開始呢?(哪裏是中文字)? 唉! 我腦筋又不清楚了...
中文應用組件有 AnsiCopy() 視中文字為一個單位, ê以下的程式呢?
var
sTest: string;
begin
sTest := '中文字';
ShowMessage(AnsiCopy(sTest, 2, 2));
sTest := #156 + '中文字';
ShowMessage(AnsiCopy(sTest, 2, 2));
// ??中憒..
end;
講了這麼多, 我的意見是: 回到原點, 除非有人故意搗蛋或者傳入的字串已經有問題, 或者ê個內碼根本沒有字, 否則只用IsDBCSLeadByte()就可以了吧.