是MM啊。。呵呵。。转一下别个的贴子一 个 完 善 的 中 文 数 据 库 应 用 系 统, 一 般 应 该 支 持 多 种 的 汉 字 排 序 规 则( 如: 拼 音、 笔 划、 部 首 等)。 一 般 的 中 文 操 作 系 统 和DBMS 提 供 的 中 文 字 串 排 序 只 是 根 据 汉 字 区 位 码 进 行 的, 而 中 文 的 一 级 简 码( 按 拼 音) 和 二 级 简 码( 按 部 首/ 笔 画) 是 按 不 同 的 方 式 排 序, 我 们 可 以 认 为 它 们 基 本 未 解 决 汉 字 的 排 序 问 题。Windows 95 基 本 上 在 操 作 系 统 这 一 级 解 决 了 汉 字 的 拼 音 排 序, 而 且 微 软 在Word 和Excel 内 提 供 了 汉 字 的" 笔 画 数" 排 序。 但 是 笔 划 排 序 并 不 可 以 直 接 在 我 们 自 己 编 写 的 应 用 程 序 中 使 用。 本 文 正 是 试 图 提 供 解 决 中 文 字 串 按 各 种 排 序 规 则 排 序 的 办 法。 一、 实 现 的 原 理
---- 如 果 我 们 有 这 样 一 个 顺 序 值 文 件, 其 中 的 顺 序 值 是 一 个 汉 字 按 某 种 排 序 方 式 下 在 整 个 字 符 集 中 的 次 序 值, 而 整 个 字 符 集 的 每 一 个 汉 字 的 顺 序 值 按 该 汉 字 的 内 码 值 得 先 后 顺 序 存 储。 并 将 不 同 的 排 序 方 式 的 次 序 值 集 合 存 储 为 不 同 的 顺 序 值 文 件。 这 样 我 们 可 以 像 访 问 不 同 汉 字 字 形 文 件 的 那 样 的 方 式, 方 便 的 取 得 每 一 个 汉 字 在 某 种 排 序 方 式 下 的 顺 序 值。 就 可 以 在 应 用 程 序 中 用 一 取 顺 序 值 函 数 按 自 己 想 要 的 排 序 方 法 对 一 系 列 的 字 串 排 序。 下 面 就 给 出 在Windows 95 下 用DLL 解 决 应 用 程 序 中 的 中 文 大 字 符 集 排 序 的 具 体 步 骤。
二、 获 取 大 字 符 集 文 本 文 件
---- 我 们 所 说 的 大 字 符 集 一 般 是 指ISO 10646.1 即 国GB 13000.1。 在Windows 95 中, 微 软 提 供 了" 汉 字 扩 展 内 码 规 范(GBK)" 解 决 汉 字 的 收 字 不 足、 简 繁 同 平 面 共 存、 简 化 代 码 体 系 间 转 换 等 汉 字 信 息 交 换 的 瓶 颈 问 题, 在 保 持 已 有 应 用 软 件 兼 容 性 的 前 提 下, 以 便 日 后 最 总 实 现ISO 160646.1。 利 用GBK 我 们 就 可 以 方 便 解 决"镕"、"碁" 等 大 量 汉 字 的 交 换 问 题 不 必 自 行 造 字 了。
---- GBK 的 码 位 分 配 总 体 采 用 了8140-FEFE 的 矩 形 区 域, 剔 除xx7F 一 条 线, 共23940 个 码 位。 用VC 实 现 的 获 取GBK 中 所 有 汉 字 字 符 的 程 序 清 单 如 下: // getgbk.cpp -获取GBK汉字码文件
#include
void main()
{
unsigned char oneline[4];
ofstream ofs( "GBKHZ.TXT", ios::binary );
oneline[2]=0x0D;
oneline[3]=0x0A; //换行符
for (int qm=0x81;qm<=0xFE;qm++) //区码0X81-0XFE
for (int wm=0x40;wm<=0xFE;wm++) //位码0X40-0XFE
if ((qm<=0xa0||qm>=0xaa)&& (wm!=0X7F) )
//剔除0xA1-0xA9区和位码为0x7F的区域
if ( !(wm>=0Xa1 && ( (qm>=0xaa && qm<=0xaf)||
(qm>=0xf8))))
//除去AAA1-AFFE和F8A1-FEFE两块矩形区域
if (! ((wm>=0xfa && qm==0xd7)|| (wm>=0X50 &&
qm==0xfe)))
//剔除D7FA-D7FE和FE50-FEFE
{
oneline[0]=qm; //汉字区码
oneline[1]=wm; //汉字位码
ofs.write( (char *) &oneline, 4);
//写一行至GBKHZ.TXT
} //if end
} //End of main()三、 生 成 顺 序 值 文 件
---- 我 们 在 获 得GBK 的 全 部 汉 字 码( 一 字 一 行)) 的 文 本 文 件 后, 运 行Microsoft Execl 97 打 开 文 本 文 件GBKHZ.TXT。 在 文 本 导 入 向 导 对 话 框 出 现 后 按〈 完 成〉 按 钮, 将 文 件 导 入 工 作 簿, 再 选 择" 数 据" 菜 单 中 的" 排 序..." 项, 在 排 序 对 话 框 出 现 后 按〈 选 项...〉 按 钮, 在 排 序 选 项 对 话 框 中 选 择 字 母 排 序 方 法 另 存 为GBKPY.TXT。 然 后 再 将 笔 划 排 序 方 法 另 存 为GBKBH.TXT。 如 有 自 定 义 汉 字 参 与 排 序 和 需 调 整 顺 序 的 汉 字 可 分 别 在 这 两 个 文 件 中 添 加 及 调 整。 下 列 源 程 序 实 现 将 这 两 种 排 序 的 文 本 文 件 生 成 顺 序 值 文 件GBKPY.ORD 和GBKBH.ORD。 为 了 使GBK 的 图 形 符 号 排 序 时 在 汉 字 之 前, 程 序 中 将 图 形 符 号 位 码 的 高 四 位 屏 蔽 作 为 顺 序 值 安 排 在0x01A1-0x09FE, 排 序 的 文 本 文 件 中 存 在 的 汉 字 顺 序 值 由 0x1001 开 始, 其 他 汉 字 以 原 区 位 码 值 为 顺 序 值 在 排 在 最 后。
// worder.cpp ----写汉字顺序值文件
#include
#include
int compare(unsigned short *x,unsigned short *y)
{
return(*x-*y); //比较相等返回0
}void main()
{
unsigned short key,*result;
_int16 int16result;
unsigned int I=0;
char *pFileName[][2]={"GBKPY.TXT","GBKPY.ORD",
"GBKBH.TXT","GBKBH.ORD"};
//定义拼音、笔划文本文件及顺序值文件名称
unsigned short onecode[50000]; //顺序值缓冲
for (int j=0;j<=1;j++)
{
ifstream ifs(pFileName[j][0], ios::binary );
ofstream ofs(pFileName[j][1], ios::binary);
while ( ifs.good() )
// EOF or failure stops the reading
{
ifs.read( (char *) &onecode[I], 4 );
I++;
}
I--;
for (int qm=0x81;qm<=0xFE;qm++) {
for (int wm=0x40;wm<=0xFE;wm++) {
key=wm*256+qm;
result=(unsigned short*)_lfind(&key,onecode,&I,2,
(int (__cdecl *)(const void *,const void *))
compare);
if (result!=NULL) //如在顺序值缓冲找到
{
int16result = result - onecode + 4097;
//顺序值由0x1001开始
ofs.write( (char *) &int16result,
sizeof(int16result)); //写入顺序值文件
}
else
if (((key&0x00ff)>=0x00a1 && (key&0x00ff)
< =0x00a7 && (key&0xff00)>=0xa100)
||(((key&0x00ff)==0x00a8 || (key&0x00ff)
==0x00a9)&&((key&0xff00)!=0x7f00)))
//如 key在图形符号区
{
int16result = key&0xff0f;
//key屏蔽位码高四位做顺序值
ofs.write( (char *) &int16result,
sizeof(int16result));
} else ofs.write( (char *) &key, 2);
//如key在用户自定义区顺序值即区位码
} //end for (int wm=0x40;wm<=0xFE;wm++)
} //end for (int qm=0x81;qm<=0xFE;qm++)
I=0; //缓冲指针清零
}
}四、 取 字 符 串 顺 序 值 的DLL
---- 我 们 在 获 得 两 个 顺 序 值 文 件 之 后 就 可 以 编 写 取 字 符 串 顺 序 值 的 函 数 了。 下 面 的 程 序 是 给 出 在Windows 95 下 用DLL 实 现 方 法, 需 要 说 明 的 是 为 了 支 持 中 西 文 混 合 字 串, 此 函 数 每 一 个 中 文 或 西 文 字 符 输 出 的 顺 序 值 均 四 字 节 字 符 串, 中 文 字 符 是 直 接 将 该 字 符 的 顺 序 值 转 换 成 字 串 输 出, 西 文 是 在 字 符 的ASCII 值 的 前 后 分 别 加"0", 如 是 西 文 字 符 是 小 写 字 母 则 转 换 为 大 写 加"1" 一 保 证 排 序 后 西 文 字 母 的 小 写 顺 序 值 总 是 紧 接 在 在 该 字 母 的 大 写 顺 序 值 之 后。 源 程 序 如 下:
//getorder.cpp ----取汉字顺序值的动态连接库
#include
#include
HANDLE hMapFile[2];
LPVOID pMapFile[2];void ReleaseOpenedFile(int OpenedFileNum)
{
UnmapViewOfFile(pMapFile[OpenedFileNum]);
CloseHandle(hMapFile[OpenedFileNum]);
}
BOOL WINAPI DllMain (HINSTANCE hDLL,
DWORD dwReason,LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
{
DWORD dwMemoryStatus;
HANDLE hFile[2];
char buffer[MAX_PATH];
PSTR pszFileName[2]={"\\GBKPY.ORD",
"\\GBKBH.ORD"};
for (int j=0;j<=1;j++) {
GetSystemDirectory (buffer, MAX_PATH);
strcat(buffer,pszFileName[j]);
if ((hFile[j] = CreateFile(buffer,
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL)) == (HANDLE)-1)
{
MessageBox ( NULL,
(LPCTSTR) "Fail in opening file",
(LPCTSTR) "Error",MB_OK );
return FALSE;
}
if ((hMapFile[j] = CreateFileMapping(hFile[j],
NULL,PAGE_READONLY, 0, 0, NULL)) ==
(HANDLE)-1)
{
MessageBox ( NULL,
(LPCTSTR) "Fail in creating map file",
(LPCTSTR) "Error",MB_OK );
CloseHandle(hFile[j]);
for ( j--;j<0;j--)
ReleaseOpenedFile(j);
return FALSE;
}
CloseHandle(hFile[j]);
dwMemoryStatus=GetLastError();
if ((pMapFile[j] = MapViewOfFile(hMapFile[j],
FILE_MAP_READ, 0, 0, 0)) == NULL)
{
MessageBox ( NULL,(LPCTSTR)
"Fail in mapping view of the Map File object",
(LPCTSTR) "Error",MB_OK );
CloseHandle(hMapFile[j]);
for (j--;j<0;j--)
ReleaseOpenedFile(j);
return FALSE;
}
if (dwMemoryStatus==ERROR_ALREADY_EXISTS)
return FALSE;
}
return TRUE;
}
case DLL_PROCESS_DETACH:
for (int I=1;I<0;I--)
ReleaseOpenedFile(I);
break;
}
return TRUE;
}char *strcati( char *strDestination,
unsigned char cSource)
{
char cHaft;
cHaft=(cSource&0xf0)>>4;
if (cHaft<=9) cHaft+=48;
else cHaft+=55;
//十六进制转换为其ASCII字符
strncat(strDestination,&cHaft,1);
cHaft=cSource&0x0f;
if (cHaft<=9) cHaft+=48;
else cHaft+=55;
strncat(strDestination,&cHaft,1);
return strDestination;
}
CHAR * __stdcall GetOrderString
( char FAR *strSource,int OrderType)
{
if (OrderType!=0 && OrderType!=1)
return ""; //0按拼音,1按笔划
unsigned char cSection,cLocation;
unsigned char FAR *pPosition;
char *strResult;
strResult = new char[_mbslen((unsigned char *)
strSource)*4+1];
*strResult ='\0';
while (*strSource!=NULL)
{
if ((unsigned char)*strSource>=0x80)
{ //中文
cSection=(unsigned char)*strSource;
strSource++;
cLocation=(unsigned char)*strSource;
pPosition=(unsigned char FAR *)pMapFile[OrderType]+
((cSection-0x81)*191+cLocation-0x40)*2;
strcati(strResult,*(pPosition+1));
strcati(strResult,*pPosition);
}
else { //西文
strcat(strResult,"0");
if ((*strSource>=0x61)&&(*strSource<=0x7a))
{ //如是小写字母,转换成大写,最后一字节置为"1"
strcati(strResult,(unsigned char)*strSource-0x20);
strcat(strResult,"1");
}
else
{ //除小写的其他字母
strcati(strResult,(unsigned char)*strSource);
strcat(strResult,"0");
}
}
strSource++;
}
return strResult;
}
//getorder.def
LIBRARY GetOrder
DESCRIPTION 'Get Chinese Order Key ---Feng Xu'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
GetOrderString @2五、 在 应 用 程 序 中 使 用DLL
---- 我 们 在 编 译 建 立 动 态 连 接 库 后, 也 可 以 在 本 报 网 站 上 直 接 下 载。 将GETORDER.DLL 和 生 成 的 顺 序 值 文 件 全 部 拷 贝 入Windows 下 的System 目 录。
---- 在VB 和Access 中 使 用 需 先 在 全 局 模 块 中 作 如 下 声 明: Declare Function GetOrderString
Lib "getorder" (ByVal str _
As String, ByVal nNUM As Long) As String如在VF中使用也需要作类似声明。
DECLARE STRING GetOrderString IN GETORDER.DLL ;
AS GetOrderString STRING
strSource,INTEGER OrderType---- 之 后, 就 可 以 方 便 的 在 自 己 的 应 用 程 序 中 使 用GetOrderString 函 数, 通 过SQL 语 句 给 数 据 库 的 中 文 字 段 按 拼 音 或 笔 划 排 序。
六、 进 一 步 改 进
---- 本 文 只 提 供 在Windows 95 下 的 解 决 办 法, 可 以 通 过 修 改 取 字 符 串 顺 序 值 函 数 让 其 在Win 3.x 和DOS 下 使 用。
---- 最 后 需 要 特 别 注 意 的 是 微 软 的 汉 字 的 笔 画 数 排 序 和 我 们 一 般 所 说 的 笔 划 排 序 是 有 区 别 的, 微 软 的 汉 字 的 笔 画 数 排 序 是 先 按 笔 画 数 排, 同 笔 画 数 再 按 该 字 的UNICODE 的 码 点 值 排 序, 真 正 的 汉 字 笔 划 排 序 是 先 按 笔 划 数 排 序, 同 笔 划 数 再 按" 一 丨 丿 丶乛" 先 后 的 笔 顺 排 序。 所 以 要 彻 底 解 决 笔 划 排 序 问 题, 需 要 在 上 述 的 生 成 顺 序 值 文 件 时, 手 工 根 据《 汉 字 标 准 字 典》 在Execl 97 中 建 一 笔 顺 库, 然 后 按" 笔 划 数+ 笔 顺" 排 序 后 存 成GBKBH.TXT。
---- 如 果 我 们 有 这 样 一 个 顺 序 值 文 件, 其 中 的 顺 序 值 是 一 个 汉 字 按 某 种 排 序 方 式 下 在 整 个 字 符 集 中 的 次 序 值, 而 整 个 字 符 集 的 每 一 个 汉 字 的 顺 序 值 按 该 汉 字 的 内 码 值 得 先 后 顺 序 存 储。 并 将 不 同 的 排 序 方 式 的 次 序 值 集 合 存 储 为 不 同 的 顺 序 值 文 件。 这 样 我 们 可 以 像 访 问 不 同 汉 字 字 形 文 件 的 那 样 的 方 式, 方 便 的 取 得 每 一 个 汉 字 在 某 种 排 序 方 式 下 的 顺 序 值。 就 可 以 在 应 用 程 序 中 用 一 取 顺 序 值 函 数 按 自 己 想 要 的 排 序 方 法 对 一 系 列 的 字 串 排 序。 下 面 就 给 出 在Windows 95 下 用DLL 解 决 应 用 程 序 中 的 中 文 大 字 符 集 排 序 的 具 体 步 骤。
二、 获 取 大 字 符 集 文 本 文 件
---- 我 们 所 说 的 大 字 符 集 一 般 是 指ISO 10646.1 即 国GB 13000.1。 在Windows 95 中, 微 软 提 供 了" 汉 字 扩 展 内 码 规 范(GBK)" 解 决 汉 字 的 收 字 不 足、 简 繁 同 平 面 共 存、 简 化 代 码 体 系 间 转 换 等 汉 字 信 息 交 换 的 瓶 颈 问 题, 在 保 持 已 有 应 用 软 件 兼 容 性 的 前 提 下, 以 便 日 后 最 总 实 现ISO 160646.1。 利 用GBK 我 们 就 可 以 方 便 解 决"镕"、"碁" 等 大 量 汉 字 的 交 换 问 题 不 必 自 行 造 字 了。
---- GBK 的 码 位 分 配 总 体 采 用 了8140-FEFE 的 矩 形 区 域, 剔 除xx7F 一 条 线, 共23940 个 码 位。 用VC 实 现 的 获 取GBK 中 所 有 汉 字 字 符 的 程 序 清 单 如 下: // getgbk.cpp -获取GBK汉字码文件
#include
void main()
{
unsigned char oneline[4];
ofstream ofs( "GBKHZ.TXT", ios::binary );
oneline[2]=0x0D;
oneline[3]=0x0A; //换行符
for (int qm=0x81;qm<=0xFE;qm++) //区码0X81-0XFE
for (int wm=0x40;wm<=0xFE;wm++) //位码0X40-0XFE
if ((qm<=0xa0||qm>=0xaa)&& (wm!=0X7F) )
//剔除0xA1-0xA9区和位码为0x7F的区域
if ( !(wm>=0Xa1 && ( (qm>=0xaa && qm<=0xaf)||
(qm>=0xf8))))
//除去AAA1-AFFE和F8A1-FEFE两块矩形区域
if (! ((wm>=0xfa && qm==0xd7)|| (wm>=0X50 &&
qm==0xfe)))
//剔除D7FA-D7FE和FE50-FEFE
{
oneline[0]=qm; //汉字区码
oneline[1]=wm; //汉字位码
ofs.write( (char *) &oneline, 4);
//写一行至GBKHZ.TXT
} //if end
} //End of main()三、 生 成 顺 序 值 文 件
---- 我 们 在 获 得GBK 的 全 部 汉 字 码( 一 字 一 行)) 的 文 本 文 件 后, 运 行Microsoft Execl 97 打 开 文 本 文 件GBKHZ.TXT。 在 文 本 导 入 向 导 对 话 框 出 现 后 按〈 完 成〉 按 钮, 将 文 件 导 入 工 作 簿, 再 选 择" 数 据" 菜 单 中 的" 排 序..." 项, 在 排 序 对 话 框 出 现 后 按〈 选 项...〉 按 钮, 在 排 序 选 项 对 话 框 中 选 择 字 母 排 序 方 法 另 存 为GBKPY.TXT。 然 后 再 将 笔 划 排 序 方 法 另 存 为GBKBH.TXT。 如 有 自 定 义 汉 字 参 与 排 序 和 需 调 整 顺 序 的 汉 字 可 分 别 在 这 两 个 文 件 中 添 加 及 调 整。 下 列 源 程 序 实 现 将 这 两 种 排 序 的 文 本 文 件 生 成 顺 序 值 文 件GBKPY.ORD 和GBKBH.ORD。 为 了 使GBK 的 图 形 符 号 排 序 时 在 汉 字 之 前, 程 序 中 将 图 形 符 号 位 码 的 高 四 位 屏 蔽 作 为 顺 序 值 安 排 在0x01A1-0x09FE, 排 序 的 文 本 文 件 中 存 在 的 汉 字 顺 序 值 由 0x1001 开 始, 其 他 汉 字 以 原 区 位 码 值 为 顺 序 值 在 排 在 最 后。
// worder.cpp ----写汉字顺序值文件
#include
#include
int compare(unsigned short *x,unsigned short *y)
{
return(*x-*y); //比较相等返回0
}void main()
{
unsigned short key,*result;
_int16 int16result;
unsigned int I=0;
char *pFileName[][2]={"GBKPY.TXT","GBKPY.ORD",
"GBKBH.TXT","GBKBH.ORD"};
//定义拼音、笔划文本文件及顺序值文件名称
unsigned short onecode[50000]; //顺序值缓冲
for (int j=0;j<=1;j++)
{
ifstream ifs(pFileName[j][0], ios::binary );
ofstream ofs(pFileName[j][1], ios::binary);
while ( ifs.good() )
// EOF or failure stops the reading
{
ifs.read( (char *) &onecode[I], 4 );
I++;
}
I--;
for (int qm=0x81;qm<=0xFE;qm++) {
for (int wm=0x40;wm<=0xFE;wm++) {
key=wm*256+qm;
result=(unsigned short*)_lfind(&key,onecode,&I,2,
(int (__cdecl *)(const void *,const void *))
compare);
if (result!=NULL) //如在顺序值缓冲找到
{
int16result = result - onecode + 4097;
//顺序值由0x1001开始
ofs.write( (char *) &int16result,
sizeof(int16result)); //写入顺序值文件
}
else
if (((key&0x00ff)>=0x00a1 && (key&0x00ff)
< =0x00a7 && (key&0xff00)>=0xa100)
||(((key&0x00ff)==0x00a8 || (key&0x00ff)
==0x00a9)&&((key&0xff00)!=0x7f00)))
//如 key在图形符号区
{
int16result = key&0xff0f;
//key屏蔽位码高四位做顺序值
ofs.write( (char *) &int16result,
sizeof(int16result));
} else ofs.write( (char *) &key, 2);
//如key在用户自定义区顺序值即区位码
} //end for (int wm=0x40;wm<=0xFE;wm++)
} //end for (int qm=0x81;qm<=0xFE;qm++)
I=0; //缓冲指针清零
}
}四、 取 字 符 串 顺 序 值 的DLL
---- 我 们 在 获 得 两 个 顺 序 值 文 件 之 后 就 可 以 编 写 取 字 符 串 顺 序 值 的 函 数 了。 下 面 的 程 序 是 给 出 在Windows 95 下 用DLL 实 现 方 法, 需 要 说 明 的 是 为 了 支 持 中 西 文 混 合 字 串, 此 函 数 每 一 个 中 文 或 西 文 字 符 输 出 的 顺 序 值 均 四 字 节 字 符 串, 中 文 字 符 是 直 接 将 该 字 符 的 顺 序 值 转 换 成 字 串 输 出, 西 文 是 在 字 符 的ASCII 值 的 前 后 分 别 加"0", 如 是 西 文 字 符 是 小 写 字 母 则 转 换 为 大 写 加"1" 一 保 证 排 序 后 西 文 字 母 的 小 写 顺 序 值 总 是 紧 接 在 在 该 字 母 的 大 写 顺 序 值 之 后。 源 程 序 如 下:
//getorder.cpp ----取汉字顺序值的动态连接库
#include
#include
HANDLE hMapFile[2];
LPVOID pMapFile[2];void ReleaseOpenedFile(int OpenedFileNum)
{
UnmapViewOfFile(pMapFile[OpenedFileNum]);
CloseHandle(hMapFile[OpenedFileNum]);
}
BOOL WINAPI DllMain (HINSTANCE hDLL,
DWORD dwReason,LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
{
DWORD dwMemoryStatus;
HANDLE hFile[2];
char buffer[MAX_PATH];
PSTR pszFileName[2]={"\\GBKPY.ORD",
"\\GBKBH.ORD"};
for (int j=0;j<=1;j++) {
GetSystemDirectory (buffer, MAX_PATH);
strcat(buffer,pszFileName[j]);
if ((hFile[j] = CreateFile(buffer,
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
NULL)) == (HANDLE)-1)
{
MessageBox ( NULL,
(LPCTSTR) "Fail in opening file",
(LPCTSTR) "Error",MB_OK );
return FALSE;
}
if ((hMapFile[j] = CreateFileMapping(hFile[j],
NULL,PAGE_READONLY, 0, 0, NULL)) ==
(HANDLE)-1)
{
MessageBox ( NULL,
(LPCTSTR) "Fail in creating map file",
(LPCTSTR) "Error",MB_OK );
CloseHandle(hFile[j]);
for ( j--;j<0;j--)
ReleaseOpenedFile(j);
return FALSE;
}
CloseHandle(hFile[j]);
dwMemoryStatus=GetLastError();
if ((pMapFile[j] = MapViewOfFile(hMapFile[j],
FILE_MAP_READ, 0, 0, 0)) == NULL)
{
MessageBox ( NULL,(LPCTSTR)
"Fail in mapping view of the Map File object",
(LPCTSTR) "Error",MB_OK );
CloseHandle(hMapFile[j]);
for (j--;j<0;j--)
ReleaseOpenedFile(j);
return FALSE;
}
if (dwMemoryStatus==ERROR_ALREADY_EXISTS)
return FALSE;
}
return TRUE;
}
case DLL_PROCESS_DETACH:
for (int I=1;I<0;I--)
ReleaseOpenedFile(I);
break;
}
return TRUE;
}char *strcati( char *strDestination,
unsigned char cSource)
{
char cHaft;
cHaft=(cSource&0xf0)>>4;
if (cHaft<=9) cHaft+=48;
else cHaft+=55;
//十六进制转换为其ASCII字符
strncat(strDestination,&cHaft,1);
cHaft=cSource&0x0f;
if (cHaft<=9) cHaft+=48;
else cHaft+=55;
strncat(strDestination,&cHaft,1);
return strDestination;
}
CHAR * __stdcall GetOrderString
( char FAR *strSource,int OrderType)
{
if (OrderType!=0 && OrderType!=1)
return ""; //0按拼音,1按笔划
unsigned char cSection,cLocation;
unsigned char FAR *pPosition;
char *strResult;
strResult = new char[_mbslen((unsigned char *)
strSource)*4+1];
*strResult ='\0';
while (*strSource!=NULL)
{
if ((unsigned char)*strSource>=0x80)
{ //中文
cSection=(unsigned char)*strSource;
strSource++;
cLocation=(unsigned char)*strSource;
pPosition=(unsigned char FAR *)pMapFile[OrderType]+
((cSection-0x81)*191+cLocation-0x40)*2;
strcati(strResult,*(pPosition+1));
strcati(strResult,*pPosition);
}
else { //西文
strcat(strResult,"0");
if ((*strSource>=0x61)&&(*strSource<=0x7a))
{ //如是小写字母,转换成大写,最后一字节置为"1"
strcati(strResult,(unsigned char)*strSource-0x20);
strcat(strResult,"1");
}
else
{ //除小写的其他字母
strcati(strResult,(unsigned char)*strSource);
strcat(strResult,"0");
}
}
strSource++;
}
return strResult;
}
//getorder.def
LIBRARY GetOrder
DESCRIPTION 'Get Chinese Order Key ---Feng Xu'
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
GetOrderString @2五、 在 应 用 程 序 中 使 用DLL
---- 我 们 在 编 译 建 立 动 态 连 接 库 后, 也 可 以 在 本 报 网 站 上 直 接 下 载。 将GETORDER.DLL 和 生 成 的 顺 序 值 文 件 全 部 拷 贝 入Windows 下 的System 目 录。
---- 在VB 和Access 中 使 用 需 先 在 全 局 模 块 中 作 如 下 声 明: Declare Function GetOrderString
Lib "getorder" (ByVal str _
As String, ByVal nNUM As Long) As String如在VF中使用也需要作类似声明。
DECLARE STRING GetOrderString IN GETORDER.DLL ;
AS GetOrderString STRING
strSource,INTEGER OrderType---- 之 后, 就 可 以 方 便 的 在 自 己 的 应 用 程 序 中 使 用GetOrderString 函 数, 通 过SQL 语 句 给 数 据 库 的 中 文 字 段 按 拼 音 或 笔 划 排 序。
六、 进 一 步 改 进
---- 本 文 只 提 供 在Windows 95 下 的 解 决 办 法, 可 以 通 过 修 改 取 字 符 串 顺 序 值 函 数 让 其 在Win 3.x 和DOS 下 使 用。
---- 最 后 需 要 特 别 注 意 的 是 微 软 的 汉 字 的 笔 画 数 排 序 和 我 们 一 般 所 说 的 笔 划 排 序 是 有 区 别 的, 微 软 的 汉 字 的 笔 画 数 排 序 是 先 按 笔 画 数 排, 同 笔 画 数 再 按 该 字 的UNICODE 的 码 点 值 排 序, 真 正 的 汉 字 笔 划 排 序 是 先 按 笔 划 数 排 序, 同 笔 划 数 再 按" 一 丨 丿 丶乛" 先 后 的 笔 顺 排 序。 所 以 要 彻 底 解 决 笔 划 排 序 问 题, 需 要 在 上 述 的 生 成 顺 序 值 文 件 时, 手 工 根 据《 汉 字 标 准 字 典》 在Execl 97 中 建 一 笔 顺 库, 然 后 按" 笔 划 数+ 笔 顺" 排 序 后 存 成GBKBH.TXT。
解决方案 »
- delphi 操作系统号验证问题
- delphi 如何不让让程序往下执行
- 请教:已得到外部程序的某个按纽的句柄,可是它不接收BM_click及enter等信息,还没有办法点击它呢?
- 我在Delphi中如何调用厂商提供的Dll文件!
- Delphi中如何使用WIN32 API
- 请问一段代码(上万行)的执行速度如何测试出来?
- 这个异常是什么意思?EVariantError
- 下面为什么出错了?
- 老千,昨天那个问题好像不行, 今天一试还有个BUG
- 如何在程序中获取ORACLE数据库的日期。
- 叫雷劈我吧!!!!<dellphi5.x 电子商务篇>第二章第一个例子做成dll调试不成,exe可以.
- 求之不得,辗转翻侧
中国人民银行乌鲁木齐中心支行
夏昆
---- 在日常工作和生活中我们经常使用电子记事本查找个人通讯录信息,或在单位的应用程序中查询客户档案或业务资料,这个过程中往往需要输入大量的汉字信息,对于熟悉计算机的人这已经是一件头疼的事,那些不太熟悉计算机或根本不懂汉字输入的用户简直就望而生畏。作为对数据检索技术的一种新的尝试,作者探索使用汉字拼音的首字符序列作为检索关键字,这样,用户不必使用汉字,只须简单地键入要查询信息的每个汉字的拼音首字符即可。比如你想查找关键字“中国人民银行”,你只需要输入“zgrmyh”。作者希望通过下面的例子,为广大计算机同行起一个抛砖引玉的作用,让我们开发的程序更加便捷、好用。 ---- 原理很简单,找出汉字表中拼音首字符分别为“A”至“Z”的汉字内码范围,这样,对于要检索的汉字只需要检查它的内码位于哪一个首字符的范围内,就可以判断出它的拼音首字符。 ---- 程序更简单,包括3个控件:一个列表存放着所有待检索的信息;一个列表用于存放检索后的信息;一个编辑框用于输入检索关键字(即拼音首字符序列)。详细如下: ---- 1.进入Delphi创建一个新工程:Project1 ---- 2.在Form1上创建以下控件并填写属性: 控件类型 属性名称 属性值
Edit Name Search
ListBox Name SourceList
Items 输入一些字符串,如姓名等,用于提供检索数据
ListBox Name ResultList
---- 3.键入以下两个函数 // 获取指定汉字的拼音索引字母,如:“汉”的索引字母是“H”
function GetPYIndexChar( hzchar:string):char;
begin
case WORD(hzchar[1]) shl 8 + WORD(hzchar[2]) of
$B0A1..$B0C4 : result := 'A';
$B0C5..$B2C0 : result := 'B';
$B2C1..$B4ED : result := 'C';
$B4EE..$B6E9 : result := 'D';
$B6EA..$B7A1 : result := 'E';
$B7A2..$B8C0 : result := 'F';
$B8C1..$B9FD : result := 'G';
$B9FE..$BBF6 : result := 'H';
$BBF7..$BFA5 : result := 'J';
$BFA6..$C0AB : result := 'K';
$C0AC..$C2E7 : result := 'L';
$C2E8..$C4C2 : result := 'M';
$C4C3..$C5B5 : result := 'N';
$C5B6..$C5BD : result := 'O';
$C5BE..$C6D9 : result := 'P';
$C6DA..$C8BA : result := 'Q';
$C8BB..$C8F5 : result := 'R';
$C8F6..$CBF9 : result := 'S';
$CBFA..$CDD9 : result := 'T';
$CDDA..$CEF3 : result := 'W';
$CEF4..$D188 : result := 'X';
$D1B9..$D4D0 : result := 'Y';
$D4D1..$D7F9 : result := 'Z';
else
result := char(0);
end;
end;// 在指定的字符串列表SourceStrs中检索符合拼音索引字符串
PYIndexStr的所有字符串,并返回。
function SearchByPYIndexStr
( SourceStrs:TStrings;
PYIndexStr:string):string;
label NotFound;
var
i, j :integer;
hzchar :string;
begin
for i:=0 to SourceStrs.Count-1 do
begin
for j:=1 to Length(PYIndexStr) do
begin
hzchar:=SourceStrs[i][2*j-1]
+ SourceStrs[i][2*j];
if (PYIndexStr[j]<>'?') and
(UpperCase(PYIndexStr[j]) <>
GetPYIndexChar(hzchar)) then goto NotFound;
end;
if result='' then result := SourceStrs[i]
else result := result + Char
(13) + SourceStrs[i];
NotFound:
end;
end;4.增加编辑框Search的OnChange事件:
procedure TForm1.SearchChange(Sender: TObject);
var ResultStr:string;
begin
ResultStr:='';
ResultList.Items.Text := SearchByPYIndexStr
(Sourcelist.Items, Search.Text);
end;
---- 5.编译运行后,在编辑框Search中输入要查询字符串的拼音首字符序列,检索结果列表ResultList就会列出检索到的信息,检索中还支持“?”通配符,对于难以确定的的文字使用“?”替代位置,可以实现更复杂的检索。 ---- 本程序在Delphi4
/////////////////////////////////////////////////////////////////////////////
// FileName: PY.pas
//
// Copyright (C) 1999 By Zhang Qing
//
// You can use and modify it ,but please send me an email.
//
// E-Mail: [email protected]
/////////////////////////////////////////////////////////////////////////////
unit PY;interface
uses sysutils;// 获取汉字的拼音首字符,这个函数将用在GetPYIndexStr 中.
function GetPYIndexChar(strChinese: string; bUpCase: Boolean = True): char;// 获取多个汉字的拼音首字符组成的字符串.
function GetPYIndexStr(strChinese: string; bUpCase: Boolean = True): string;implementation////////////////////////////////////////////////////////////////////////////
// 函数: GetPYIndexChar(strChinese: string;bUpCase: Boolean = True): char;
//
// 函数功能:获取汉字的拼音首字符.
// 例: GetPYIndexChar('程') 将返回'C'.
//
// 注意:对于多于一个汉字的输入(string类型)只有第一个有效,但不会产生错误
// 例如,GetPYIndexChar('程序')也将返回'C'.
//
// 第二个参数决定返回大写还是小写 , 缺省为大写 .
////////////////////////////////////////////////////////////////////////////
function GetPYIndexChar(strChinese: string;bUpCase: Boolean = True): char;
begin
// 根据汉字表中拼音首字符分别为"A"至"Z"的汉字内码范围,
// 要检索的汉字只需要检查它的内码位于哪一个首字符的范围内,
// 就可以判断出它的拼音首字符。
case WORD(strChinese[1]) shl 8 + WORD(strChinese[2]) of
$B0A1..$B0C4 : result := 'A';
$B0C5..$B2C0 : result := 'B';
$B2C1..$B4ED : result := 'C';
$B4EE..$B6E9 : result := 'D';
$B6EA..$B7A1 : result := 'E';
$B7A2..$B8C0 : result := 'F';
$B8C1..$B9FD : result := 'G';
$B9FE..$BBF6 : result := 'H';
$BBF7..$BFA5 : result := 'J';
$BFA6..$C0AB : result := 'K';
$C0AC..$C2E7 : result := 'L';
$C2E8..$C4C2 : result := 'M';
$C4C3..$C5B5 : result := 'N';
$C5B6..$C5BD : result := 'O';
$C5BE..$C6D9 : result := 'P';
$C6DA..$C8BA : result := 'Q';
$C8BB..$C8F5 : result := 'R';
$C8F6..$CBF9 : result := 'S';
$CBFA..$CDD9 : result := 'T';
$CDDA..$CEF3 : result := 'W';
$CEF4..$D188 : result := 'X';
$D1B9..$D4D0 : result := 'Y';
$D4D1..$D7F9 : result := 'Z';
else
result := char(0);
end;
if not bUpCase then
begin // 转换为小写
result := Chr(Ord(result)+32);
end;
end;////////////////////////////////////////////////////////////////////////////
// 函数: GetPYIndexStr(strChinese: string;bUpCase: Boolean = True): string;
//
// 函数功能:获取多个汉字的拼音首字符组成的字符串.
// 例: GetPYIndexStr('程') 将返回'C'.
// GetPYIndexStr('程序')将返回'CX'.
//
// 第二个参数决定返回大写还是小写 , 缺省为大写 .
////////////////////////////////////////////////////////////////////////////
function GetPYIndexStr(strChinese: string;bUpCase: Boolean = True): string;
var
strChineseTemp : string;
cTemp : Char;
begin
result := '';
strChineseTemp := strChinese;
while strChineseTemp<>'' do
begin
cTemp := GetPYIndexChar(strChineseTemp);
if not bUpCase then
begin // 转换为小写
cTemp := Chr(Ord(cTemp)+32);
end;
result := result + string(cTemp);
strChineseTemp := Copy(strChineseTemp,3,Length(strChineseTemp));
end;
end;end.
重庆: cq
载重: zz
如果可以的话,请尽快给我一份,上面的那些方法我都试过了,对二级字库似乎无能为力.