TRANUC.CPP
上传用户:zhang8947
上传日期:2007-01-08
资源大小:1910k
文件大小:11k
源码类别:

多国语言处理

开发平台:

Visual C++

  1. //UCDOS输入法文本文件转换程序
  2. #include "stdafx.h"
  3. #include "windowsx.h"
  4. #include "tranuc.h"
  5. #include "csinput.h"
  6. CTranUcdos OTranUcdos ;
  7. //转换的接口
  8. BOOL CTranUcdos::TranslateUcdos( CString pathName )
  9. {
  10. //组织库文件名
  11. strcpy( m_sLibName , pathName ) ;
  12. m_sLibName[strlen(m_sLibName)-3] ='' ;
  13. strcat( m_sLibName , "iml" ) ;
  14.  
  15. //打开原文件
  16. CFile file ;
  17. if( !file.Open( pathName , CFile::modeRead|CFile::typeBinary ) )
  18. {
  19. AfxMessageBox( "Open file error" ) ;
  20. return 0 ;
  21. }
  22. //得到文件长度
  23. m_dwSourceLen =file.GetLength() ;
  24. //分配地址空间
  25. m_hpsSource =(char huge*)GlobalAllocPtr( GMEM_FIXED ,
  26. m_dwSourceLen ) ;
  27. if( !m_hpsSource )
  28. {
  29. AfxMessageBox( "GlobalAllocPtr error" ) ;
  30. file.Close() ;
  31. return 0 ;
  32. }
  33. //读出源文件内容
  34. file.ReadHuge( m_hpsSource , m_dwSourceLen ) ;
  35. //关闭文件
  36. file.Close() ;
  37. //对源库进行分析,以生成我的库
  38. //设置初始值
  39. //整个库所占字节数
  40. inputLibHead.dwTotalBytes =sizeof( INPUT_LIB_HEAD ) ;
  41. inputLibHead.dwTotalWords =0 ; //整个库中的词条数目
  42. inputLibHead.sName[0] ='' ; //输入法名,以''结束
  43. inputLibHead.nFunctionKey =0 ; //功能键号
  44. inputLibHead.nGodKey ='z' ; //万能键
  45. inputLibHead.nMaxCodeLen =0 ; //最大码长
  46. for( int i=0 ; i<CODE_CELL_NUM ; i++ )
  47. {
  48. inputLibHead.sCodeCells[i] =0 ;
  49. inputLibHead.dwIndex[i] =0 ; //首码索引表
  50. }
  51. Analysis() ;
  52. //释放申请的空间
  53. GlobalFreePtr( m_hpsSource ) ;
  54. //产生我的输入法文件
  55. CreateMyLib() ;
  56. return 1 ;
  57. }
  58. //创建我的输入法库
  59. void CTranUcdos::CreateMyLib( void )
  60. {
  61. DWORD dwLibPoint =sizeof( INPUT_LIB_HEAD ) ; //库指针
  62. char sFileName[13] ="a.tmp" ;
  63. CFile file ;
  64. DWORD dwFileLen ;
  65. char huge *hpsFile ;
  66. CFile libFile ; //库文件
  67. if( !libFile.Open( m_sLibName , CFile::modeReadWrite|
  68. CFile::modeCreate|
  69. CFile::typeBinary ) )
  70. {
  71. AfxMessageBox( "创建.iml文件失败" ) ;
  72. return ;
  73. }
  74. //将库头写入,主要是为了定位
  75. libFile.Write( &inputLibHead , sizeof( INPUT_LIB_HEAD ) ) ;
  76. INPUT_LIB_ITEM huge *pItem ;
  77. DWORD j ;
  78. DWORD dwItemNum ;
  79. int nItemLen ;
  80. for( int i=0 ; i<CODE_CELL_NUM ; i++ )
  81. {
  82. if( !inputLibHead.sCodeCells[i] ) //没有这个元
  83. continue ;
  84. //组织文件名
  85. sFileName[0] =i+33 ;
  86. //打开文件
  87. if( !file.Open( sFileName , CFile::modeRead|CFile::typeBinary ) )
  88. continue ; //可能该文件不存在
  89. //得到文件长度
  90. dwFileLen =file.GetLength() ;
  91. if( dwFileLen % sizeof( INPUT_LIB_ITEM ) )
  92. {
  93. AfxMessageBox( "文件长度不对" ) ;
  94. return ;
  95. }
  96. //分配空间
  97. hpsFile =(char huge*)GlobalAllocPtr( GMEM_FIXED ,
  98.                             dwFileLen ) ;
  99. if( !hpsFile )
  100. {
  101. AfxMessageBox( "GlobalAllocPtr error" ) ;
  102. return ;
  103. }                                         
  104. //读出内容
  105. file.ReadHuge( hpsFile , dwFileLen ) ;
  106. //关闭文件
  107. file.Close() ;
  108. //删除该文件
  109. remove( sFileName ) ;
  110. //对该内容进行排序
  111. SortContent( hpsFile , dwFileLen ) ;
  112. //填写该码元检索表
  113. inputLibHead.dwIndex[i] =dwLibPoint ;
  114. //将排序结果写入库文件
  115. dwItemNum =dwFileLen/sizeof( INPUT_LIB_ITEM) ;
  116. pItem =(INPUT_LIB_ITEM huge*)hpsFile ;
  117. for( j=0 ; j<dwItemNum ; j++ )
  118. {
  119. //项长度
  120. nItemLen =1 + pItem->nEnglishLen + pItem->nChineseLen ;
  121. dwLibPoint +=nItemLen ; //修改库指针
  122. //写入项长度
  123. libFile.Write( &nItemLen , 1 ) ;
  124. //写入英文串
  125. libFile.Write( pItem->sEnglish , pItem->nEnglishLen ) ;
  126. //写入汉字串
  127. libFile.Write( pItem->sChinese , pItem->nChineseLen ) ;
  128. pItem++ ;
  129. }
  130. //释放空间
  131. GlobalFreePtr( hpsFile ) ;
  132. }
  133. //定位到库开始,重新写入库头
  134. libFile.SeekToBegin() ;
  135. libFile.Write( &inputLibHead , sizeof( INPUT_LIB_HEAD ) ) ;
  136. //关闭库文件
  137. libFile.Close() ;
  138. if( dwLibPoint != inputLibHead.dwTotalBytes )
  139. AfxMessageBox( "dwLibPoint!==dwTotalBytes" ) ;
  140. }
  141. //对该内容进行排序
  142. void CTranUcdos::SortContent( char huge *hpsFile , DWORD dwFileLen )
  143. {
  144. int nItemLen =sizeof( INPUT_LIB_ITEM ) ;
  145. DWORD dwItemNum =dwFileLen/nItemLen ; //项数
  146. INPUT_LIB_ITEM huge *pItem1 ;
  147. INPUT_LIB_ITEM  huge *pItem2 ; //排序用
  148. INPUT_LIB_ITEM item ; //排序用缓冲区
  149. DWORD i , j ;
  150. int n ;
  151. for( i=0 ; i<dwItemNum ; i++ )
  152. {
  153. pItem1 =(INPUT_LIB_ITEM huge*)( hpsFile + i*nItemLen ) ;
  154. for( j=i+1 ; j<dwItemNum ; j++ )
  155. {
  156. pItem2 =(INPUT_LIB_ITEM huge*)( hpsFile + j*nItemLen ) ;
  157.     //比较两者的编码
  158.     n =_fstrncmp( pItem1->sEnglish , pItem2->sEnglish ,
  159.      min( pItem1->nEnglishLen , pItem2->nEnglishLen ) ) ;
  160. if( !n ) //两者相等,长者在后,短者在前
  161. {
  162. if( pItem1->nEnglishLen > pItem2->nEnglishLen ) //交换
  163. {
  164. CopyInputItem( &item , pItem1 ) ;
  165. CopyInputItem( pItem1 , pItem2 ) ;
  166. CopyInputItem( pItem2 , &item ) ;
  167. }
  168. continue ;
  169. }
  170. if( n>0 ) //前者大,需要交换
  171. {
  172. CopyInputItem( &item , pItem1 ) ;
  173. CopyInputItem( pItem1 , pItem2 ) ;
  174. CopyInputItem( pItem2 , &item ) ;
  175.     }
  176.     //前者小,不需要交换
  177. }   
  178. }
  179. }
  180. //拷贝输入项
  181. void CTranUcdos::CopyInputItem( INPUT_LIB_ITEM huge *item1 , 
  182. INPUT_LIB_ITEM huge *item2 )
  183. {
  184. item1->nEnglishLen =item2->nEnglishLen ;
  185. item1->nChineseLen =item2->nChineseLen ;
  186. _fstrncpy( item1->sEnglish , item2->sEnglish , item2->nEnglishLen ) ;
  187. _fstrncpy( item1->sChinese , item2->sChinese , item2->nChineseLen ) ;
  188. }
  189. void CTranUcdos::ShowResult( CDC *pdc )
  190. {
  191. char sBuff[100] ;
  192. int y =32 ;
  193. wsprintf( sBuff , "输入法名:%s" , inputLibHead.sName ) ;
  194. pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
  195. y +=16 ;
  196. wsprintf( sBuff , "功能键号:%c" , inputLibHead.nFunctionKey ) ;
  197. pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
  198. y +=16 ;
  199. wsprintf( sBuff , "万能键:%c" , inputLibHead.nGodKey ) ;
  200. pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
  201. y +=16 ;
  202. wsprintf( sBuff , "最大码长:%d" , inputLibHead.nMaxCodeLen ) ;
  203. pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
  204. y +=16 ;
  205. wsprintf( sBuff , "总字节数:%lu 总行数:%lu 总词条数:%lu" , 
  206. inputLibHead.dwTotalBytes ,
  207. m_dwTotalLines , inputLibHead.dwTotalWords ) ;
  208. pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
  209. }
  210. //得到一行
  211. BOOL CTranUcdos::GetOneLine( char *sLineBuff )
  212. {
  213. if( m_dwSourcePoint >= m_dwSourceLen ) //完了
  214. return 0 ;
  215. int nLineLen =0 ; //行长度
  216. for( ; m_dwSourcePoint < m_dwSourceLen ; m_dwSourcePoint++ )
  217. {
  218. if( m_dwSourcePoint < m_dwSourceLen-1 )
  219. {
  220. if( m_hpsSource[m_dwSourcePoint] == 0x0d &&
  221. m_hpsSource[m_dwSourcePoint+1] == 0x0a ) //行结束
  222. {
  223. m_dwSourcePoint +=2 ;
  224. break ;
  225. }
  226. }
  227. sLineBuff[nLineLen++] =m_hpsSource[m_dwSourcePoint] ;
  228. }
  229. sLineBuff[nLineLen] ='' ;
  230. return 1 ;
  231. }
  232. //分析源库文件(指UCDOS输入法文本文件格式)
  233. BOOL CTranUcdos::Analysis( void )
  234. {
  235. char sLineBuff[201] ; //行缓冲
  236. //------------------------------------------------------------------//
  237. m_dwTotalLines =0 ;
  238. m_dwSourcePoint =0 ; //源库指针指向库头
  239. while( 1 )
  240. {
  241. //得到一行
  242. if( !GetOneLine( sLineBuff ) ) //到达库尾
  243. return 1 ;
  244. m_dwTotalLines++ ;
  245. if( sLineBuff[0] == '' || sLineBuff[0] == ' ' ) //行结束或空格
  246. continue ; //放弃该行
  247. if( sLineBuff[0] & 0x80 ) //是汉字
  248. {
  249. if( !AnalysisHead( sLineBuff ) ) //分析头
  250. return 0 ;
  251. }
  252. else //头个字母是英文,说明这行是编码内容
  253. {
  254. inputLibHead.dwTotalWords++ ; //词数增加
  255. if( !AnalysisContent( sLineBuff ) ) //分析编码项
  256. return 0 ;
  257. }
  258. }
  259. return 1 ;
  260. }
  261. BOOL CTranUcdos::AnalysisContent( char *psLine )
  262. {
  263. char sTmpFile[13] ="a.tmp" ; //临时文件名
  264. CFile tmpFile ;
  265. sTmpFile[0] =psLine[0] ; //构造文件名
  266. //打开该文件
  267. if( !tmpFile.Open( sTmpFile , CFile::modeReadWrite|CFile::typeBinary ) )
  268. {
  269. //创建该文件
  270. if( !tmpFile.Open( sTmpFile , CFile::modeReadWrite|CFile::modeCreate|CFile::typeBinary ) )
  271. {
  272. AfxMessageBox( "创建文件失败" ) ;
  273. return 0 ;
  274. }
  275. }
  276. else
  277. //定位到文件尾
  278. tmpFile.SeekToEnd() ;
  279. INPUT_LIB_ITEM item ; //英文,汉字对照项
  280. item.nEnglishLen =0 ;
  281. item.nChineseLen =0 ;
  282. //去掉行首空格
  283. for( ; (*psLine) == ' ' ; psLine++ )
  284. ;
  285. //得到英文编码
  286. for( ; (*psLine) && (*psLine)!=' ' ; psLine++ )
  287. item.sEnglish[item.nEnglishLen++] =*psLine ;
  288. //去掉空格
  289. for( ; (*psLine) == ' ' ; psLine++ )
  290. ;
  291. if( !(*psLine) ) //到达行尾
  292. {
  293. char sBuff[50] ;
  294. wsprintf( sBuff , "第%d行只有编码,没有汉字" , m_dwTotalLines ) ;
  295. AfxMessageBox( sBuff ) ;
  296. return 0 ;
  297. }
  298. //得到汉字,直到行末
  299. for( ; *psLine ; )
  300. {
  301. if( (*psLine) == ' ' )
  302. {
  303. item.sChinese[item.nChineseLen++] =' ' ;
  304. //去掉其后的所有空 格
  305. for( psLine++ ; (*psLine) && (*psLine)==' ' ; psLine ++ )
  306. ;
  307. }
  308. else
  309. item.sChinese[item.nChineseLen++] =*psLine++ ;
  310. }
  311. //写入文件
  312. tmpFile.Write( &item , sizeof( INPUT_LIB_ITEM ) ) ;
  313. //关闭文件
  314. tmpFile.Close() ;
  315. int nBuffLen =1+item.nEnglishLen+item.nChineseLen ;
  316. inputLibHead.dwTotalBytes +=nBuffLen ;
  317. return 1 ;
  318. }
  319. //分析UCDOS输入法文本文件的头
  320. BOOL CTranUcdos::AnalysisHead( char *psLine )
  321. {
  322. int nFlag ;
  323. int nNameLen ; //等号后内容的长度
  324. char *psNamePoint ; //等号后内容的名字
  325. int i ;
  326. nFlag =0 ;
  327. if( !strncmp( "名称" , psLine , 4 ) ) //是输入法名称
  328. {
  329. nFlag =1 ;
  330. psLine +=4 ;
  331. }
  332. else if( !strncmp( "功能键号" , psLine , 8 ) )
  333. {
  334. nFlag =2 ;
  335. psLine +=8 ;
  336. }
  337. else if( !strncmp( "码元表" , psLine , 6 ) )
  338. {
  339. nFlag =3 ;
  340. psLine +=6 ;
  341. }
  342. else if( !strncmp( "万能键" , psLine , 6 ) )
  343. {
  344. nFlag =4 ;
  345. psLine +=6 ;
  346. }
  347. else if( !strncmp( "最大码长" , psLine , 8 ) )
  348. {
  349. nFlag =5 ;
  350. psLine +=8 ;
  351. }
  352. if( !nFlag ) //不需要的东西
  353. return 1 ;
  354. //去掉空格和等号
  355. for( ; (*psLine) == ' ' || (*psLine) == '=' ; psLine++ )
  356. ;
  357. //得到下一串内容(在碰到空格或行结束之前)
  358. psNamePoint =psLine ;
  359. for( nNameLen=0 ; (*psLine) && (*psLine)!=' ' ; 
  360. nNameLen++,psLine++)
  361. ;
  362. if( !nNameLen )
  363. {
  364. AfxMessageBox( "等号后没有东西" ) ;
  365. return 0 ;
  366. }
  367. switch( nFlag )
  368. {
  369. case 1: //输入法名称
  370. if( nNameLen > MAX_NAME_LEN ) //太长
  371. {
  372. AfxMessageBox( "文件名太长" ) ;
  373. return 0 ;
  374. }
  375. //得到文件名
  376. strncpy( inputLibHead.sName , psNamePoint , nNameLen ) ;
  377. inputLibHead.sName[nNameLen] ='' ;
  378. break ;
  379. case 2: //功能键号
  380. if( nNameLen > 1 )
  381. {
  382. AfxMessageBox( "功能键号不是个位数" ) ;
  383. return 0 ;
  384. }
  385. inputLibHead.nFunctionKey =(int)(*psNamePoint) ;
  386. break ;
  387. case 3: //码元表
  388. if( nNameLen > CODE_CELL_NUM )
  389. {
  390. AfxMessageBox( "码元太多了" ) ;
  391. return 0 ;
  392. }
  393. for( i=0 ; i<nNameLen ; i++ ) //得到码元
  394. {
  395. if( psNamePoint[i] < 33 || psNamePoint[i] > 126 )
  396. {
  397. AfxMessageBox( "码元不合法" ) ;
  398. return 0 ;
  399. }
  400. //设上标记
  401. inputLibHead.sCodeCells[psNamePoint[i]-33] =1 ;
  402. }
  403. break ;
  404. case 4: //万能键
  405. if( nNameLen > 1 )
  406. {
  407. AfxMessageBox( "万能键不是一个键" ) ;
  408. return 0 ;
  409. }
  410. inputLibHead.nGodKey =(int)(*psNamePoint) ;
  411. break ;
  412. case 5: //最大码长
  413. psNamePoint[nNameLen] ='' ;
  414. i =atoi( psNamePoint ) ; //将字符串转换成整数
  415. if( i<=0 || i>MAX_CODE_LEN )
  416. {
  417. AfxMessageBox( "最大码长不对" ) ;
  418. return 0 ;
  419. }
  420. inputLibHead.nMaxCodeLen =i ;
  421. break ;
  422. }
  423. return 1 ;
  424. }
  425. #ifdef __cplusplus
  426. extern "C" {
  427. #endif
  428. BOOL __export FAR PASCAL TranslateUcdos( LPCSTR pathName )
  429. {
  430. return OTranUcdos.TranslateUcdos( pathName ) ;
  431. }
  432. #ifdef __cplusplus
  433. }
  434. #endif