在开发各类应用管理系统中,一般都要实现各种查询功能,如何准确、快速查找到符合条件的记录,是实现各种查询功能的重点。系统的实际开发过程中,查询功能一般都是通过对字符进行比较、判断等方法来实现。我们开发一个人事管理系统中过程中,系统要具有新的查询方式,即只要知道一个人姓名的读音,并不知道每个字的具体写法,通过检索数据库,就能把所有符合这个读音的记录内容全部显示出来。由于汉字存在着大量的同音字,采用常用的字符比较法,如查找一个名叫“李晓军”的人,数据库中存在的叫“李小君”的数据就不能查到,利用常用的查询方法实现不了同音字的查询功能。为了解决同音字的模糊查询问题,笔者借用WINDOWS系统下的输入法生成器,将系统中的拼音输入法字典库,生成了一个拼音查询字典库,利用这个拼音查询字典库,在使用VFP数据库管理系统编写的人事管理系统中,轻松实现了按语音进行模糊查询功能,具体思路如下:
---- 一、首先要生成一个拼音字典查询数据库
---- 选择WINDOWS系统的开始—程序—附件—输入法生成器,进入输入法生成器窗口,使用鼠标点击逆转换的页框,点击打开文件按钮,选中硬盘WINDOWS/SYSTEM文件夹下的WINPY.MB文件,在码表原文件中输入C:/WINPY.TXT,输入完毕后点击逆转换,此时系统对全拼字典库进行转换,最后将生成一个纯文本文件,利用这个纯文本文件编写一段小程序即可生成一个拼音字典查询数据库。
---- 二、进入VFP系统,编写一段生成程序命令为ZH.PRG
---- 程序中的内容如下所列:
---- CREA TABL B1 (NR C(60),HZ C(2),PY1 C(12),PY2 C(12))&&创建一个临时数据库
---- USE B1 &&打开生成的数据库
---- APPE FROM C:/WINPY.TXT SDF
---- &&将利用输入法生成器生成的字典码文件WINPY.TXT文件内容追加到数据库中
---- DELE FOR ASC(SUBS(NR,3,1)) >=128
---- &&在数据库中删除全部词组内容,只留下单字 DELE FOR RECN()< 13 &&在数据库删除编码库的头文件
---- PACK &&清除打了删除标记的记录。
---- REPL HZ WITH SUBS(NR,1,2),PY1 WITH SUBS(NR,3,AT(' ',NR)-2),;
---- PY2 WITH SUBS(NR,AT(' ',NR)+1) ALL
---- &&将汉字与拼音存放在不同的字段里,这里拼音有两个字段,其中有一个为同音字。
---- REPL NR1 WITH ‘s’+SUBS(NR1,3) FOR “sh”$NR1
---- &&为了照顾南方口音的人员使用,可将全部zh,ch,sh替换成z,c,s
---- REPL NR1 WITH ‘c’+SUBS(NR1,3) FOR “ch”$NR1
---- REPL NR1 WITH ‘z’+SUBS(NR1,3) FOR “zh”$NR1
---- REPL NR2 WITH ‘s’+SUBS(NR2,3) FOR “sh”$NR2
---- REPL NR2 WITH ‘c’+SUBS(NR2,3) FOR “ch”$NR2
---- REPL NR2 WITH ‘z’+SUBS(NR2,3) FOR “zh”$NR2
---- COPY TO PYZDK FIEL HZ,PY1,PY2 &&生成一个拼音查询数据库
---- USE &&关闭打开的数据库
---- ERASE 'B1.DBF' &&删除生成的临过数据库
---- 在VFP中命令窗口中,执行上面这段程序系统将自动生成一个拼音查询库,并将这个数据库命名为PYZDK.DBF。
---- 三、新建一个表单
---- 在数据环境中加入“人员情况表”和“PYZDK”,两个数据库,在人员情况表中存在需要有查询的人员姓名字段,字段名为NAME,标志位字段,字段名为BZW。
---- 在表单上新建一个LABEL1对象用来提示“请输入要查询的姓名”;一个文本框用来输入要查询的字符内容;一个表格对像,用来显示人员情况表数据库中的内容,两个命令按钮,COMMAND2用来执行查询过程文件,COMMAND1用来退出查询窗口。
---- COMMAND1命令按钮属性设置如下:
COMMAND1.CAPTION=’退出’
在COMMAND1命令按钮的.CLICK事件中写入代码
THISFORM.RELEASE
COMMAND2命令按钮属性设置如下:
COMMAND2.CAPTION=’开始查询’
在COMMAND2命令按钮的CLICK事件中写入代码:
IF THIS.CAPTION='开始查询'
THIS.CAPTION='恢复数据'
SRNR=ALLT(THISFORM.TEXT1.VALUE)
ZDD=LEN(SRNR)/2
DIME HH(100)
HH=''
FOR I=1 TO LEN(SRNR)/2
ABC=SUBS(SRNR,I*2-1,2)
SELE PYZDK
SET FILT TO
LOCA FOR ABC$HZ
PYNR1=PY1
PYNR2=PY2
IF PYNR2< >' '
SET FILT TO PY1=PYNR1 OR PY2=PYNR2
ELSE
SET FILT TO PY1=PYNR1
ENDIF
GO TOP
DO WHIL NOT EOF()
HH(I)=HH(I)+HZ
SKIP
ENDDO
ENDFOR
SELE 人员情况表
SET FILT TO
REPL BZW WITH '' ALL
GO TOP
DO WHIL NOT EOF()
JSQ=0
FOR I=1 TO LEN(ALLT(NAME))/2
IF SUBS(YXMM,I*2-1,2)$HH(I)
JSQ=JSQ+1
ENDIF
ENDFOR
IF JSQ=LEN(ALLT(NAME))/2 OR JSQ >=ZDD
REPL BZW WITH '*'
ENDIF
SKIP
ENDDO
SET FILT TO BZW="*"
THISFORM.REFRESH
ELSE
THIS.CAPTION='开始查询'
SELE 人员情况表
SET FILT TO
GO TOP
THISFORM.REFRESH
ENDIF
---- 全部设置完毕后,执行这个程序,在文本框中输入要查询的关键字,点击查询命令按钮,这时表格中显示的将是符合查询关键字的全部内容,再次点击这个命令按钮,表格中将恢复显示全部数据内容,点击退出系统命令按钮,将退出系统。
---- 四、查询程序实现的原理
---- 在系统中提供的编辑框中输入要查询的关键字,如果在一个人员数据库中查询一个姓名音为“李晓军”的人员,首先在生成的拼音查询数据库中找输入第一个汉字在字典库中的位置,利用这个汉字的读音,对字典库记录内容进行过滤,这样字典库中只有符合这个汉字读音的全部汉字,利用一个循环,将全部同音字相加生成一个字符串送到一个变量中,继续对另外输入的汉字进行同样的处理,最后根据输入汉字的多少,生成多个字符串变量。生成字符串变量后,开始检索你要查询的数据库,将数据库中每人的姓名拆开分别与生成的字符串进行判断,只有当数据库中一个人的姓名全部字符都能在相应的字符串中查找到,那么这条记录就符合查找的条件,打上一个标识,比较下一条记录,循环到数据库的结尾,这时就可以将所有做了查询标记的数据库内容显示出来,即实现了按语音模糊查询的方法。
---- 上面简要介绍了在VFP系统中,实现按语音模糊查询的一种方法,在程序中并没有考虑容错性,在这里只是提供了一种思路,读者根据以上实现语音查询的原理,根据实际工作的需要实现不同形式的语音模糊查询方式。
---- 一、首先要生成一个拼音字典查询数据库
---- 选择WINDOWS系统的开始—程序—附件—输入法生成器,进入输入法生成器窗口,使用鼠标点击逆转换的页框,点击打开文件按钮,选中硬盘WINDOWS/SYSTEM文件夹下的WINPY.MB文件,在码表原文件中输入C:/WINPY.TXT,输入完毕后点击逆转换,此时系统对全拼字典库进行转换,最后将生成一个纯文本文件,利用这个纯文本文件编写一段小程序即可生成一个拼音字典查询数据库。
---- 二、进入VFP系统,编写一段生成程序命令为ZH.PRG
---- 程序中的内容如下所列:
---- CREA TABL B1 (NR C(60),HZ C(2),PY1 C(12),PY2 C(12))&&创建一个临时数据库
---- USE B1 &&打开生成的数据库
---- APPE FROM C:/WINPY.TXT SDF
---- &&将利用输入法生成器生成的字典码文件WINPY.TXT文件内容追加到数据库中
---- DELE FOR ASC(SUBS(NR,3,1)) >=128
---- &&在数据库中删除全部词组内容,只留下单字 DELE FOR RECN()< 13 &&在数据库删除编码库的头文件
---- PACK &&清除打了删除标记的记录。
---- REPL HZ WITH SUBS(NR,1,2),PY1 WITH SUBS(NR,3,AT(' ',NR)-2),;
---- PY2 WITH SUBS(NR,AT(' ',NR)+1) ALL
---- &&将汉字与拼音存放在不同的字段里,这里拼音有两个字段,其中有一个为同音字。
---- REPL NR1 WITH ‘s’+SUBS(NR1,3) FOR “sh”$NR1
---- &&为了照顾南方口音的人员使用,可将全部zh,ch,sh替换成z,c,s
---- REPL NR1 WITH ‘c’+SUBS(NR1,3) FOR “ch”$NR1
---- REPL NR1 WITH ‘z’+SUBS(NR1,3) FOR “zh”$NR1
---- REPL NR2 WITH ‘s’+SUBS(NR2,3) FOR “sh”$NR2
---- REPL NR2 WITH ‘c’+SUBS(NR2,3) FOR “ch”$NR2
---- REPL NR2 WITH ‘z’+SUBS(NR2,3) FOR “zh”$NR2
---- COPY TO PYZDK FIEL HZ,PY1,PY2 &&生成一个拼音查询数据库
---- USE &&关闭打开的数据库
---- ERASE 'B1.DBF' &&删除生成的临过数据库
---- 在VFP中命令窗口中,执行上面这段程序系统将自动生成一个拼音查询库,并将这个数据库命名为PYZDK.DBF。
---- 三、新建一个表单
---- 在数据环境中加入“人员情况表”和“PYZDK”,两个数据库,在人员情况表中存在需要有查询的人员姓名字段,字段名为NAME,标志位字段,字段名为BZW。
---- 在表单上新建一个LABEL1对象用来提示“请输入要查询的姓名”;一个文本框用来输入要查询的字符内容;一个表格对像,用来显示人员情况表数据库中的内容,两个命令按钮,COMMAND2用来执行查询过程文件,COMMAND1用来退出查询窗口。
---- COMMAND1命令按钮属性设置如下:
COMMAND1.CAPTION=’退出’
在COMMAND1命令按钮的.CLICK事件中写入代码
THISFORM.RELEASE
COMMAND2命令按钮属性设置如下:
COMMAND2.CAPTION=’开始查询’
在COMMAND2命令按钮的CLICK事件中写入代码:
IF THIS.CAPTION='开始查询'
THIS.CAPTION='恢复数据'
SRNR=ALLT(THISFORM.TEXT1.VALUE)
ZDD=LEN(SRNR)/2
DIME HH(100)
HH=''
FOR I=1 TO LEN(SRNR)/2
ABC=SUBS(SRNR,I*2-1,2)
SELE PYZDK
SET FILT TO
LOCA FOR ABC$HZ
PYNR1=PY1
PYNR2=PY2
IF PYNR2< >' '
SET FILT TO PY1=PYNR1 OR PY2=PYNR2
ELSE
SET FILT TO PY1=PYNR1
ENDIF
GO TOP
DO WHIL NOT EOF()
HH(I)=HH(I)+HZ
SKIP
ENDDO
ENDFOR
SELE 人员情况表
SET FILT TO
REPL BZW WITH '' ALL
GO TOP
DO WHIL NOT EOF()
JSQ=0
FOR I=1 TO LEN(ALLT(NAME))/2
IF SUBS(YXMM,I*2-1,2)$HH(I)
JSQ=JSQ+1
ENDIF
ENDFOR
IF JSQ=LEN(ALLT(NAME))/2 OR JSQ >=ZDD
REPL BZW WITH '*'
ENDIF
SKIP
ENDDO
SET FILT TO BZW="*"
THISFORM.REFRESH
ELSE
THIS.CAPTION='开始查询'
SELE 人员情况表
SET FILT TO
GO TOP
THISFORM.REFRESH
ENDIF
---- 全部设置完毕后,执行这个程序,在文本框中输入要查询的关键字,点击查询命令按钮,这时表格中显示的将是符合查询关键字的全部内容,再次点击这个命令按钮,表格中将恢复显示全部数据内容,点击退出系统命令按钮,将退出系统。
---- 四、查询程序实现的原理
---- 在系统中提供的编辑框中输入要查询的关键字,如果在一个人员数据库中查询一个姓名音为“李晓军”的人员,首先在生成的拼音查询数据库中找输入第一个汉字在字典库中的位置,利用这个汉字的读音,对字典库记录内容进行过滤,这样字典库中只有符合这个汉字读音的全部汉字,利用一个循环,将全部同音字相加生成一个字符串送到一个变量中,继续对另外输入的汉字进行同样的处理,最后根据输入汉字的多少,生成多个字符串变量。生成字符串变量后,开始检索你要查询的数据库,将数据库中每人的姓名拆开分别与生成的字符串进行判断,只有当数据库中一个人的姓名全部字符都能在相应的字符串中查找到,那么这条记录就符合查找的条件,打上一个标识,比较下一条记录,循环到数据库的结尾,这时就可以将所有做了查询标记的数据库内容显示出来,即实现了按语音模糊查询的方法。
---- 上面简要介绍了在VFP系统中,实现按语音模糊查询的一种方法,在程序中并没有考虑容错性,在这里只是提供了一种思路,读者根据以上实现语音查询的原理,根据实际工作的需要实现不同形式的语音模糊查询方式。