首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 拼音首字碼檢索:漢字內碼範圍對應實作中文輸入法輔助查詢

     編輯:Delphi

前言

傳統中文檢索需輸入完整漢字,對不熟悉輸入法使用者門檻極高。利用漢字內碼 (Big5/GB) 與拼音首字母的固定對應關係,僅輸入拼音首字碼 (如「中國人民銀行」→「zgrmyh」) 即可快速檢索。本文完整實作首字碼對應表、檢索演算法、通配符支援與 Delphi 整合範例。

核心原理:Big5 內碼與拼音首字母對應

Big5 編碼中,漢字按拼音排序,同首字母漢字佔據連續內碼區間。以第一字節高位區分:

首字母內碼範圍 (十六進位)說明
A$B0A1 - $B0C4
B$B0C5 - $B2C0
C$B2C1 - $B4ED
D$B4EE - $B6E9
E$B6EA - $B7A1
F$B7A2 - $B8C0
G$B8C1 - $B9FD
H$B9FE - $BBF6
J$BBF7 - $BFA5無 I
K$BFA6 - $C0AB
L$C0AC - $C2E7
M$C2E8 - $C4C2
N$C4C3 - $C5B5
O$C5B6 - $C5BD
P$C5BE - $C6D9
Q$C6DA - $C8BA
R$C8BB - $C8F5
S$C8F6 - $CBF9
T$CBFA - $CDD9
W$CDDA - $CEF3無 U, V
X$CEF4 - $D188
Y$D1B9 - $D4D0
Z$D4D1 - $D7F9

核心函數實作


unit PinyinSearch;

interface

uses
  SysUtils, Classes;

{ 取得單一漢字的拼音首字母 (大寫)
  參數: hzchar - 兩個字元組成的 AnsiChar (Big5 雙位元組)
  回傳: 'A'..'Z' 或 #0 (非漢字) }
function GetPYIndexChar(const hzchar: string): Char;

{ 在字串列表中檢索符合拼音首字碼字串的項目
  參數:
    SourceStrs - 待檢索資料來源 (每項為完整字串)
    PYIndexStr - 檢索鍵值 (如 "zgrmyh"),支援 ? 通配符
  回傳: 符合項目以 #13 分隔的字串 }
function SearchByPYIndexStr(SourceStrs: TStrings; const PYIndexStr: string): string;

implementation

function GetPYIndexChar(const hzchar: string): Char;
var
  Code: Word;
begin
  Result := #0;
  if Length(hzchar) < 2 then Exit;
  
  // 組合 Big5 雙位元組內碼: 高位元組 * 256 + 低位元組
  Code := Word(Byte(hzchar[1])) shl 8 + Byte(hzchar[2]);
  
  case Code of
    $B0A1..$B0C4: Result := 'A';
    $B0C5..$B2C0: Result := 'B';
    $B2C1..$B4ED: Result := 'C';
    $B4EE..$B6E9: Result := 'D';
    $B6EA..$B7A1: Result := 'E';
    $B7A2..$B8C0: Result := 'F';
    $B8C1..$B9FD: Result := 'G';
    $B9FE..$BBF6: Result := 'H';
    $BBF7..$BFA5: Result := 'J';
    $BFA6..$C0AB: Result := 'K';
    $C0AC..$C2E7: Result := 'L';
    $C2E8..$C4C2: Result := 'M';
    $C4C3..$C5B5: Result := 'N';
    $C5B6..$C5BD: Result := 'O';
    $C5BE..$C6D9: Result := 'P';
    $C6DA..$C8BA: Result := 'Q';
    $C8BB..$C8F5: Result := 'R';
    $C8F6..$CBF9: Result := 'S';
    $CBFA..$CDD9: Result := 'T';
    $CDDA..$CEF3: Result := 'W';
    $CEF4..$D188: Result := 'X';
    $D1B9..$D4D0: Result := 'Y';
    $D4D1..$D7F9: Result := 'Z';
  else
    Result := #0;
  end;
end;

function SearchByPYIndexStr(SourceStrs: TStrings; const PYIndexStr: string): string;
var
  i, j: Integer;
  hzchar: string;
  Matched: Boolean;
  UpperKey: string;
begin
  Result := '';
  UpperKey := UpperCase(PYIndexStr);
  
  for i := 0 to SourceStrs.Count - 1 do
  begin
    Matched := True;
    
    // 檢查每個首字碼字元
    for j := 1 to Length(UpperKey) do
    begin
      // 取得來源字串第 j 個漢字 (雙位元組)
      if (2*j - 1 <= Length(SourceStrs[i])) and (2*j <= Length(SourceStrs[i])) then
        hzchar := SourceStrs[i][2*j - 1] + SourceStrs[i][2*j]
      else
      begin
        Matched := False;
        Break;
      end;
      
      // 通配符 ? 匹配任意首字母
      if (UpperKey[j] <> '?') and (UpperKey[j] <> GetPYIndexChar(hzchar)) then
      begin
        Matched := False;
        Break;
      end;
    end;
    
    if Matched then
    begin
      if Result = '' then
        Result := SourceStrs[i]
      else
        Result := Result + #13 + SourceStrs[i];
    end;
  end;
end;

end.

表單整合範例


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, PinyinSearch;

type
  TForm1 = class(TForm)
    EditSearch: TEdit;        // 輸入拼音首字碼
    ListBoxSource: TListBox;  // 來源資料
    ListBoxResult: TListBox;  // 檢索結果
    procedure EditSearchChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // 載入測試資料
  ListBoxSource.Items.Add('中國人民銀行');
  ListBoxSource.Items.Add('中國工商銀行');
  ListBoxSource.Items.Add('中國農業銀行');
  ListBoxSource.Items.Add('中國建設銀行');
  ListBoxSource.Items.Add('交通銀行');
  ListBoxSource.Items.Add('招商銀行');
  ListBoxSource.Items.Add('浦發銀行');
  ListBoxSource.Items.Add('民生銀行');
  ListBoxSource.Items.Add('興業銀行');
  ListBoxSource.Items.Add('光大銀行');
end;

procedure TForm1.EditSearchChange(Sender: TObject);
var
  ResultStr: string;
  List: TStringList;
begin
  ResultStr := SearchByPYIndexStr(ListBoxSource.Items, EditSearch.Text);
  
  ListBoxResult.Items.Clear;
  if ResultStr <> '' then
  begin
    List := TStringList.Create;
    try
      List.Text := ResultStr;
      ListBoxResult.Items.Assign(List);
    finally
      List.Free;
    end;
  end;
end;

end.

通配符支援說明

  • ?:匹配任意單一首字母
  • 範例:搜尋 zg?myh 可匹配 中國人民銀行 (z g r m y h) 和 中國農業銀行 (z g n y h) - 注意長度需一致
  • 實務上可擴充 * 匹配任意長度

編碼相容性注意事項

Unicode 版本改良方案


uses
  System.Character, System.SysUtils;

{ 使用 Windows API 或第三方拼音庫取得首字母 }
function GetPinyinInitial(const Ch: Char): Char;
var
  // 這裡需整合拼音庫,如:
  // 1. pinyin4delphi (開源)
  // 2. Windows IMM API: ImmGetCompositionString
  // 3. 自建 Unicode->首字母對應表 (約 2萬常用字)
begin
  // 示範:簡單判斷是否為 CJK 字元
  if Ch.IsExtended then
    Result := '?'  // 需查表
  else
    Result := UpCase(Ch);
end;

效能優化建議

  1. 預計算首字碼索引:資料載入時預先計算每筆資料的首字碼字串存入隱藏欄位,檢索時直接字串比較
  2. 使用 Trie 樹:大量資料 (萬筆以上) 建立首字碼 Trie 樹,O(m) 查找 (m=鍵長)
  3. 快取熱門查詢:LRU 快取近期查詢結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
編碼適用性處理方式
Big5 (繁體中文)完美適用原始碼直接使用
GB2312/GBK (簡體中文)內碼順序不同,不可直接用需建立 GB 專用對應表,或轉 Unicode 後查表
Unicode (Delphi 2009+)無固定內碼順序建議:轉換為拼音庫 (如 pinyin4delphi) 或使用 Windows API GetPhonetic