CreateLib.cpp
上传用户:hyb6888
上传日期:2016-01-24
资源大小:5186k
文件大小:13k
- // reateLib.cpp: implementation of the CreateLib class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "CreateLib.h"
- #include "stdio.h"
- #include "malloc.h"
- char ms[1000];
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CreateLib::CreateLib()
- {
- pChHead=new mynode[20000];
- LIBlonEnCh=0;
- LIBnum=0;
- }
- CreateLib::~CreateLib()
- {
- delete []pChHead;
- }
- //////////////////////////////////////////////////////////////////
- // 建立码表程序部分
- //
- //外部条件: 需要CA结点结构,
- int CreateLib::CreatChiLib(char *CodeSource,char *userdefine,char *ExCodeSource,char *outfname,long Locbase, long LocGoldeNum, long LocGoldeLen)
- {
- int i;
- long tt;
- unsigned long clon=0,lon=0,countAdd;
- char ss[1000];
- FILE *fp;
- int hnum ;
- tool mytool;
- HANDLE houtfile;
- DWORD retbyteNum;
- this->Base=Locbase;
- this->GoldeLen=LocGoldeLen;
- this->GoldeNum=GoldeNum;
- if(Base>1000 || GoldeLen>1000 || GoldeNum>1000){
- sprintf(ms,"Base:%d GoldeLen:%d GoldeNum:%d",Base,GoldeLen,GoldeNum);
- MessageBox(0,ms,"参数错",0);
- return -1;
- }
- this->Base=Locbase;
- this->GoldeLen=LocGoldeLen;
- this->GoldeNum=LocGoldeNum;
- //如遇更大数据可用头三字符确定头结点
- //LocGoldeNum=27时,使用头二个字符本变量为729,头三个19683,但要视变量而定LocGoldeNum
- hnum=Sqrt(LocGoldeNum,3);
- for(i=0;i<hnum+1;i++)//头接点设置
- {
- pChHead[i].Next=NULL;
- pChHead[i].Enstr=NULL;
- pChHead[i].Chistr=NULL;
- }
- //////////////////////////////////////////////////////////
- //先为用户词库、五笔词库、扩展词库
- sprintf(ss,"%s",userdefine);
- fp=fopen(ss, "r"); /*打开附加文件*/
- if(fp==NULL){
- sprintf(ss,"CreatChiLib函数装载附加文件失败:n%s",userdefine);
- MessageBox(0,ss,"源文件没找到",0);
- return -1;
- }
- //由源文件生成结点。
- if(CreatNode(fp)!=0)//用户词库
- return 0;
- ///////////////////////////////////////////////////////////
- fp=fopen(CodeSource, "r"); /*打开主库文件只读*/
- if(fp==NULL){
- sprintf(ss,"CreatChiLib函数装载n%sn文件失败",CodeSource);
- MessageBox(0,ss,"源文件没找到",0);
- return -1;
- }
- //由源文件生成结点。
- if(CreatNode(fp)!=0)//主词库
- return 0;
- ///////////////////////////////////////////////////////////
- fp=fopen(ExCodeSource, "r"); /*打开扩展文件*/
- if(fp==NULL){
- sprintf(ss,"CreatChiLib函数装载n%sn文件失败",ExCodeSource);
- MessageBox(0,ss,"源文件没找到",0);
- return -1;
- }
- //由源文件生成结点。
- if(CreatNodeEx(fp,&mytool)!=0)//扩展词库
- return 0;
- /////////////////////////////////////////////////////////////////
- //代码写入文件中;
- //由于outfname可能处于映射中,不能用fopen独占打开。
- //输出数据占用时间较少可不必进行改进,
- //需改进生成结点程序,它占用了80%以上的时间。
- houtfile=CreateFile(outfname,
- GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ ,NULL,
- OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if(houtfile==INVALID_HANDLE_VALUE)
- {
- sprintf(ss,"CreatChiLib函数装载n%sn文件失败",outfname);
- MessageBox(0,ss,"输出文件不能打开",0);
- return -1;
- }
- {
- long headlon;
- headlon=32;
- tt=headlon;
- WriteFile(houtfile,&tt,4,&retbyteNum,0); // headlon;
- WriteFile(houtfile,&LIBnum,4,&retbyteNum,0); // 输出索引个数 IndexNum
- tt=1000;
- WriteFile(houtfile,&tt,4,&retbyteNum,0); // NullIndex;
- tt=headlon+LIBnum*4+4000;
- WriteFile(houtfile,&tt,4,&retbyteNum,0); //字库Start
- WriteFile(houtfile,&LIBlonEnCh,4,&retbyteNum,0); //输出字库长度
- tt=headlon+LIBnum*4+4000+LIBlonEnCh;
- WriteFile(houtfile,&tt,4,&retbyteNum,0);//ExCodeStart
- tt=mytool.NodeNum*5;
- WriteFile(houtfile,&tt,4,&retbyteNum,0);//ExCodelong
- tt=headlon+LIBnum*4+4000+LIBlonEnCh+mytool.NodeNum*5;
- WriteFile(houtfile,&tt,4,&retbyteNum,0);//FileLong
- }
- //输出索引
- countAdd=0;
- for(i=0;i<hnum;i++)
- if(pChHead[i].Next!=NULL)
- countAdd=writeIndex(&pChHead[i],houtfile,countAdd);
- //输出空索引1000个
- tt=0;
- for(i=0;i<1000;i++)
- WriteFile(houtfile,&tt,4,&retbyteNum,0);//FileLong
- //输出字库
- for(i=0;i<hnum;i++)
- if(pChHead[i].Next!=NULL)
- writeChLib(&pChHead[i],houtfile);
- //输出识别码
- mytool.OutExCode(houtfile);
- CloseHandle(houtfile);
- return 0;
- }
- //输出地址
- //返回值已计数地址
- unsigned long CreateLib::writeIndex(mynode *pHead, HANDLE outfp, unsigned long count)
- {
- mynode *h;
- unsigned long PC;
- DWORD retbyteNum;
- h=pHead->Next;
- while(h!=NULL)
- {
- PC=count;
- WriteFile(outfp,&PC,4,&retbyteNum,0);
- count+=h->len;
- h=h->Next;
- }
- return count;
- }
- //输出中文字库
- CreateLib::writeChLib(mynode *pHead, HANDLE outfp)
- {
- mynode *h;
- DWORD retbyteNum;
- char ss[2000],*p,*pp;
- h=pHead->Next;
- while(h!=NULL) //中文
- {
- strcpy(ss,h->Enstr);
- p=ss;
- pp=p;
- pp+=strlen(ss)+1;
- if(h->Chistr!=NULL)
- {
- strcpy(pp,h->Chistr);
- pp+=strlen(h->Chistr)+1;
- }
- else
- {
- strcpy(pp,"");
- pp++;
- }
- if(h->ChistrEx!=NULL)
- {
- strcpy(pp,h->ChistrEx);
- pp+=strlen(h->ChistrEx)+1;
- }
- else
- {
- strcpy(pp,"");
- pp++;
- }
- WriteFile(outfp,p,h->len,&retbyteNum,0);
- h=h->Next;
- }
- return 0;
- }
- //新接点插入
- //返回为2,说明结点重复,直接余去
- //返回为1,说明结点被合并。
- //返回为0,说明结点成功插入
- CreateLib::inertNewdnode(mynode *NP, mynode *pHead)
- {
- mynode *P;
- char *ss, *cc,*rep;//由于拼音之类的重码多,会tg很快大于1000
- int ret=0, reptrue,h=0;
- NP->len=strlen(NP->Chistr)+strlen(NP->Enstr)+3;
- P=pHead;
- while(1)//大字库的90%时间主要消耗在这里.
- {
- h++;
- if(P->Next==NULL)
- break;
- else
- if(strcmp(P->Next->Enstr, NP->Enstr)>=0)//如果相等也要后移
- break;
- else
- P=P->Next;
- }
- //P结束于比它小者,或者后面为空的结点之前。
- //if(strcmp("LKAN",strupr(NP->Enstr))==0)
- // MessageBox(0,NP->Enstr,"00",0);
- if(P->Next==NULL|| P->Next==0)
- {
- P->Next=NP;
- }
- else
- {
- if(strcmp(P->Next->Enstr, NP->Enstr)==0)//英文相同
- {
- reptrue=0;
- strlen(P->Next->Chistr);
- cc=new char[(strlen(NP->Chistr)+strlen(P->Next->Chistr)+2)];
- strcpy(cc,P->Next->Chistr);
- rep = strtok(cc, ";"); //判断编码是否重复
- while(rep){
- if(strcmp(rep,NP->Chistr)==0)
- reptrue=1;
- rep = strtok(NULL, ";");
- }
- if(reptrue) //编码和汉字串相等则直接余
- ret=2;
- else //编码相同则合并编码
- { //为了简便,汉字串的空间不释放,直接余弃
- ss=new char[(strlen(NP->Chistr)+strlen(P->Next->Chistr)+2)];
- strcpy(ss,P->Next->Chistr);
- strcat(ss,";");
- strcat(ss,NP->Chistr);
- P->Next->Chistr=ss;
- P->Next->len+=strlen(NP->Chistr)+1;//加上新结点的长度
- ret=1;
- }
- }
- else //英文不同
- {
- NP->Next=P->Next;
- P->Next=NP;
- }
- }
- return ret;
- }
- //新接点插入
- //返回为2,说明结点重复,直接余去
- //返回为1,说明结点被合并。
- //返回为3,说明结点直拉挂在扩展区
- //返回为0,说明结点成功插入
- CreateLib::inertNewdnodeEx(mynode *NP, mynode *pHead)
- {
- mynode *P;
- char *ss, *cc,*rep;//由于拼音之类的重码多,会tg很快大于1000
- int ret=0, reptrue,h=0,lon;
- NP->len=strlen(NP->ChistrEx)+strlen(NP->Enstr)+3;
- P=pHead;
- while(1)//大字库的90%时间主要消耗在这里.
- {
- h++;
- if(P->Next==NULL)
- break;
- else
- if(strcmp(P->Next->Enstr, NP->Enstr)>=0)//如果相等也要后移
- break;
- else
- P=P->Next;
- }
- //P结束于比它小者,或者后面为空的结点之前。
- //if(strcmp("LKAN",strupr(NP->Enstr))==0)
- // MessageBox(0,NP->Enstr,"00",0);
- if(P->Next==NULL|| P->Next==0)
- {
- P->Next=NP;
- }
- else
- {
- if(strcmp(P->Next->Enstr, NP->Enstr)==0)//英文相同
- {
- reptrue=0;
- if(P->Next->ChistrEx!=NULL)
- {
- //strlen(P->Next->ChistrEx);
- lon=strlen(NP->ChistrEx)+strlen(P->Next->ChistrEx)+2;
- cc=new char[lon];
- strcpy(cc,P->Next->ChistrEx);
- }
- else
- {
- lon=strlen(NP->ChistrEx)+2;
- cc=new char[(strlen(NP->ChistrEx)+2)];
- strcpy(cc,"");
- }
- rep = strtok(cc, ";"); //判断编码是否重复
- while(rep){
- if(strcmp(rep,NP->ChistrEx)==0)
- reptrue=1;
- rep = strtok(NULL, ";");
- }
- if(reptrue) //编码和汉字串相等则直接余
- ret=2;
- else //编码相同则合并编码
- { //为了简便,汉字串的空间不释放,直接余弃
- if(P->Next->ChistrEx!=NULL)
- {
- ss=new char[lon];
- strcpy(ss,P->Next->ChistrEx);
- strcat(ss,";");
- strcat(ss,NP->ChistrEx);
- P->Next->ChistrEx=ss;
- P->Next->len+=strlen(NP->ChistrEx)+1;//加上新结点的长度
- ret=1;
- }
- else
- {
- ss=new char[lon];
- strcpy(ss,NP->ChistrEx);
- P->Next->ChistrEx=ss;
- P->Next->len+=strlen(NP->ChistrEx)+1;//加上新结点的长度
- if(P->Next->Chistr!=NULL) //
- P->Next->len--;
- ret=3;
- }
- }
- }
- else //英文不同
- {
- NP->Next=P->Next;
- P->Next=NP;
- }
- }
- return ret;
- }
- //求平方
- unsigned long CreateLib::Sqrt(long num, int p)
- {
- int i;
- unsigned long ret=1;
- for(i=0;i<p;i++)
- {
- ret=ret*num;
- }
- return ret;
- }
- //由指定的编码转换成头接点号。供建立结点时找头结点用
- long CreateLib::getheadID(char *ss, long lon)
- {
- long i,n,ret=0;
- char s1[100];
- strcpy(s1,ss);
- strupr(s1);
- n=strlen(ss);
- for(i=0;i<lon&&i<n;i++)
- {
- ret+=(s1[i]-Base)*Sqrt(GoldeNum,lon-1-i);
- }
- if(ret<0)
- MessageBox(0,"getheadID",0,0);
- return ret;
- }
- //将文件中的原编码形成结点,分发到不同头结点中
- // 返回为0表示成功,为1表示失败。
- //GoldeNum 为编码长度 GoldeLen为编码数
- int CreateLib::CreatNode(FILE *fp)
- {
- int tt; //tt用于判断文件是否结束
- int t; //t用于判断结点插入情况
- int count=0,ret=0;
- int sslon,codelon;
- char ss[1000],code[200];
- char cc[1000];
- mynode *NP ;
-
- tt=fscanf(fp,"%s %s",code,ss);
- while(tt>-1)
- {
- sslon=strlen(ss);
- codelon=strlen(code);
- if(codelon==0||sslon==0){
- sprintf(cc,"代码:%s n汉字串为:%s n位置:%d ",code,ss,LIBnum);
- MessageBox(0,cc,"代码或字串为空",0);
- ret=1;
- break;
- }
- /*
- if(codelon>GoldeLen){
- sprintf(cc,"代码:%s n汉字串为:%s n位置:%d n GoldeLen指定为:%d",code,ss,LIBnum,GoldeLen);
- MessageBox(0,cc,"代码长度大于GoldeLen中的指定值",0);
- ret=1;
- break;
- }*/
- ht=getheadID(code,3);
- //由头二个字符确定头接点,本变量为2,头三个3
- //*******************准备新结点***************************
- NP=new mynode;//分配新结点
- strupr(code); //将代码变成大写,否则会发生冲突不同代码计算出相等值;
- NP->Enstr=(char *)malloc(codelon+1);//汉字串
- strcpy(NP->Enstr,code);
-
- NP->Chistr=(char *)malloc( sslon+1);//汉字串
- strcpy(NP->Chistr,ss);
- NP->Next=NULL;
- NP->len=codelon+sslon+2;
- //*******************新结点就序***************************
- //大约占1/5时间
- t=inertNewdnode(NP,&pChHead[ht]);//新接点插入
- if(t==0){
- LIBnum++; //统计结点个数
- LIBlonEnCh+=strlen(ss)+strlen(code)+3; //计算下一个代码地址.
- }
- else//为2就不处理直接放弃
- if(t==1) //英文代码相等
- {
- LIBlonEnCh+=strlen(ss)+1;
- }
- tt=fscanf(fp,"%s %s",code,ss);
- }
- fclose(fp);//关闭源文件
- return ret;
- }
- //将文件中的原编码形成结点,分发到不同头结点中
- // 返回为0表示成功,为1表示失败。
- //GoldeNum 为编码长度 GoldeLen为编码数
- //mytool的主要目的是接收扩展识别码
- int CreateLib::CreatNodeEx(FILE *fp,tool *mytool)
- {
- int tt; //tt用于判断文件是否结束
- int t; //t用于判断结点插入情况
- int count=0,ret=0;
- int sslon,codelon;
- char ss[1000],code[200];
- char cc[1000];
- mynode *NP ;
- tt=fscanf(fp,"%s %s",code,ss);
- while(tt>-1)
- {
- sslon=strlen(ss);
- codelon=strlen(code);
- if(codelon==0||sslon==0){
- sprintf(cc,"代码:%s n汉字串为:%s n位置:%d ",code,ss,LIBnum);
- MessageBox(0,cc,"代码或字串为空",0);
- ret=1;
- break;
- }
- ht=getheadID(code,3);
- //由头二个字符确定头接点,本变量为2,头三个3
- //*******************准备新结点***************************
- NP=new mynode; //分配新结点
- strupr(code); //将代码变成大写,否则会发生冲突不同代码计算出相等值;
- NP->Enstr=(char *)malloc(codelon+1);//汉字串
- strcpy(NP->Enstr,code);
- mytool->InsertStr(code); //插入识别码库
-
- NP->ChistrEx=(char *)malloc( sslon+1);//汉字串
- strcpy(NP->ChistrEx,ss);
- NP->Next=NULL;
- NP->len=codelon+sslon+2;
- //*******************新结点就序***************************
- //大约占4/5时间
- t=inertNewdnodeEx(NP,&pChHead[ht]);//新接点插入
- if(t==0){
- LIBnum++; //统计结点个数
- LIBlonEnCh+=strlen(ss)+strlen(code)+3; //计算下一个代码地址.
- }
- else//为2就不处理直接放弃
- {
- if(t==1) //英文代码相等
- {
- LIBlonEnCh+=strlen(ss)+1;
- }
- if(t==3) //直接挂在扩展区
- {
- LIBlonEnCh+=strlen(ss);
- }
- }
- tt=fscanf(fp,"%s %s",code,ss);
- }
- fclose(fp);//关闭源文件
- return ret;
- }