VC 获取汉字拼音首字母(unicode编码)上

    最近要做一个根据汉字取拼音的首字母进行查询的电话簿项目,网上关于这方面的资料很多,因为是基于wince开发的,需要将unicode编码转换成ansi编码,将源码贴于此,希望对网友有用。

//若含有非汉字的字符要保留
CString GetFirstLetter(LPCTSTR strName)
{
	static int li_SecPosValue[] = {
		1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212,
		3472, 3635, 3722, 3730, 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249
	};
	static char* lc_FirstLetter[] = {
		"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "O",
		"P", "Q", "R", "S", "T", "W", "X", "Y", "Z"
	};
	static char* ls_SecondSecTable =
		"CJWGNSPGCGNE[Y[BTYYZDXYKYGT[JNNJQMBSGZSCYJSYY[PGKBZGY[YWJKGKLJYWKPJQHY[W[DZLSGMRYPYWWCCKZNKYYGTTNJJNYKKZYTCJNMCYLQLYPYQFQRPZSLWBTGKJFYXJWZLTBNCXJJJJTXDTTSQZYCDXXHGCK[PHFFSS[YBGXLPPBYLL[HLXS[ZM[JHSOJNGHDZQYKLGJHSGQZHXQGKEZZWYSCSCJXYEYXADZPMDSSMZJZQJYZC[J[WQJBYZPXGZNZCPWHKXHQKMWFBPBYDTJZZKQHY"
		"LYGXFPTYJYYZPSZLFCHMQSHGMXXSXJ[[DCSBBQBEFSJYHXWGZKPYLQBGLDLCCTNMAYDDKSSNGYCSGXLYZAYBNPTSDKDYLHGYMYLCXPY[JNDQJWXQXFYYFJLEJPZRXCCQWQQSBNKYMGPLBMJRQCFLNYMYQMSQYRBCJTHZTQFRXQHXMJJCJLXQGJMSHZKBSWYEMYLTXFSYDSWLYCJQXSJNQBSCTYHBFTDCYZDJWYGHQFRXWCKQKXEBPTLPXJZSRMEBWHJLBJSLYYSMDXLCLQKXLHXJRZJMFQHXHWY"
		"WSBHTRXXGLHQHFNM[YKLDYXZPYLGG[MTCFPAJJZYLJTYANJGBJPLQGDZYQYAXBKYSECJSZNSLYZHSXLZCGHPXZHZNYTDSBCJKDLZAYFMYDLEBBGQYZKXGLDNDNYSKJSHDLYXBCGHXYPKDJMMZNGMMCLGWZSZXZJFZNMLZZTHCSYDBDLLSCDDNLKJYKJSYCJLKWHQASDKNHCSGANHDAASHTCPLCPQYBSDMPJLPZJOQLCDHJJYSPRCHN[NNLHLYYQYHWZPTCZGWWMZFFJQQQQYXACLBHKDJXDGMMY"
		"DJXZLLSYGXGKJRYWZWYCLZMSSJZLDBYD[FCXYHLXCHYZJQ[[QAGMNYXPFRKSSBJLYXYSYGLNSCMHZWWMNZJJLXXHCHSY[[TTXRYCYXBYHCSMXJSZNPWGPXXTAYBGAJCXLY[DCCWZOCWKCCSBNHCPDYZNFCYYTYCKXKYBSQKKYTQQXFCWCHCYKELZQBSQYJQCCLMTHSYWHMKTLKJLYCXWHEQQHTQH[PQ[QSCFYMNDMGBWHWLGSLLYSDLMLXPTHMJHWLJZYHZJXHTXJLHXRSWLWZJCBXMHZQXSDZP"
		"MGFCSGLSXYMJSHXPJXWMYQKSMYPLRTHBXFTPMHYXLCHLHLZYLXGSSSSTCLSLDCLRPBHZHXYYFHB[GDMYCNQQWLQHJJ[YWJZYEJJDHPBLQXTQKWHLCHQXAGTLXLJXMSL[HTZKZJECXJCJNMFBY[SFYWYBJZGNYSDZSQYRSLJPCLPWXSDWEJBJCBCNAYTWGMPAPCLYQPCLZXSBNMSGGFNZJJBZSFZYNDXHPLQKZCZWALSBCCJX[YZGWKYPSGXFZFCDKHJGXDLQFSGDSLQWZKXTMHSBGZMJZRGLYJB"
		"PMLMSXLZJQQHZYJCZYDJWBMYKLDDPMJEGXYHYLXHLQYQHKYCWCJMYYXNATJHYCCXZPCQLBZWWYTWBQCMLPMYRJCCCXFPZNZZLJPLXXYZTZLGDLDCKLYRZZGQTGJHHGJLJAXFGFJZSLCFDQZLCLGJDJCSNZLLJPJQDCCLCJXMYZFTSXGCGSBRZXJQQCTZHGYQTJQQLZXJYLYLBCYAMCSTYLPDJBYREGKLZYZHLYSZQLZNWCZCLLWJQJJJKDGJZOLBBZPPGLGHTGZXYGHZMYCNQSYCYHBHGXKAMTX"
		"YXNBSKYZZGJZLQJDFCJXDYGJQJJPMGWGJJJPKQSBGBMMCJSSCLPQPDXCDYYKY[CJDDYYGYWRHJRTGZNYQLDKLJSZZGZQZJGDYKSHPZMTLCPWNJAFYZDJCNMWESCYGLBTZCGMSSLLYXQSXSBSJSBBSGGHFJLYPMZJNLYYWDQSHZXTYYWHMZYHYWDBXBTLMSYYYFSXJC[DXXLHJHF[SXZQHFZMZCZTQCXZXRTTDJHNNYZQQMNQDMMG[YDXMJGDHCDYZBFFALLZTDLTFXMXQZDNGWQDBDCZJDXBZGS"
		"QQDDJCMBKZFFXMKDMDSYYSZCMLJDSYNSBRSKMKMPCKLGDBQTFZSWTFGGLYPLLJZHGJ[GYPZLTCSMCNBTJBQFKTHBYZGKPBBYMTDSSXTBNPDKLEYCJNYDDYKZDDHQHSDZSCTARLLTKZLGECLLKJLQJAQNBDKKGHPJTZQKSECSHALQFMMGJNLYJBBTMLYZXDCJPLDLPCQDHZYCBZSCZBZMSLJFLKRZJSNFRGJHXPDHYJYBZGDLQCSEZGXLBLGYXTWMABCHECMWYJYZLLJJYHLG[DJLSLYGKDZPZXJ"
		"YYZLWCXSZFGWYYDLYHCLJSCMBJHBLYZLYCBLYDPDQYSXQZBYTDKYXJY[CNRJMPDJGKLCLJBCTBJDDBBLBLCZQRPPXJCJLZCSHLTOLJNMDDDLNGKAQHQHJGYKHEZNMSHRP[QQJCHGMFPRXHJGDYCHGHLYRZQLCYQJNZSQTKQJYMSZSWLCFQQQXYFGGYPTQWLMCRNFKKFSYYLQBMQAMMMYXCTPSHCPTXXZZSMPHPSHMCLMLDQFYQXSZYYDYJZZHQPDSZGLSTJBCKBXYQZJSGPSXQZQZRQTBDKYXZK"
		"HHGFLBCSMDLDGDZDBLZYYCXNNCSYBZBFGLZZXSWMSCCMQNJQSBDQSJTXXMBLTXZCLZSHZCXRQJGJYLXZFJPHYMZQQYDFQJJLZZNZJCDGZYGCTXMZYSCTLKPHTXHTLBJXJLXSCDQXCBBTJFQZFSLTJBTKQBXXJJLJCHCZDBZJDCZJDCPRNPQCJPFCZLCLZXZDMXMPHJSGZGSZZQLYLWTJPFSYASMCJBTZKYCWMYTCSJJLJCQLWZMALBXYFBPNLSFHTGJWEJJXXGLLJSTGSHJQLZFKCGNNNSZFDEQ"
		"FHBSAQTGYLBXMMYGSZLDYDQMJJRGBJTKGDHGKBLQKBDMBYLXWCXYTTYBKMRTJZXQJBHLMHMJJZMQASLDCYXYQDLQCAFYWYXQHZ";
	//将unicode编码转换成ANSI编码
	int nSecondSecTable = strlen(ls_SecondSecTable);
	int stringlen = wcslen(strName);
	char   *buffer = NULL;   
	buffer = new char[stringlen * sizeof(TCHAR) + 1]; 
	ZeroMemory(buffer, stringlen * sizeof(TCHAR) + 1);
	WideCharToMultiByte(CP_ACP,NULL,strName,stringlen,buffer,stringlen * sizeof(TCHAR) + 1,NULL,NULL);
	//
	string result;
	int nHigh, nLow, nCode;
	int i,j;
	for (i = 0; i < stringlen*sizeof(TCHAR); i++)
	{
		//找到汉字的机内码
		nHigh = (UCHAR) (buffer[i + 0]);
		nLow = (UCHAR) (buffer[i + 1]);

		if (nHigh < 0xA1 || nLow < 0xA1)    //非汉字保留
		{
			result += buffer[i];
			continue;
		} 
		else 
		{
			//一级汉字机内码与区位码的关系
			//机内码高字节 = 区码 + 0XA0;
			//机内码低字节 = 位码 + 0XA0;
			//区位码 = (机内码高字节 - 0XA0) * 100 + 机内码低字节 - 0XA0;
			nCode = (nHigh - 0XA0) * 100 + nLow - 0XA0;
		}

		if (nCode > 1600 && nCode < 5590)       //一级汉字 16-55区    
		{
			for (j = 22; j >= 0; j--)
			{
				if (nCode >= li_SecPosValue[j])
				{
					result += lc_FirstLetter[j];
					i ++;
					break;
				}
			}

			continue;
		} 
		else  //二级汉字通过查表  56-87区;将二级汉字拼音的首字母放在ls_SecondSecTable表中
		{
			i++;
			//根据机内码转换成ls_SecondSecTable表的下标
			nCode = (nHigh - 0XA0 - 56) * 94 + nLow - 0XA0 - 1; 
			if (nCode >= 0 && nCode < nSecondSecTable)
				result += ls_SecondSecTable[nCode];
			else 
			{
				result += (char) nHigh;
				result += (char) nLow;
			}
		}
	} 

	//将ANSI编码转换成unicode编码
	TCHAR *pwcsTemp = new TCHAR[stringlen+1];
	ZeroMemory(pwcsTemp, (stringlen+1) * sizeof(TCHAR));

	MultiByteToWideChar(CP_ACP,NULL,result.c_str(),result.length(),pwcsTemp,stringlen);
	CString str = pwcsTemp;
	//
	delete []pwcsTemp;
	pwcsTemp = NULL;

	delete []buffer;
	buffer = NULL;

	return str;
}

不足之处就是对多音字,无法区分,如东莞 DW,莞尔 WE。

 

附录:汉字编码原则
1.国家标准汉字代码体系
  汉字字数繁多,属性丰富,因而汉字代码体系也较复杂,包括:
  (1)汉字机内码。它们是汉字在计算机汉字系统内部的表示方法,是计算机汉字系统
的基础代码。
  (2)汉字交换码。它们是国标汉字(如机内码)进行信息交换的代码标准。
  (3)汉字输入码。它们是在计算机标准键盘上输入汉字用到的各种代码体系。
  (4)汉字点阵码。它们是在计算机屏幕上显示和在打印机上打印输出汉字的代码体系。
  (5)汉字字形控制码。为了打印各种风格的字体和字形所制定的代码。
  这些代码系统有的必须有统一的国家标准,有的则不要求统一。近年来我国已经制定
系列汉字信息处理方面的国家标准,今后将继续完善,并与国际上求得统一。

2. 国家标准汉字交换码
  我国制定了"中华人民共和国国家标准信息交换汉字编码",标准代号为GB2312―80,
这种编码又称为国标码。在国标码的字符集中共收录了一级汉字3755个,二级汉字3008
个,图形符号682个,三项字符总计7445个。
  在国标GD2312―80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,
方阵的每一行称为一个"区",编号为01区到94区,每一列称为一个"位",编号为01
位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯
数字就是它们的"区位码"。区位码的前两位是它的区号,后两位是它的位号。用区位码
就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一
的区位码。汉字"母"字的区位码是3624,表明它在方阵的36区24位,问号"?"的区
位码为0331,则它在03区3l位。
  所有的汉字和符号所在的区分为以下四个组:
    (1)01区到15区。图形符号区,其中01区到09区为标准符号区,10区到15区为
自定义符号区。
  01区到09区的具体内容如下;
  1)01区。一般符号202个,如间隔符、标点、运算符、单位符号及制表符;
  2)02区。序号60个,如1.~20.、(1)~(20)、①~⑩及(一)~(十);
  3)03区。数字22个,如0―9及X一XII,英文字母52个,其中大写A―Z、小写
a―z各26个;
  4)04区。日文平假名83个;
  5)05区。日文片假名86个;
  6)06区。希腊字母48个;
  7)07区。俄文字母66个;
  8)08区。汉语拼音符号a―z26个;
  9)09区。汉语拼音字母37个。
    (2)16区到55区。一级常用汉字区,包括了3755个一统汉字。这40个区中的汉字
是按汉语拼音排序的,同音字按笔划顺序排序。其中55区的90一94位未定义汉字。
    (3)56区到87区。二级汉字区,包括了3008个二级汉字,按部首排序。
    (4)88区到94区。自定义汉字区。
    第10区到第15区的自定义符号区和第88区到第94区的自定义汉字区可由用户自行
  定义国标码中未定义的符号和汉字。

3. 国家标准汉字机内码
    汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上
所述,汉字区位码的区码和位码的取值均在1~94之间,如直接用区位码作为机内码,就
会与基本ASCII码混淆。为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII码
中的控制码(00H~1FH),还需与基本ASCII码中的字符相区别。为了实现这两点,可以
先在区码和位码分别加上20H,在此基础上再加80H(此处"H"表示前两位数字为十六
进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别  称为高位字
节和低位字节,这两位字节的机内码按如下规则表示:
    高位字节=区码+20H+80H(或区码+A0H)
    低位字节=位码+20H+80H(或位码+AOH)
    由于汉字的区码与位码的取值范围的十六进制数均为01H~5EH(即十进制的01~94),
  所以汉字的高位字节与低位字节的取值范围则为A1H~FEH(即十进制的161~254)。
    例如,汉字"啊"的区位码为1601,区码和位码分别用十六进制表示即为1001H,它
的机内码的高位字节为B0H,低位字节为A1H,机内码就是B0A1H。 

4. 汉字的输入码
    在计算机标准键盘上,汉字的输入和西文的输入有很大的不同。西文的输入,击一次
键就直接输入了相应的字符或代码,"键入"和"输入"是同一个含义。但是在计算机上
进行汉字输入时,"键入"是指击键的动作即键盘操作的过程,而"输入"则是把所需的
汉字或字符送到指定的地方,是键盘操作的目的。目前已有多种汉字输入方法,因此就有
多种汉字输入码。汉字输入码是面向输入者的,使用不同的输入码其操作过程不同,但是
得到的结果是一样的。不管采用何种输入方法,所有输入的汉字都以机内码的形式存储在
介质中,而在进行汉字传输时,又都以交换码的形式发送和接收。
    国标GB2312―80规定的区位码和沿用多年的电报码都可以作为输入码。这类汉字编码
和输入码是一一对应的,具有标准的性质,它们编码用的字符是10个阿拉伯数字,每个
汉字的码长均为等长的四个数码。
    其他编码的种类很多,可从以下几点加以讨论:
    (2)编码类型。可分为拼音码、字形码、音形结合码等类型。
    (2)编码规则。不同的编码方案有很大的不同,有的规则简单,学习起来较容易记忆,'
  有的规则复杂,较难记亿。
    (3)编码字符集。有用字母键的,有用数字键的,有用字母键加数字键的,或者用了
  更多的键作编码字符集的。
    (4)编码长度。它与编码字符集的大小有关,字符集越大,编码长度越短。采用26
  个字母的编码,其码长一般为四位。
    (5)对应关系。除上面提到的区位码和电报码为一一对应的无重码编码外,其他现有
的编码方案均有一定数量的重码。所谓重码即一码对应多字。有许多编码为了增加输入的
灵活性,同一汉字用多个码来对应,例如双音编码。
    (6)单宁和词汇的编码。现有的编码方案,为了提高效率,除了单字外还规定了词汇
的编码,甚至使用者可以自行增加词汇库中的词汇,但在提高效率的同时也增加了记亿和
操作的复杂性。
    (7)码表的类型和大小。从汉字输入码到机内码的转换一股需要在机内检索码表。如
果输入码和机内码存在简单的函数关系,有公式可以计算,如区位码等编码就不需要码表,
其他没有简单函数关系的编码就需要码表。码表大小与数据结构、单字数量、词汇数量等
因素有关。国标血2312―80规定的6763个一、二级汉字,备类编码的码表从几千字节到
几万字节。随着词汇旦的增加,有的码表达到了若干兆字节。

5. 汉字的点阵码
    汉字的显示和输出,普遍采用点阵方法。由于汉字数量多且字形变化大,对不同字形
汉字的输出,就有不同的点阵字形。所谓汉字的点阵码,就是汉字点阵字形的代码。存储
在介质中的全部汉字的点阵码又称为字库。    .
  16x16点阵的汉字其点阵有16行,每一行上有16个点。如果每一个点用一个二进制
位来表示,则每一行有16个二进制位,需用两个字节来存放每一行上的16个点,并且规
定其点阵中二进制位0为白点,1为黑点,这样一个16X16点阵的汉字需要用2×t6即32
个字节来存放。依次类推,24×24点阵和32×32点阵的汉字则依次要用72个字节和128
个字节存放一个汉字,构成它在字库中的字模信息。
    要显示或打印输出一个汉字时,计算机汉字系统根据该汉字的机内码找出其字模信息
在字库中的位置,再取出其字模信息作为字形在屏幕上显示或在打印机上打印输出

 

参考资料:http://www.cnblogs.com/thankgoodness/articles/1384078.html

参考资料:http://hi.baidu.com/shi51314/blog/item/667be536ed70e9280b55a93c.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值