您的位置:首页 > 编程语言 > C语言/C++

六一儿童节的礼物:基于GB18030-2000汉字拼音类库(C++)

2011-05-30 22:02 441 查看
开发工具:

Visual Studio v2010

Windows SDK v7.1

版本历史:

V1.0 2011年5月30日

实现GB18030-2000汉字拼音模块。

功能描述:

通过汉字获取拼音(基于频率排序)。可查询的汉字编码范围为0x3400~0x9FA5 0xF900~0xFAD9。
获取指定字符集的同音字列表(基于频率排序)。
数字标调音节和字符标调音节之间的互相转换。
音节排序(基于新华字典序)。
将兼容码字符转换为标准字符。

下载地址:

HYPY_Mandarin_CPlusPlus.zip

源代码:

HYPY_Mandarin.h

/* ----------------------------------------------------------
文件名称:HYPY_Mandarin.h

作者:秦建辉

MSN:splashcn@msn.com

版本历史:
V1.0	2011年5月30日
实现GB18030-2000汉字拼音模块。

功能描述:
1.通过汉字获取拼音(基于频率排序)。可查询的汉字编码范围为0x3400~0x9FA5 0xF900~0xFAD9。
2.获取指定字符集的同音字列表(基于频率排序)。
3.数字标调音节和字符标调音节之间的互相转换。
4.音节排序(基于新华字典序)。
5.将兼容码字符转换为标准字符。
------------------------------------------------------------ */
#pragma once

#include <Windows.h>

class Pinyin
{
public:
// 常量
static const INT SYLLABLE_NUM = 1402;				// 音节总类数
static const DWORD NormZoneBegin = 0x3400;			// 标准码区间起始编码
static const DWORD NormZoneEnd = 0x9FA5;			// 标准码区间结束编码
static const DWORD CompatibilityZoneBegin = 0xF900;	// 兼容码区间起始编码
static const DWORD CompatibilityZoneEnd = 0xFAFF;	// 兼容码区间结束编码

// 枚举类型
enum TCharSet {GB2312 = 0x01, GBK = 0x02, GB18030 = 0x04};	// 字符集

public:
/*
功能:获取汉字拼音音节索引集
参数说明:
dwUCS4:汉字UCS4编码
hSyllableSet:句柄,其内容指向拼音音节索引区。
返回值:
-1:参数错误
0:读音未知
>0:读音数
*/
static INT Pronunciation( DWORD dwUCS4, const WORD** hSyllableSet );

/*
功能:获取索引对应的拼音音节
参数说明:
pSyllable:存储拼音音节(要求不少于16个单元),为NULL结束的Unicode字符串。
iIndex:音节索引号
isDigitTone:
true:音节使用数字标调
false:音节使用字符标调
isUppercase:
true:音节使用大写字母形式
false:音节使用小写字母形式
返回值:
-1:参数错误
>0:音节长度
调用说明:
pSyllable的存储空间不少于16个单元
*/
static INT Syllable( WCHAR* pSyllable, INT iIndex, BOOL isDigitTone = TRUE, BOOL isUppercase = TRUE );

/*
功能:获取音节索引对应的同音字集
参数说明:
pHomophone:存储同音字结果。可以为NULL。
iIndex:音节索引号
cs:
GB2312:GB2312字符集内的同音字
GBK:GBK字符集内的同音字
GB18030:GB18030-2000字符集内的同音字
返回值:
-1:参数错误
>=0:同音字个数
调用说明:
第一次调用设置pHomophone为NULL,获得同音字个数
按(同音字个数+1)为pHomophone申请空间
第二次调用传入已分配空间的pHomophone获得同音字集
*/
static INT Homophone( WCHAR* pHomophone, INT iIndex, TCharSet cs = GB2312 );

/*
功能:将字符标调音节转成数字标调音节
参数说明:
pDigitToneSyllable:存储转换后的数字标调音节,其存储空间不少于16个单元
pCharToneSyllable:要转换的字符标调音节
isUppercase:
true:输出大写字母形式的数字标调音节
false:输出小写字母形式的数字标调音节
返回值:
-1:参数错误
>0:数字标调音节长度
调用说明:
pDigitToneSyllable的存储空间不少于16个单元
*/
static INT CharTone2DigitTone( WCHAR* pDigitToneSyllable, const WCHAR* pCharToneSyllable, BOOL isUppercase = TRUE );

/*
功能:将数字标调音节转成字符标调音节
参数说明:
pCharToneSyllable:存储转换后的字符标调音节,其存储空间不少于16个单元
pDigitToneSyllable:要转换的数字标调音节
isUppercase:
true:输出大写字母形式的字符标调音节
false:输出小写字母形式的字符标调音节
返回值:
-1:参数错误
-2:音节错误
>0:字符标调音节长度
调用说明:
pCharToneSyllable的存储空间不少于16个单元
*/
static INT DigitTone2CharTone( WCHAR* pCharToneSyllable, const WCHAR* pDigitToneSyllable, BOOL isUppercase = FALSE );

/*
功能:基于数字标调的汉语拼音串比较函数(新华字典序)
参数说明:
x:数字标调的音节x
y:数字标调的音节y
返回值:
-1:x排在y前面
0:x与y位置相同
1:x排在y后面
*/
static INT PinyinCompare( const WCHAR* x, const WCHAR* y );

public:
/*
功能:将UTF8编码转换成UCS4编码
参数:
pbUTF8:要转换的UTF8编码
dwUCS4:存储转换后的UCS4编码
返回值:
0:参数错误或无效的UTF8编码
1-6:UTF8编码的有效长度
*/
static INT UTF8_To_UCS4( const BYTE* pbUTF8, DWORD& dwUCS4 );

/*
功能:将UCS4编码转换成UTF16编码
参数:
dwUCS4:要转换的UCS4编码
pwUTF16:用于存储转换后的UTF16编码。设为NULL,可以获取长度信息(字符数)
返回值:
0:无效的UCS4编码
1:转换成1个UTF16编码
2:转换成2个UTF16编码(代理项对)
*/
static INT UCS4_To_UTF16( DWORD dwUCS4, WCHAR* pwUTF16 );

/*
功能:将UTF16编码转换成UCS4编码
参数:
pwUTF16:需要转换的UTF16编码
dwUCS4:存储转换后的UCS4编码
返回值:
0:参数错误或无效的UTF16编码
1:1个UTF16编码被转换
2:2个UTF16编码被转换(代理项对)
*/
static INT UTF16_To_UCS4( const WORD* pwUTF16, DWORD& dwUCS4 );

/*
功能:将字符转成大写字母
参数说明:
wCode:要转换的字符
返回值:
对应的大写字母
说明:
由于没有语言信息,对土耳其语的i处理有问题
*/
static WCHAR CharToUpper( WCHAR wCode );

/*
功能:将字符转成小写字母
参数说明:
wCode:要转换的字符
返回值:
对应的小写字母
说明:
由于没有语言信息,对土耳其语的I处理有问题
*/
static WCHAR CharToLower( WCHAR wCode );

/*
功能:将字符串转换成大写串
参数说明:
strDestination:目标字符串
strSource:源字符串
返回值:
目标字符串
*/
static WCHAR* StringToUpper( WCHAR* strDestination, const WCHAR* strSource );

/*
功能:将字符串转换成小写串
参数说明:
strDestination:目标字符串
strSource:源字符串
返回值:
目标字符串
*/
static WCHAR* StringToLower( WCHAR* strDestination, const WCHAR* strSource );

/*
功能:获取字符所属的字符集组合(GB2312、GBK、GB18030)
参数说明:
dwUCS4:汉字UCS4编码
返回值:
汉字所属的字符集组合
0x01:GB2312
0x02:GBK
0x04:GB18030
调用说明:
只能判断0x3400~0x9FA5之间的字符
*/
static BYTE CharSetClass( DWORD dwUCS4 );

/*
功能:将兼容码字符转换为标准码字符
参数说明:
dwUCS4:汉字UCS4编码
返回值:
如果是兼容码字符,则返回转换后的标准码字符,否则不变
调用说明:
只处理0xF900~0xFAFF之间的兼容码字符
*/
static DWORD Compatibility2Norm( DWORD dwUCS4 );

protected:
/*
功能:单音节比较函数
参数说明:
x:数字标调的音节x
iLenX:x音节有效长度,如果为-1,则x为NULL结束的字符串,长度为整个字符串长度
y:数字标调的音节y
iLenY:y音节有效长度,如果为-1,则y为NULL结束的字符串,长度为整个字符串长度
返回值:
-1:x排在y前面
0:x与y位置相同
1:x排在y后面
*/
static INT MonoSyllableCompare(const WCHAR* x, INT iLenX, const WCHAR* y, INT iLenY);
};

HYPY_Mandarin.cpp

#include "HYPY_Mandarin.h"
#include <wchar.h>

// 音节相关
extern "C" const WORD awCharToSyllableTable[];
extern "C" const WORD awSyllableEndIndex[];
extern "C" const BYTE abSyllableMap[];

// 同音字相关
extern "C" const WORD awHomophoneEndIndex[];
extern "C" const WORD awHomophoneMap[];
extern "C" const BYTE abHZClass[];

// 声调转换
extern "C" const WORD awCharTone2DigitToneTable[][3];
#define CHARTONE_DIGITTONE_NUM		64	// 字符标调组合数

// 兼容码相关
extern "C" const WORD awCompatibility2Norm[][2];
#define COMPATIBILITY_VARIANT_NUM	451	// 兼容码字符个数

// 大小写相关
extern "C" const WORD awSpecialTwins[][2];
#define SPECIAL_TWINS_NUM			9	// 特殊大小写字符个数

extern "C" const WORD awCapitalLetterZone[][3];
#define CAPITAL_LETTER_ZONE_NUM		19	// 大写字符区域

// 转换UTF8编码到UCS4编码
INT Pinyin::UTF8_To_UCS4( const BYTE* pbUTF8, DWORD& dwUCS4 )
{
INT i, iLen;
BYTE b;

if( pbUTF8 == NULL )
{	// 参数错误
return 0;
}

b = *pbUTF8++;
if( b < 0x80 )
{
dwUCS4 = b;
return 1;
}

if( b < 0xC0 || b > 0xFD )
{	// 非法UTF8
return 0;
}

// 确定编码长度
if( b < 0xE0 )
{
dwUCS4 = b & 0x1F;
iLen = 2;
}
else if( b < 0xF0 )
{
dwUCS4 = b & 0x0F;
iLen = 3;
}
else if( b < 0xF8 )
{
dwUCS4 = b & 7;
iLen = 4;
}
else if( b < 0xFC )
{
dwUCS4 = b & 3;
iLen = 5;
}
else
{
dwUCS4 = b & 1;
iLen = 6;
}

for( i = 1; i < iLen; i++ )
{
b = *pbUTF8++;
if( b < 0x80 || b > 0xBF )
{	// 非法UTF8
break;
}

dwUCS4 = (dwUCS4 << 6) + (b & 0x3F);
}

if( i < iLen )
{	// 非法UTF8
return 0;
}
else
{
return iLen;
}
}

// 转换UCS4编码或者UCS2编码到UTF16编码
INT Pinyin::UCS4_To_UTF16( DWORD dwUCS4, WCHAR* pwUTF16 )
{
if( dwUCS4 <= 0xFFFF )
{
if( pwUTF16 != NULL )
{
*pwUTF16 = static_cast<WORD>(dwUCS4);
}

return 1;
}
else if( dwUCS4 <= 0xEFFFF )
{
if( pwUTF16 != NULL )
{	// 代理项对
pwUTF16[0] = static_cast<WORD>(0xD800 + (dwUCS4 >> 10) - 0x40);	// 高10位
pwUTF16[1] = static_cast<WORD>(0xDC00 + (dwUCS4 & 0x03FF));		// 低10位
}

return 2;
}
else
{
return 0;
}
}

// 转换UCS2编码到UCS4编码
INT Pinyin::UTF16_To_UCS4( const WORD* pwUTF16, DWORD& dwUCS4 )
{
WORD w1, w2;

if( pwUTF16 == NULL )
{	// 参数错误
return 0;
}

w1 = pwUTF16[0];
if( w1 >= 0xD800 && w1 <= 0xDFFF )
{	// 编码在代理项区域(Surrogate Area)
if( w1 < 0xDC00 )
{
w2 = pwUTF16[1];
if( w2 >= 0xDC00 && w2 <= 0xDFFF )
{
dwUCS4 = (w2 & 0x03FF) + (((w1 & 0x03FF) + 0x40) << 10);
return 2;
}
}

return 0;	// 非法UTF16编码
}
else
{
dwUCS4 = w1;
return 1;
}
}

// 将字符转换成大写字母
WCHAR Pinyin::CharToUpper( WCHAR wUCS2 )
{	//	特殊希腊字符
if( wUCS2 == 0x03C2 ) return 0x03A3;

// 特例处理
for( INT i = 0; i < SPECIAL_TWINS_NUM; i++ )
{
if( wUCS2 == awSpecialTwins[i][1] )
{
return awSpecialTwins[i][0];
}
}

// 区域处理
for( INT i = 0; i < CAPITAL_LETTER_ZONE_NUM; i++ )
{
WORD wBegin = awCapitalLetterZone[i][0];
WORD wEnd = awCapitalLetterZone[i][1];
WORD wType = awCapitalLetterZone[i][2];

if( wUCS2 < wBegin )break;

if( wType == 1 || wType == 2 )
{
wBegin++;
wEnd++;
}
else
{
wBegin += wType;
wEnd += wType;
}

if( wUCS2 >= wBegin && wUCS2 <= wEnd )
{
if( wType == 1 )
{	// 大写字母编码为偶数,大小写连在一起
if( wUCS2 % 2 != 0 )
wUCS2--;
}
else if( wType == 2 )
{	// 大写字母编码为奇数,大小写连在一起
if( wUCS2 % 2 == 0 )
wUCS2--;
}
else
{	// 大小写字母没有连在一起,而是在各自的区域块
wUCS2 -= wType;
}

break;
}
} // End for i

return wUCS2;
}

// 将字符转换成小写字母
WCHAR Pinyin::CharToLower( WCHAR wUCS2 )
{	// 特例处理
for( INT i = 0; i < SPECIAL_TWINS_NUM; i++ )
{
if( wUCS2 == awSpecialTwins[i][0] )
{
return awSpecialTwins[i][1];
}
}

for( INT i = 0; i < CAPITAL_LETTER_ZONE_NUM; i++ )
{
WORD wBegin = awCapitalLetterZone[i][0];
WORD wEnd = awCapitalLetterZone[i][1];
WORD wType = awCapitalLetterZone[i][2];

if( wUCS2 < wBegin )break;

if( wUCS2 >= wBegin && wUCS2 <= wEnd )
{
if( wType == 1 )
{	// 大写字母编码为偶数,大小写连在一起
if( wUCS2 % 2 == 0 )
wUCS2++;
}
else if( wType == 2 )
{	// 大写字母编码为奇数,大小写连在一起
if( wUCS2 % 2 != 0 )
wUCS2++;
}
else
{	// 大小写字母没有连在一起,而是在各自的区域块
wUCS2 += wType;
}

break;
}
} // End for i

return wUCS2;
}

// 转换成大写字母形式
WCHAR* Pinyin::StringToUpper( WCHAR* strDestination, const WCHAR* strSource )
{
if(strDestination == NULL || strSource == NULL)return NULL;

WCHAR* p = strDestination;
while(*strDestination++ = CharToUpper(*strSource++));
return p;
}

// 转换成小写字母形式
WCHAR* Pinyin::StringToLower( WCHAR* strDestination, const WCHAR* strSource )
{
if(strDestination == NULL || strSource == NULL)return NULL;

WCHAR* p = strDestination;
while(*strDestination++ = CharToLower(*strSource++));
return p;
}

// 获取字符所属的字符集组合(GB2312、GBK、GB18030)
BYTE Pinyin::CharSetClass( DWORD dwUCS4 )
{
BYTE ucClass = 0;
if (dwUCS4 >= NormZoneBegin && dwUCS4 <= NormZoneEnd)
{
INT iSpan = dwUCS4 - NormZoneBegin;
ucClass = abHZClass[iSpan >> 1];
if (iSpan % 2 == 0)
{   // 字节低4Bit
ucClass &= 0x0F;
}
else
{   // 字节高4Bit
ucClass >>= 4;
}
}

return ucClass;
}

// 将兼容码字符转换为标准码字符
DWORD Pinyin::Compatibility2Norm( DWORD dwUCS4 )
{	// 兼容码区间
if (dwUCS4 >= CompatibilityZoneBegin && dwUCS4 <= CompatibilityZoneEnd)
{   // 折半查找
INT iBegin = 0;
INT iEnd = COMPATIBILITY_VARIANT_NUM - 1;
while (iBegin <= iEnd)
{
INT iMiddle = (iBegin + iEnd) >> 1;
DWORD dwCode = awCompatibility2Norm[iMiddle][0];
if (dwUCS4 > dwCode)
{
iBegin = iMiddle + 1;
}
else if (dwUCS4 < dwCode)
{
iEnd = iMiddle - 1;
}
else
{   // 返回标准码
return awCompatibility2Norm[iMiddle][1];
}
}
}

// 返回原始码
return dwUCS4;
}

// 获取汉字的拼音音节索引集
INT Pinyin::Pronunciation( DWORD dwUCS4, const WORD** hSyllableSet )
{
// 入口参数判断
if( hSyllableSet == NULL )
{
return -1;	// 参数错误
}

*hSyllableSet = NULL;

// 将兼容码字符转换到标准码字符
dwUCS4 = Compatibility2Norm(dwUCS4);

// 有效区间0x3400~0x9FA5,共计27484个有效汉字
if (dwUCS4 >= NormZoneBegin && dwUCS4 <= NormZoneEnd)
{
INT iIndex = dwUCS4 - NormZoneBegin;
WORD wKey = awCharToSyllableTable[iIndex];
if (wKey != 0xFFFF)
{
if (wKey < (NormZoneEnd - NormZoneBegin + 1))
{   // 单音字
*hSyllableSet = awCharToSyllableTable + iIndex;
return 1;
}
else
{   // 多音字,二次定位
*hSyllableSet = awCharToSyllableTable + wKey + 1;
return awCharToSyllableTable[wKey];
}
}
}

// 读音未知
return 0;
}

// 获取索引对应的拼音音节
INT Pinyin::Syllable( WCHAR* pSyllable, INT iIndex, BOOL isDigitTone, BOOL isUppercase )
{
if( pSyllable == NULL || iIndex < 0 || iIndex >= SYLLABLE_NUM )
{
return -1;	// 参数错误
}

WORD wBegin, wEnd;
DWORD dwUCS4;

// 音节起始位置
if( iIndex == 0 )
wBegin = 0;
else
wBegin = awSyllableEndIndex[iIndex - 1];

// 音节结束位置
wEnd = awSyllableEndIndex[iIndex];

// 将音节由UTF-8转换为UTF-16
INT iNum = 0;
if(isDigitTone)
{	// 数字标调
WORD wTone = '5';	// 声调初始化
while( wBegin < wEnd )
{
wBegin += UTF8_To_UCS4( abSyllableMap + wBegin, dwUCS4 );
if( dwUCS4 == 0x0300 )
wTone = '4';
else if( dwUCS4 == 0x0301 )
wTone = '2';
else if( dwUCS4 == 0x0304 )
wTone = '1';
else if( dwUCS4 == 0x030C )
wTone = '3';
else
{
if( dwUCS4 == '-' )
{	// 多音节
pSyllable[iNum++] = wTone;
pSyllable[iNum++] = '-';
wTone = '5';	// 声调初始化
}
else
{
iNum += UCS4_To_UTF16( dwUCS4, pSyllable + iNum );
}
}
}	// End While

pSyllable[iNum++] = wTone;
}
else
{	// 字符标调
while( wBegin < wEnd )
{
wBegin += UTF8_To_UCS4( abSyllableMap + wBegin, dwUCS4 );
iNum += UCS4_To_UTF16( dwUCS4, pSyllable + iNum );
} // End While
}

pSyllable[iNum] = 0;	// 写入字符串结束标记

if(isUppercase)
{	// 转换到大写字母
StringToUpper( pSyllable, pSyllable );
}

return iNum;
}

// 获取音节的同音字集
INT Pinyin::Homophone( WCHAR* pHomophone, INT iIndex, TCharSet cs )
{
if( iIndex < 0 || iIndex >= SYLLABLE_NUM )
{
return -1;	// 参数错误
}

// 开始索引位置
INT iBegin;
if( iIndex == 0 )
iBegin = 0;
else
iBegin = awHomophoneEndIndex[iIndex - 1];

// 结束索引位置
INT iEnd = awHomophoneEndIndex[iIndex];

INT iNum = 0;
while(iBegin < iEnd)
{
DWORD dwUCS4;

iBegin += UTF16_To_UCS4( awHomophoneMap + iBegin, dwUCS4 );
if((CharSetClass(dwUCS4) & cs) != 0)	// 字符集检测
{	// 在所要求的字符集内
if(pHomophone == NULL)
{
if(dwUCS4 <= 0xFFFF)
iNum++;
else
iNum += 2;
}
else
{
iNum += UCS4_To_UTF16(dwUCS4, pHomophone + iNum);
}
}
}

if(pHomophone != NULL)
{
pHomophone[iNum] = 0;	// 写入字符串结束标记
}

return iNum;
}

// 将字符标调音节转成数字标调音节
INT Pinyin::CharTone2DigitTone( WCHAR* pDigitToneSyllable, const WCHAR* pCharToneSyllable, BOOL isUppercase )
{
if((pCharToneSyllable == NULL) || (pDigitToneSyllable == NULL))
{
return -1;
}

WCHAR wUCS2, wTone;
INT iNum = 0;

wTone = '5';	// 声调初始化
while( (wUCS2 = *pCharToneSyllable++) != 0 )
{
if(wUCS2 == '-')
{
pDigitToneSyllable[iNum++] = wTone;
pDigitToneSyllable[iNum++] = '-';
wTone = '5';
}
else
{
INT i;
for(i = 0; i < CHARTONE_DIGITTONE_NUM; i++)
{
if(wUCS2 == awCharTone2DigitToneTable[i][0])
{	// 音调字符
wTone = awCharTone2DigitToneTable[i][2];
if(awCharTone2DigitToneTable[i][1] != 0)
{
pDigitToneSyllable[iNum++] = awCharTone2DigitToneTable[i][1];
}

break;
}
}

if(i == CHARTONE_DIGITTONE_NUM)
{	// 非音调字符
pDigitToneSyllable[iNum++] = wUCS2;
}
}
}	// End While

pDigitToneSyllable[iNum++] = wTone;
pDigitToneSyllable[iNum] = 0;	// 写入字符串结束标记

if(isUppercase)
{	// 转换到大写字母
StringToUpper( pDigitToneSyllable, pDigitToneSyllable );
}
else
{	// 转换到小写字母
StringToLower( pDigitToneSyllable, pDigitToneSyllable );
}

return iNum;
}

// 将数字标调音节转成字符标调音节
INT Pinyin::DigitTone2CharTone( WCHAR* pCharToneSyllable, const WCHAR* pDigitToneSyllable, BOOL isUppercase )
{	// 可标调字符集
const WCHAR ToneCharSet[] = {'a', 'o', 'e', 'i', 'u', 0x00FC, 0x00EA, 'n', 'm'};
const WCHAR CombiningCharSet[] = {0x0304, 0x0301, 0x030C, 0x0300};
const INT ToneCharNum = sizeof(ToneCharSet) / sizeof(WCHAR);

if((pDigitToneSyllable == NULL) || (pCharToneSyllable == NULL))
{
return -1;	// 参数错误
}

INT iNum = 0;
while( *pDigitToneSyllable != 0 )
{
INT iLen;

// 定位连接符
const WCHAR* pHyphen = wcschr( pDigitToneSyllable, '-' );
if(pHyphen == NULL)
{	// 单音节
iLen = wcslen( pDigitToneSyllable ) - 1;
}
else
{	// 多音节
iLen = pHyphen - pDigitToneSyllable - 1;
}

if(iLen < 1)return -2;	// 音节错误

// 获取数字声调
WCHAR wTone = pDigitToneSyllable[iLen];
if(wTone >= '1' && wTone <= '4')
{	// 获取插入点
INT i;
for(i = 0; i < ToneCharNum; i++)
{	// 查找可标调字符
WCHAR wUCS2 = ToneCharSet[i];
const WCHAR* pInsert = wmemchr( pDigitToneSyllable, wUCS2, iLen );
if( pInsert == NULL )
{
pInsert = wmemchr( pDigitToneSyllable, CharToUpper(wUCS2), iLen );
}

if( pInsert != NULL )
{	// 找到插入点
pInsert++;
if(CharToLower(wUCS2) == 'i')	// 处理特例"iu"
{
if((pInsert < pDigitToneSyllable + iLen) && CharToLower(*pInsert) == 'u')
{
pInsert++;
}
}

INT iCount = pInsert - pDigitToneSyllable;
wcsncpy( pCharToneSyllable + iNum, pDigitToneSyllable, iCount );
iNum += iCount;
pCharToneSyllable[iNum++] = CombiningCharSet[wTone - '1'];	// 插入组合音符
iCount = iLen - iCount;	// 剩余字符个数
wcsncpy( pCharToneSyllable + iNum, pInsert, iCount );
iNum += iCount;

break;
}
}	// End for i

if(i == ToneCharNum)
{	// 未发现可标调字符
return -2;	// 音节错误
}
}
else if(wTone == '5')
{	// 轻声
wcsncpy( pCharToneSyllable + iNum, pDigitToneSyllable, iLen );
iNum += iLen;
}
else
{
return -2;	// 音节错误
}

if(pHyphen == NULL)
{
break;
}
else
{
pCharToneSyllable[iNum++] = '-';
pDigitToneSyllable = pHyphen + 1;
}
} // End While

pCharToneSyllable[iNum] = 0;	// 写入字符串结束标记

if(isUppercase)
StringToUpper(pCharToneSyllable, pCharToneSyllable);	// 大写字母形式
else
StringToLower(pCharToneSyllable, pCharToneSyllable);	// 小写字母形式

return iNum;
}

// 基于数字标调的汉语拼音串比较函数(新华字典序)
INT Pinyin::PinyinCompare( const WCHAR* x, const WCHAR* y )
{
INT iRank;

if(x == NULL || wcslen(x) == 0)
{
if(y == NULL || wcslen(y) == 0)
return 0;
else
return 1;
}
else if(y == NULL || wcslen(y) == 0)
{
return 1;
}

// 定位连接符
const WCHAR* pHyphenX = wcschr(x, '-');
const WCHAR* pHyphenY = wcschr(y, '-');
if(pHyphenX != NULL)	// x为多音节
{
if(pHyphenY != NULL)	// y为多音节
{	// 比较第一个音节
iRank = MonoSyllableCompare(x, pHyphenX - x, y, pHyphenY - y);
if(iRank == 0)
{	// 继续比较其余音节
return PinyinCompare(pHyphenX + 1, pHyphenY + 1);
}
else
return iRank;
}
else
{	// y为单音节
iRank = MonoSyllableCompare(x, pHyphenX - x, y, -1);
return (iRank == 0) ? 1 : iRank;
}
}
else if(pHyphenY != NULL)
{	// x为单音节,y为多音节
iRank = MonoSyllableCompare(x, -1, y, pHyphenY - y);
return (iRank == 0) ? (-1) : iRank;
}
else
{	// x和y都是单音节
return MonoSyllableCompare(x, -1, y, -1);
}
}

// 基于数字标调的单音节串比较函数(新华字典序)
INT Pinyin::MonoSyllableCompare(const WCHAR* x, INT iLenX, const WCHAR* y, INT iLenY)
{
INT iFlagX = 0;
INT iFlagY = 0;

if(iLenX < 0)iLenX = wcslen(x);
if(iLenY < 0)iLenY = wcslen(y);

INT iMinLen = (iLenX < iLenY) ? iLenX : iLenY;
for(INT i = 0; i < iMinLen; i++)
{
WCHAR wCodeX = x[i];
WCHAR wCodeY = y[i];
if(wCodeX == 0x00CA || wCodeX == 0x00EA)
{
wCodeX = 'E';
iFlagX = 1;
}
else if(wCodeX == 0x00DC || wCodeX == 0x00FC)
{
wCodeX = 'U';
iFlagX = 1;
}
else if( wCodeX >= 'a' && wCodeX <= 'z')
{
wCodeX -= ('a' - 'A');	// 大写字母
}

if(wCodeY == 0x00CA || wCodeY == 0x00EA)
{
wCodeY = 'E';
iFlagY = 1;
}
else if(wCodeY == 0x00DC || wCodeY == 0x00FC)
{
wCodeY = 'U';
iFlagY = 1;
}
else if(wCodeY >= 'a' && wCodeY <= 'z')
{
wCodeY -= ('a' - 'A');
}

if(wCodeX < wCodeY)
{	// 特例:声调部分
if(iFlagX == 1 && iFlagY == 0)
{
if(wCodeX >= '1' && wCodeX <= '5' && wCodeY >= '1' && wCodeY <= '5')
return 1;
}

return -1;
}
else if(wCodeX > wCodeY)
{	// 特例:声调部分
if(iFlagY == 1 && iFlagX == 0)
{
if(wCodeX >= '1' && wCodeX <= '5' && wCodeY >= '1' && wCodeY <= '5')
return -1;
}

return 1;
}
}

if(iFlagX == 1)
{
if(iFlagY == 1)
return (iLenX < iLenY) ? (-1) : ((iLenX > iLenY) ? 1 : 0);
else
return 1;
}
else
{
if(iFlagY == 1)
return -1;
else
return (iLenX < iLenY) ? (-1) : ((iLenX > iLenY) ? 1 : 0);
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息