希望通過本文能讓大家對C#如何快速獲取助記碼有更深刻的了解CTO也向您推薦《C#實用基礎教程》
本文實現
以犧牲空間為代價方便快速地實現漢字的助記碼獲取
針對拼音特性實現多音字並提供顯式地姓氏調用方法
網上關於使用C#取助記碼的方法很多不過一般都是采用將每一個碼有哪些漢字的方法來實現助記碼的轉換它的缺點是顯而易見的
相當於本來應該存放在數據庫或者是外部的數據存放到程序中
利用字符串的定位功能性能上也不一定好
在線性表中我們查找指定位置結點的數據是最快的比如一個包含個元素的線性表中無論直接訪問哪一個位置的數據值只要根據表的第一個位置就可以直接定位到第個元素的位置數組也是一種簡單有效的線性表需要某個項目只要通過編移量即可搞定
在不使用數據庫直接使用文件做資源方便配置完成中文到助記碼的的轉換同時針對拼音助記碼還要實現多音字詞組匹配姓氏專用方法
同時五筆碼四角碼等多種類別也易如反掌雖然在以犧牲空間為代價但用空間換得時間的性能提高還是非常值得的
數據存放使用數組
數組就是一種線性表我們的解決思路是
每一個項目對應一個結構它包括漢字拼音碼是否多音字五筆碼(或其它更多編碼)
每一個漢字直接轉換成一個數字編碼(ASCII或者是UNICODE)數字就是數組下標
讀取文字串根據每一個漢字取得數字直接定位數組中的位置取得編碼
因此我們定義用於存放漢字的助記簡碼的結構(有更多編碼只要在結構上擴充即可)
private struct ItemWord
{
public int numFlag;
//是否多音字 public char strWord;
//當前單詞 public string strSpell;
//輸入碼 public string strSpell;
//輸入碼 public string strExt;
//多音字保留串 public string strName;
//用於定義姓氏碼
加載助記碼字典
由於要支持拼音及多音字也支持五筆的助記碼為了例子方便編碼表都暫時存放在d:\myword下下面以拼音碼的加載為例首先初始化Itemword中的每一個項目通常情況下GBK的實際漢字數應該在字左右從雙字節的角度來看最多也就只有K因此把我們的數組定義為K即
private static readonly int INTMAX = ; private ItemWord[] stWord = new ItemWord[INTMAX];
在函數fun_LoadWord中拼音碼hzpytxt的加載方法
while ((strInput = srFileReadLine()) != null)
{
chrWord = strInputToCharArray();
numIndex = (int)chrWord[];
stWord[numIndex]strWord = chrWord[];
stWord[numIndex]strSpell = chrWord[]ToString();
注意其中最最關鍵是把讀取的內容轉成char的數組再通過(int)chrWord[]把它轉換為一個數組的下標值(這個相對來說C就簡單許多)再把相應內容填到數組中此下標項目對於五筆碼的讀取方法也一致非常簡單(更多的其它編碼也不在話下)不過拼音碼的多音存儲需要介紹一下實際上對於漢字來說單音是大多數只有少部分才是多音字為了結構更簡單把多音字是存放在相應的漢字結構中即
numIndex = (int)chrWord[];
strInput = strInputSubstring();
strInput = strInputReplace(\t );
strInput = strInputReplace( /);
stWord[numIndex]strExt = stWord[numIndex]strExt + strInput + |;
最終strExt中的結構內容是|曾哥/Z|的格式它的好處會在多音碼的展現時進行說明
從漢字到簡碼
我們先舉例五筆的助記碼實現對傳入的漢字串來說只要提取每一個漢字得到對應的字符編碼再直接提取其對應編碼由於直接采用下標取得編碼而數據又加載在內存數組中可以用飛速來描述它
chrWord = strChineseToCharArray();
numCount = strChineseLength;
for (i = ; i < numCount; i++)
{
numIndex = (int)chrWord[i];
strSpell = strSpell + stWord[numIndex]strSpellToString();
拼音碼則存在著幾個主要問題一個是姓氏還有一個是多音字多音字的實現通過詞組模式來處理即首先它是一個多音字即結構中的numFlag標志同時根據漢字串往前往後追蹤一個形成詞組例如曾哥它雖然來源於姓氏但是本身已經形成一個受眾很廣的詞在hzpytxt中定義曾 曾哥 Z這樣一行內容在多音字時我們用函數funFindMulti來定位多音字的編碼
strWord = | + ch + ch + /; numPos = stWord[numIndex]strExtIndexOf(strWord);
if (numPos >= ) return stWord[numIndex]strExtSubstring(numPos + strWordLength );
也就是說但我們定位漢字曾時首先它是一個多音字再根據詞組曾哥對應的編碼
我們把用於定位的詞組形成前綴|詞組/的格式假定有多個多音時可以通過唯一位置定位後再取得此串後面的字符即Z所以當我們輸入信曾哥得自信時得到拼音助記碼自然就是XZGDZX了因為姓氏的特殊性並且實際業務中比較明確地知道當前的內容是否是姓名即我們顯式調用而姓名中也只有在首字時才發生按姓的讀音只要調用參數提供是否姓名的開關(下面的變量IsName為了文章方便緊湊格式了)即可
if (stWord[numIndex]numFlag > && !IsName){if (i > )
strThis = funFindMulti(numIndex chrWord[i ] chrWord[i]);
if (strThisLength == && i < numCount )
strThis = funFindMulti(numIndex chrWord[i] chrWord[i + ]);
}
if (IsName && i == && stWord[numIndex]strNameLength > )strThis = stWord[numIndex]strName;
if (strThisLength == )strThis = stWord[numIndex]strSpellToString();
strSpell = strSpell + strThis;
當所輸入的是單個的姓名時我們只處理首漢字比如金庸的原名
對於姓名之後是否按詞組處理比如張長春這樣的人如果指定為姓名可能叫ZZC也可能叫ZCC這個很難說所以在某種程度上我們解決多音字只能說是處理多音字中的%問題還是可以接受的而且在實際業務中像我們這些人參他一本這樣的字串是不會在數據字典中出現的最後看看多單字中有典型意義的單字在三種模式下的效果吧
這樣我們不僅可以快速處理多音字也同時處理了多個助記碼的實現在非WEB應用的業務中在內存中進行快速助記碼的過濾就會非常實用實例中除了漢字編碼外所提供的五筆編碼的漢字量還是不少的
From:http://tw.wingwit.com/Article/program/net/201311/11796.html