CreateLib.cpp
上传用户:hyb6888
上传日期:2016-01-24
资源大小:5186k
文件大小:13k
源码类别:

输入法编程

开发平台:

Visual C++

  1. // reateLib.cpp: implementation of the CreateLib class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "CreateLib.h"
  6. #include "stdio.h"
  7. #include "malloc.h"
  8. char ms[1000];
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. CreateLib::CreateLib()
  13. {
  14. pChHead=new mynode[20000];
  15. LIBlonEnCh=0;
  16. LIBnum=0;
  17. }
  18. CreateLib::~CreateLib()
  19. {
  20. delete []pChHead;
  21. }
  22. //////////////////////////////////////////////////////////////////
  23. //              建立码表程序部分
  24. //
  25. //外部条件:  需要CA结点结构,
  26. int CreateLib::CreatChiLib(char *CodeSource,char *userdefine,char *ExCodeSource,char *outfname,long Locbase, long LocGoldeNum, long LocGoldeLen)
  27. {
  28. int i; 
  29. long tt;
  30. unsigned long clon=0,lon=0,countAdd;
  31. char ss[1000];
  32. FILE  *fp; 
  33. int hnum ;
  34. tool mytool;
  35. HANDLE  houtfile;
  36. DWORD retbyteNum;
  37. this->Base=Locbase;
  38. this->GoldeLen=LocGoldeLen;
  39. this->GoldeNum=GoldeNum;
  40. if(Base>1000 || GoldeLen>1000 || GoldeNum>1000){
  41.  sprintf(ms,"Base:%d   GoldeLen:%d   GoldeNum:%d",Base,GoldeLen,GoldeNum);
  42.  MessageBox(0,ms,"参数错",0);
  43.  return -1;
  44. }
  45. this->Base=Locbase;
  46. this->GoldeLen=LocGoldeLen;
  47. this->GoldeNum=LocGoldeNum;
  48.    //如遇更大数据可用头三字符确定头结点
  49.    //LocGoldeNum=27时,使用头二个字符本变量为729,头三个19683,但要视变量而定LocGoldeNum
  50.    hnum=Sqrt(LocGoldeNum,3);
  51.    for(i=0;i<hnum+1;i++)//头接点设置
  52.    {
  53.    pChHead[i].Next=NULL;
  54.    pChHead[i].Enstr=NULL;
  55.    pChHead[i].Chistr=NULL;
  56.    }
  57.    //////////////////////////////////////////////////////////
  58.    //先为用户词库、五笔词库、扩展词库
  59.    sprintf(ss,"%s",userdefine);
  60.    fp=fopen(ss, "r");    /*打开附加文件*/ 
  61.    if(fp==NULL){
  62.   sprintf(ss,"CreatChiLib函数装载附加文件失败:n%s",userdefine);
  63.       MessageBox(0,ss,"源文件没找到",0);
  64.   return -1;
  65. }
  66.     //由源文件生成结点。
  67.    if(CreatNode(fp)!=0)//用户词库
  68.    return 0;
  69.    ///////////////////////////////////////////////////////////
  70.    fp=fopen(CodeSource, "r");    /*打开主库文件只读*/ 
  71.    if(fp==NULL){
  72.   sprintf(ss,"CreatChiLib函数装载n%sn文件失败",CodeSource);
  73.       MessageBox(0,ss,"源文件没找到",0);
  74.   return -1;
  75. }
  76.    //由源文件生成结点。
  77.    if(CreatNode(fp)!=0)//主词库
  78.    return 0;
  79.    ///////////////////////////////////////////////////////////
  80. fp=fopen(ExCodeSource, "r");    /*打开扩展文件*/ 
  81.     if(fp==NULL){
  82.    sprintf(ss,"CreatChiLib函数装载n%sn文件失败",ExCodeSource);
  83.        MessageBox(0,ss,"源文件没找到",0);
  84.    return -1;
  85. }
  86.    //由源文件生成结点。
  87.    if(CreatNodeEx(fp,&mytool)!=0)//扩展词库
  88.    return 0;
  89.     /////////////////////////////////////////////////////////////////
  90.     //代码写入文件中;
  91. //由于outfname可能处于映射中,不能用fopen独占打开。
  92. //输出数据占用时间较少可不必进行改进,
  93. //需改进生成结点程序,它占用了80%以上的时间。
  94.     houtfile=CreateFile(outfname,
  95. GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ ,NULL,
  96. OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  97. if(houtfile==INVALID_HANDLE_VALUE)
  98. {
  99.     sprintf(ss,"CreatChiLib函数装载n%sn文件失败",outfname);
  100.         MessageBox(0,ss,"输出文件不能打开",0);
  101. return -1;
  102. }
  103. {
  104. long headlon;
  105. headlon=32;
  106. tt=headlon;
  107. WriteFile(houtfile,&tt,4,&retbyteNum,0);        // headlon;
  108.     WriteFile(houtfile,&LIBnum,4,&retbyteNum,0);    // 输出索引个数      IndexNum
  109. tt=1000;
  110. WriteFile(houtfile,&tt,4,&retbyteNum,0);        // NullIndex;
  111. tt=headlon+LIBnum*4+4000;
  112. WriteFile(houtfile,&tt,4,&retbyteNum,0);    //字库Start
  113.     WriteFile(houtfile,&LIBlonEnCh,4,&retbyteNum,0);   //输出字库长度
  114. tt=headlon+LIBnum*4+4000+LIBlonEnCh;
  115. WriteFile(houtfile,&tt,4,&retbyteNum,0);//ExCodeStart
  116. tt=mytool.NodeNum*5;
  117. WriteFile(houtfile,&tt,4,&retbyteNum,0);//ExCodelong
  118. tt=headlon+LIBnum*4+4000+LIBlonEnCh+mytool.NodeNum*5;
  119. WriteFile(houtfile,&tt,4,&retbyteNum,0);//FileLong
  120. }
  121.     //输出索引
  122. countAdd=0;
  123. for(i=0;i<hnum;i++)         
  124. if(pChHead[i].Next!=NULL)
  125. countAdd=writeIndex(&pChHead[i],houtfile,countAdd); 
  126.     //输出空索引1000个
  127. tt=0;
  128. for(i=0;i<1000;i++)  
  129. WriteFile(houtfile,&tt,4,&retbyteNum,0);//FileLong
  130.     //输出字库
  131. for(i=0;i<hnum;i++)         
  132. if(pChHead[i].Next!=NULL)
  133. writeChLib(&pChHead[i],houtfile);  
  134. //输出识别码
  135.     mytool.OutExCode(houtfile);
  136. CloseHandle(houtfile);
  137. return 0;
  138. }
  139. //输出地址
  140. //返回值已计数地址
  141. unsigned long CreateLib::writeIndex(mynode *pHead, HANDLE outfp, unsigned long count)
  142. {
  143. mynode *h;
  144. unsigned long PC;
  145. DWORD retbyteNum;
  146. h=pHead->Next;
  147. while(h!=NULL)
  148. {
  149. PC=count;
  150. WriteFile(outfp,&PC,4,&retbyteNum,0);
  151. count+=h->len;
  152. h=h->Next;
  153. }
  154. return count;
  155. }
  156.  //输出中文字库
  157. CreateLib::writeChLib(mynode *pHead, HANDLE outfp)
  158. {  
  159. mynode *h;
  160. DWORD retbyteNum;
  161. char ss[2000],*p,*pp;
  162.     h=pHead->Next;
  163. while(h!=NULL)   //中文
  164. {
  165. strcpy(ss,h->Enstr);
  166. p=ss;
  167. pp=p;
  168. pp+=strlen(ss)+1;
  169. if(h->Chistr!=NULL)
  170. {
  171. strcpy(pp,h->Chistr);
  172. pp+=strlen(h->Chistr)+1;
  173. }
  174. else
  175. {
  176. strcpy(pp,"");
  177. pp++;
  178. }
  179. if(h->ChistrEx!=NULL)
  180. {
  181. strcpy(pp,h->ChistrEx);
  182. pp+=strlen(h->ChistrEx)+1;
  183. }
  184. else
  185. {
  186. strcpy(pp,"");
  187. pp++;
  188. }
  189. WriteFile(outfp,p,h->len,&retbyteNum,0);
  190. h=h->Next;
  191. }
  192.   return 0;
  193. }
  194. //新接点插入
  195. //返回为2,说明结点重复,直接余去
  196. //返回为1,说明结点被合并。
  197. //返回为0,说明结点成功插入
  198. CreateLib::inertNewdnode(mynode *NP, mynode *pHead)
  199. {
  200. mynode *P;
  201. char *ss, *cc,*rep;//由于拼音之类的重码多,会tg很快大于1000
  202. int ret=0, reptrue,h=0;
  203. NP->len=strlen(NP->Chistr)+strlen(NP->Enstr)+3;
  204. P=pHead;
  205. while(1)//大字库的90%时间主要消耗在这里.
  206. {
  207. h++;
  208.   if(P->Next==NULL)
  209.   break;
  210.   else
  211. if(strcmp(P->Next->Enstr, NP->Enstr)>=0)//如果相等也要后移
  212. break;
  213. else
  214. P=P->Next;
  215. }
  216. //P结束于比它小者,或者后面为空的结点之前。
  217.     //if(strcmp("LKAN",strupr(NP->Enstr))==0)
  218. // MessageBox(0,NP->Enstr,"00",0);
  219. if(P->Next==NULL|| P->Next==0)
  220. {
  221. P->Next=NP;
  222. }
  223. else
  224. {
  225. if(strcmp(P->Next->Enstr, NP->Enstr)==0)//英文相同
  226. {
  227. reptrue=0;
  228. strlen(P->Next->Chistr);
  229.     cc=new char[(strlen(NP->Chistr)+strlen(P->Next->Chistr)+2)];
  230. strcpy(cc,P->Next->Chistr);
  231. rep = strtok(cc, ";"); //判断编码是否重复
  232. while(rep){
  233. if(strcmp(rep,NP->Chistr)==0)
  234. reptrue=1;
  235. rep = strtok(NULL, ";");
  236. }
  237. if(reptrue)  //编码和汉字串相等则直接余
  238. ret=2;
  239. else                       //编码相同则合并编码
  240. {                          //为了简便,汉字串的空间不释放,直接余弃
  241.    ss=new char[(strlen(NP->Chistr)+strlen(P->Next->Chistr)+2)];
  242.    strcpy(ss,P->Next->Chistr);
  243.    strcat(ss,";");
  244.    strcat(ss,NP->Chistr);
  245.    P->Next->Chistr=ss;
  246.    P->Next->len+=strlen(NP->Chistr)+1;//加上新结点的长度
  247.    ret=1;
  248. }
  249. }
  250. else  //英文不同
  251. {
  252. NP->Next=P->Next;
  253. P->Next=NP;
  254. }
  255. }
  256. return ret;
  257. }
  258. //新接点插入
  259. //返回为2,说明结点重复,直接余去
  260. //返回为1,说明结点被合并。
  261. //返回为3,说明结点直拉挂在扩展区
  262. //返回为0,说明结点成功插入
  263. CreateLib::inertNewdnodeEx(mynode *NP, mynode *pHead)
  264. {
  265. mynode *P;
  266. char *ss, *cc,*rep;//由于拼音之类的重码多,会tg很快大于1000
  267. int ret=0, reptrue,h=0,lon;
  268. NP->len=strlen(NP->ChistrEx)+strlen(NP->Enstr)+3;
  269. P=pHead;
  270. while(1)//大字库的90%时间主要消耗在这里.
  271. {
  272. h++;
  273.   if(P->Next==NULL)
  274.   break;
  275.   else
  276. if(strcmp(P->Next->Enstr, NP->Enstr)>=0)//如果相等也要后移
  277. break;
  278. else
  279. P=P->Next;
  280. }
  281. //P结束于比它小者,或者后面为空的结点之前。
  282.     //if(strcmp("LKAN",strupr(NP->Enstr))==0)
  283. // MessageBox(0,NP->Enstr,"00",0);
  284. if(P->Next==NULL|| P->Next==0)
  285. {
  286. P->Next=NP;
  287. }
  288. else
  289. {
  290. if(strcmp(P->Next->Enstr, NP->Enstr)==0)//英文相同
  291. {
  292. reptrue=0;
  293. if(P->Next->ChistrEx!=NULL)
  294. {
  295. //strlen(P->Next->ChistrEx);
  296. lon=strlen(NP->ChistrEx)+strlen(P->Next->ChistrEx)+2;
  297. cc=new char[lon];
  298. strcpy(cc,P->Next->ChistrEx);
  299. }
  300. else
  301. {
  302. lon=strlen(NP->ChistrEx)+2;
  303. cc=new char[(strlen(NP->ChistrEx)+2)];
  304. strcpy(cc,"");
  305. }
  306. rep = strtok(cc, ";"); //判断编码是否重复
  307. while(rep){
  308. if(strcmp(rep,NP->ChistrEx)==0)
  309. reptrue=1;
  310. rep = strtok(NULL, ";");
  311. }
  312. if(reptrue)  //编码和汉字串相等则直接余
  313. ret=2;
  314. else                       //编码相同则合并编码
  315. {                          //为了简便,汉字串的空间不释放,直接余弃
  316. if(P->Next->ChistrEx!=NULL)
  317. {
  318.    ss=new char[lon];
  319.    strcpy(ss,P->Next->ChistrEx);
  320.    strcat(ss,";");
  321.    strcat(ss,NP->ChistrEx);
  322.    P->Next->ChistrEx=ss;
  323.    P->Next->len+=strlen(NP->ChistrEx)+1;//加上新结点的长度
  324.    ret=1;
  325. }
  326. else
  327. {
  328.    ss=new char[lon];
  329.    strcpy(ss,NP->ChistrEx);
  330.    P->Next->ChistrEx=ss;
  331.    P->Next->len+=strlen(NP->ChistrEx)+1;//加上新结点的长度
  332.    if(P->Next->Chistr!=NULL)    //
  333.    P->Next->len--;
  334.    ret=3;
  335. }
  336. }
  337. }
  338. else  //英文不同
  339. {
  340. NP->Next=P->Next;
  341. P->Next=NP;
  342. }
  343. }
  344. return ret;
  345. }
  346. //求平方
  347. unsigned long CreateLib::Sqrt(long num, int p)
  348. {
  349. int i;
  350. unsigned long ret=1;
  351. for(i=0;i<p;i++)
  352. {
  353.    ret=ret*num;
  354. }
  355. return ret;
  356. }
  357. //由指定的编码转换成头接点号。供建立结点时找头结点用
  358. long CreateLib::getheadID(char *ss, long lon)
  359. {
  360. long i,n,ret=0;
  361. char s1[100];
  362. strcpy(s1,ss);
  363. strupr(s1);
  364. n=strlen(ss);
  365. for(i=0;i<lon&&i<n;i++)
  366. {
  367. ret+=(s1[i]-Base)*Sqrt(GoldeNum,lon-1-i);
  368. }
  369. if(ret<0)
  370. MessageBox(0,"getheadID",0,0);
  371.     return ret;
  372. }
  373. //将文件中的原编码形成结点,分发到不同头结点中
  374. // 返回为0表示成功,为1表示失败。
  375. //GoldeNum 为编码长度 GoldeLen为编码数
  376. int CreateLib::CreatNode(FILE  *fp)
  377. {
  378.    int tt;     //tt用于判断文件是否结束
  379.    int t;      //t用于判断结点插入情况
  380.    int count=0,ret=0; 
  381.    int sslon,codelon;
  382.    char ss[1000],code[200];
  383.    char cc[1000];
  384.    mynode  *NP ;
  385.    
  386.    tt=fscanf(fp,"%s %s",code,ss);
  387.    while(tt>-1)
  388.    {
  389.    sslon=strlen(ss);
  390.    codelon=strlen(code);
  391.    if(codelon==0||sslon==0){
  392.    sprintf(cc,"代码:%s n汉字串为:%s n位置:%d ",code,ss,LIBnum);
  393.    MessageBox(0,cc,"代码或字串为空",0);
  394.    ret=1;
  395.    break;
  396.    }
  397.    /*
  398.    if(codelon>GoldeLen){
  399.    sprintf(cc,"代码:%s n汉字串为:%s n位置:%d n GoldeLen指定为:%d",code,ss,LIBnum,GoldeLen);
  400.    MessageBox(0,cc,"代码长度大于GoldeLen中的指定值",0);
  401.    ret=1;
  402.    break;
  403.    }*/
  404.    ht=getheadID(code,3);
  405.    //由头二个字符确定头接点,本变量为2,头三个3
  406.    //*******************准备新结点***************************
  407.    NP=new mynode;//分配新结点
  408.    strupr(code);     //将代码变成大写,否则会发生冲突不同代码计算出相等值;
  409.    NP->Enstr=(char *)malloc(codelon+1);//汉字串
  410.    strcpy(NP->Enstr,code);
  411.  
  412.    NP->Chistr=(char *)malloc( sslon+1);//汉字串
  413.    strcpy(NP->Chistr,ss);
  414.    NP->Next=NULL;
  415.    NP->len=codelon+sslon+2;
  416.      //*******************新结点就序***************************
  417.          //大约占1/5时间
  418.  t=inertNewdnode(NP,&pChHead[ht]);//新接点插入
  419.  if(t==0){
  420.  LIBnum++;                 //统计结点个数
  421.  LIBlonEnCh+=strlen(ss)+strlen(code)+3; //计算下一个代码地址.
  422.  }
  423.  else//为2就不处理直接放弃
  424.  if(t==1) //英文代码相等
  425.  {
  426.  LIBlonEnCh+=strlen(ss)+1;
  427.  }
  428.    tt=fscanf(fp,"%s %s",code,ss);
  429.    }
  430.    fclose(fp);//关闭源文件
  431. return ret;
  432. }
  433. //将文件中的原编码形成结点,分发到不同头结点中
  434. // 返回为0表示成功,为1表示失败。
  435. //GoldeNum 为编码长度 GoldeLen为编码数
  436. //mytool的主要目的是接收扩展识别码
  437. int CreateLib::CreatNodeEx(FILE *fp,tool *mytool)
  438. {
  439.    int tt;     //tt用于判断文件是否结束
  440.    int t;      //t用于判断结点插入情况
  441.    int count=0,ret=0; 
  442.    int sslon,codelon;
  443.    char ss[1000],code[200];
  444.    char cc[1000];
  445.    mynode  *NP ;
  446.    tt=fscanf(fp,"%s %s",code,ss);
  447.    while(tt>-1)
  448.    {
  449.    sslon=strlen(ss);
  450.    codelon=strlen(code);
  451.    if(codelon==0||sslon==0){
  452.    sprintf(cc,"代码:%s n汉字串为:%s n位置:%d ",code,ss,LIBnum);
  453.    MessageBox(0,cc,"代码或字串为空",0);
  454.    ret=1;
  455.    break;
  456.    }
  457.    ht=getheadID(code,3);
  458.    //由头二个字符确定头接点,本变量为2,头三个3
  459.    //*******************准备新结点***************************
  460.    NP=new mynode;    //分配新结点
  461.    strupr(code);     //将代码变成大写,否则会发生冲突不同代码计算出相等值;
  462.    NP->Enstr=(char *)malloc(codelon+1);//汉字串
  463.    strcpy(NP->Enstr,code);
  464.    mytool->InsertStr(code);       //插入识别码库
  465.  
  466.    NP->ChistrEx=(char *)malloc( sslon+1);//汉字串
  467.    strcpy(NP->ChistrEx,ss);
  468.    NP->Next=NULL;
  469.    NP->len=codelon+sslon+2;
  470.    //*******************新结点就序***************************
  471.          //大约占4/5时间
  472. t=inertNewdnodeEx(NP,&pChHead[ht]);//新接点插入
  473.  if(t==0){
  474.  LIBnum++;                 //统计结点个数
  475.  LIBlonEnCh+=strlen(ss)+strlen(code)+3; //计算下一个代码地址.
  476.  }
  477.  else//为2就不处理直接放弃
  478.  {
  479.  if(t==1) //英文代码相等
  480.  {
  481.  LIBlonEnCh+=strlen(ss)+1;
  482.  }
  483.  if(t==3) //直接挂在扩展区
  484.  {
  485.  LIBlonEnCh+=strlen(ss);
  486.  }
  487.  }
  488.    tt=fscanf(fp,"%s %s",code,ss);
  489.    }
  490.    fclose(fp);//关闭源文件
  491. return ret;
  492. }