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

讓 TRichEdit 支援 BIG5 內碼顯示:碼表查表法完整實作

     編輯:關於C++

Foxmail 等經典軟體支援 GB/BIG5 雙內碼顯示。本文詳細記錄如何在 C++Builder 中為 TRichEdit 增加 BIG5→GB 碼表轉換功能,從碼表獲取、轉換陣列產生到即時解碼顯示完整流程。

編碼背景

  • 中文雙位元組編碼:邏輯位置 → 字庫點陣 → 顯示
  • GB 碼 (大陸) vs BIG5 碼 (台灣) 編碼不同 → 亂碼
  • BIG5 結構:高位 0x81–0xFE,低位 0x40–0x7E + 0xA1–0xFE

步驟一:獲取 BIG5→GB 碼表檔

  • 來源:CCDOS 97 附帶 CCDOS.TAB (45,840 位元組)
  • 或自行窮舉 BIG5 編碼 → 轉換工具 (地球村/東方快車) → 產出對應 GB 碼檔

步驟二:碼表檔轉 C 陣列原始碼


// TABTOHEX.cpp (Console App)
#include 
#include 
int main() {
    FILE *tab = fopen("ccdos.tab", "rb");
    FILE *hex = fopen("tab.h", "wb");
    fputs("unsigned char tab[45840]={", hex);
    for (int i = 0; i < 45840; i++) {
        if (i % 20 == 0) fputs("\n", hex);
        unsigned int ch = fgetc(tab);
        fprintf(hex, "0x%x,", ch);
    }
    fputs("0xff};", hex);
    fcloseall();
    return 0;
}

編譯執行得 tab.h,含 unsigned char tab[45840] 陣列定義。

步驟三:TRichEdit 即時 BIG5→GB 解碼


#include "tab.h"  // 包含碼表陣列

void __fastcall TForm1::Button1Click(TObject *Sender) {
    char *text = RichEdit1->Lines->GetText();  // 取得完整文字緩衝區
    unsigned long i = 0;
    while (text[i]) {
        unsigned char ch1 = text[i];
        if (ch1 >= 0xA1) {  // 可能為 BIG5 高位元組
            unsigned char ch2 = text[i+1];
            unsigned long addr;
            if (ch2 >= 0x40 && ch2 <= 0x7E) {
                addr = ch1 * 314 + ch2 * 2 - 33010;  // 區間 1 索引公式
            } else if (ch2 >= 0xA1 && ch2 <= 0xFE) {
                addr = ch1 * 314 + ch2 * 2 - 33078;  // 區間 2 索引公式
            } else {
                i++; continue;
            }
            text[i]   = tab[addr];     // GB 高位元組
            text[i+1] = tab[addr+1];   // GB 低位元組
            i += 2;
        } else {
            i++;  // ASCII 直通
        }
    }
    RichEdit1->Lines->Text = text;  // 回寫解碼後文字
    RichEdit1->SetFocus();
    RichEdit1->SelStart = 0;
}

索引公式推導

碼表線性排列:所有 BIG5 編碼按高位元組主序、低位元組次序展開

  • 低位元組區間 1 (0x40–0x7E):63 個碼位
  • 低位元組區間 2 (0xA1–0xFE):94 個碼位
  • 每高位元組總碼位 = 63 + 94 = 157
  • 區間 1 索引基礎:(hi - 0xA1) * 157 + (lo - 0x40) → 化簡得 hi*314 + lo*2 - 33010
  • 區間 2 索引基礎:(hi - 0xA1) * 157 + 63 + (lo - 0xA1) → 化簡得 hi*314 + lo*2 - 33078
  • 碼表每項 2 位元組 (GB 雙位元組),故 addr * 2 為實際位元組偏移 (程式中直接用 tab[addr] 因陣列為 unsigned char)

GB→BIG5 反向轉換

同理製作 GB→BIG5 碼表 (窮舉 GB 編碼 → BIG5 轉換工具 → 產出陣列),邏輯對稱,索引公式依 GB 編碼結構推導。

現代化建議

  • 新專案採用 Unicode (UTF-16/UTF-8) 內碼,載入時用 MultiByteToWideChar/ICU 轉換,避免雙位元組編碼地獄
  • 維護舊專案時,將碼表陣列封裝為單例類,提供 AnsiString Big5ToGb(const AnsiString&) 介面
  • 大量文字處理時,考慮 TEncoding (CB2009+) 原生支援

此碼表查表法雖屬經典,但完整展示了「編碼映射 → 線性索引 → 陣列查表 → 就地修改」的通用字碼轉換工程模式,對理解字元編碼本質極具教學價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved