希望通过本文能让大家对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应用的业务中在内存中进行快速助记码的过滤就会非常实用实例中除了汉字编码外所提供的五笔编码的汉字量还是不少的