MyDictionary.cpp
上传用户:qzyuheng
上传日期:2013-04-28
资源大小:71k
文件大小:11k
源码类别:

词法分析

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "MyDictionary.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. // # define MaxWordLength 8  // 最大词长为8个字节(即4个汉字)
  9. extern int MaxWordLength;
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CWordTagSet
  12. IMPLEMENT_DYNAMIC(CWordTagSet, CDaoRecordset)
  13. CWordTagSet::CWordTagSet(CDaoDatabase* pdb)
  14. : CDaoRecordset(pdb)
  15. {
  16. //{{AFX_FIELD_INIT(CWordTagSet)
  17. m_wid = 0;
  18. m_pos = _T("");
  19. m_pfreq = 0;
  20. m_pid = 0;
  21. m_word = _T("");
  22. m_wfreq = 0;
  23. m_wid2 = 0;
  24. m_nFields = 7;
  25. //}}AFX_FIELD_INIT
  26. m_nDefaultType = dbOpenSnapshot;
  27. m_WordParam=""; // 给词语参数赋值
  28. m_TagParam="";  // 给词性标记参数赋值
  29. m_nParams = 2;  // 参数个数为2
  30. }
  31. /*
  32. CString CWordTagSet::GetDefaultDBName()
  33. {
  34. return _T("Lexicon.mdb");
  35. }
  36. CString CWordTagSet::GetDefaultSQL()
  37. {
  38. return _T("[poss],[words]");
  39. }
  40. */
  41. void CWordTagSet::DoFieldExchange(CDaoFieldExchange* pFX)
  42. {
  43. //{{AFX_FIELD_MAP(CWordTagSet)
  44. pFX->SetFieldType(CDaoFieldExchange::param);
  45. DFX_Text(pFX,"wordParam",m_WordParam);
  46. DFX_Text(pFX,"tagParam",m_TagParam);
  47. pFX->SetFieldType(CDaoFieldExchange::outputColumn);
  48. DFX_Long(pFX, _T("[poss].[wid]"), m_wid);
  49. DFX_Text(pFX, _T("[pos]"), m_pos);
  50. DFX_Long(pFX, _T("[pfreq]"), m_pfreq);
  51. DFX_Long(pFX, _T("[pid]"), m_pid);
  52. DFX_Text(pFX, _T("[word]"), m_word);
  53. DFX_Long(pFX, _T("[wfreq]"), m_wfreq);
  54. DFX_Long(pFX, _T("[words].[wid]"), m_wid2);
  55. //}}AFX_FIELD_MAP
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. // CWordTagSet diagnostics
  59. #ifdef _DEBUG
  60. void CWordTagSet::AssertValid() const
  61. {
  62. CDaoRecordset::AssertValid();
  63. }
  64. void CWordTagSet::Dump(CDumpContext& dc) const
  65. {
  66. CDaoRecordset::Dump(dc);
  67. }
  68. #endif //_DEBUG
  69. int CWordTagSet::GetFreq(CString w, CString t)
  70. {
  71. // 参量赋值
  72. m_WordParam=w;
  73. m_TagParam=t;
  74. // 设置查询条件
  75. m_strFilter="words.wid=poss.wid AND word=wordParam AND pos=tagParam";
  76. // 执行查询
  77. Requery();
  78. if(GetRecordCount()==0)
  79. return -1;
  80. else
  81. return m_pfreq;  // 返回该词语在这一词性标记下的出现次数
  82. }
  83. int CWordTagSet::GetFreqs(CString w, CObArray &a)
  84. {// 第二个参数是动态数组,存放查询到的标记及其出现次数
  85. m_WordParam=w; // 只给一个参数变量赋值
  86. m_strFilter="words.wid=poss.wid AND word=wordParam";
  87. Requery();
  88. if(GetRecordCount()==0)
  89. return 0;
  90. for(int i=0;i<a.GetSize();i++)
  91. if (a[i])
  92. delete a[i];
  93. a.RemoveAll();
  94. i=0;
  95. CTagFreq * tf;
  96. while(!IsEOF()) {
  97. tf=new CTagFreq(m_pos,m_pfreq);
  98. a.Add(tf);
  99. i++;
  100. MoveNext();
  101. }
  102. return i;
  103. }
  104. /////////////////////////////////////////////////
  105. /////////////////////////////////////////////////
  106. // CMyDictionary类成员函数定义
  107. BOOL CMyDictionary :: OpenMDB()
  108. {//打开词语表,词性标记表
  109. if (myDatabaseName.IsEmpty()) {
  110. CFileDialog dlg(TRUE, "mdb", "*.mdb",OFN_OVERWRITEPROMPT);
  111. if (dlg.DoModal()!=IDOK) { 
  112. AfxMessageBox("您没有打开词库");
  113. return FALSE;
  114. }
  115.       myDatabaseName = dlg.GetPathName();
  116.     }
  117. if(pDatabase)
  118. return FALSE;
  119. pDatabase=new CDaoDatabase;
  120. pDatabase->Open(myDatabaseName);
  121. pWordsDef=new CDaoTableDef(pDatabase);
  122. pWordsDef->Open("words"); // 打开词表结构,用词表名words作为参数
  123. pWords=new CDaoRecordset(pDatabase);
  124. pWords->Open(pWordsDef); // 打开词表记录集,用词表结构指针作为参数
  125. pTagsDef=new CDaoTableDef(pDatabase);
  126. pTagsDef->Open("poss"); // 打开词性表结构,用词性表名poss作为参数
  127. pTags=new CDaoRecordset(pDatabase);
  128. pTags->Open(pTagsDef); // 打开词性表记录集,用词性表结构指针作为参数
  129. pNamesDef=new CDaoTableDef(pDatabase);
  130. pNamesDef->Open("names"); // 打开姓名表结构,用姓名表名names作为参数
  131. pNames=new CDaoRecordset(pDatabase);
  132. pNames->Open(pNamesDef); // 打开姓名表记录集,用姓名表结构指针作为参数
  133. pHanziDef=new CDaoTableDef(pDatabase);
  134. pHanziDef->Open("hanzixm");
  135. pHanzi=new CDaoRecordset(pDatabase);
  136. pHanzi->Open(pHanziDef);
  137. return TRUE;
  138. }
  139. BOOL CMyDictionary :: CloseMDB()
  140. {// 构析函数,关闭词语表,词性标记表,中文姓名表
  141. if(pWords) {
  142. pWords->Close();
  143. delete pWords;
  144. }
  145. if(pTags) {
  146. pTags->Close();
  147. delete pTags;
  148. }
  149. if(pWordsDef) {
  150. pWordsDef->Close();
  151. delete pWordsDef;
  152. }
  153. if(pTagsDef) {
  154. pTagsDef->Close();
  155. delete pTagsDef;
  156. }
  157. if(pDatabase) {
  158. pDatabase->Close();
  159. delete pDatabase;
  160. AfxDaoTerm(); // can now safely terminate DAO
  161. }
  162. else
  163. return FALSE;
  164. myDatabaseName = "";
  165. return TRUE;
  166. }
  167. long CMyDictionary :: GetWordID(CString w)
  168. {
  169. COleVariant kw(w,VT_BSTRT),kwi;
  170. pWords->SetCurrentIndex("word");
  171. if(pWords->Seek("=",&kw)) {
  172. kwi=pWords->GetFieldValue("wid");
  173. return kwi.lVal;
  174. }
  175. else 
  176. return -1;
  177. }
  178. long CMyDictionary::GetFreq(CString w)
  179. {
  180. COleVariant kw(w,VT_BSTRT),kf;
  181. pWords->SetCurrentIndex("word");
  182. if(pWords->Seek("=",&kw)) {
  183. kf=pWords->GetFieldValue("wfreq");
  184. return kf.lVal;
  185. }
  186. else return -1;
  187. }
  188. long CMyDictionary::GetFreq(CString w, CString t)
  189. {// 查找某词以某标记出现的次数
  190. long i=GetWordID(w); // 从词语words表中取词语标识号
  191. if(i==-1)  // 没有这个词
  192. return 0;
  193. COleVariant kwi(i,VT_I4),kt,kf;
  194. pTags->SetCurrentIndex("wid");
  195. if(!pTags->Seek("=",&kwi))
  196. return 0;
  197. while(!pTags->IsEOF())
  198. { // 如果在词性表poss中找到了词语标识号
  199. kwi = pTags->GetFieldValue("wid"); // 取词性表poss中的当前记录的词语代号值
  200. if(kwi.lVal != i) // 如果当前记录的wid值发生变化,表示已经不是正在查找的词,则终止查询
  201. break; 
  202. kt=pTags->GetFieldValue("pos"); // 取当前记录的词性标记值
  203. if(!strcmp((const char *)kt.pbVal,(const char*)t)) { // 找到词性标记吻合的记录
  204. kf=pTags->GetFieldValue("pfreq"); // 取当前记录的频次值
  205. return kf.lVal;
  206. }
  207. pTags->MoveNext(); // 移动记录指针到下一条记录
  208. }
  209. return -1; // 没有找到词性标记吻合的记录,返回-1
  210. }
  211. long CMyDictionary::GetFreq(CString w, CObArray & a)
  212. {// 查找一个词语在词典中的所有词性标记的出现次数
  213. long i;
  214. for(i=0;i<a.GetSize();i++)
  215. delete a[i];
  216. a.RemoveAll();
  217. i=GetWordID(w);
  218. if(i==-1)
  219. return 0;
  220. pTags->SetCurrentIndex("wid");
  221. CTagFreq * p;
  222. COleVariant kwi(i,VT_I4), kt,kf;
  223. if(!pTags->Seek("=",&kwi))
  224. return 0;
  225. while(!pTags->IsEOF()) {
  226. kwi=pTags->GetFieldValue("wid");
  227. if(kwi.lVal!=i)
  228. break;
  229. kt=pTags->GetFieldValue("pos");
  230. kf=pTags->GetFieldValue("pfreq");
  231. p=new CTagFreq((LPCSTR) (kt.bstrVal), kf.lVal);
  232. a.Add(p);
  233. pTags->MoveNext();
  234. }
  235. return a.GetSize();
  236. }
  237. long CMyDictionary::Insert(CString w, long freq)
  238. {//向词库中的words表加入一个词在语料库中的出现次数信息,freq的缺省值为1
  239. if(w.GetLength()>MaxWordLength || w=="") // w太长或为空
  240. return -1;
  241. COleVariant kw(w,VT_BSTRT), kf;
  242. pWords->SetCurrentIndex("word");
  243. if(pWords->Seek("=",&kw)) { // 如果这个词在词库中已经存在
  244. kf=pWords->GetFieldValue("wfreq");
  245. kf.lVal+=freq;
  246. pWords->Edit();
  247. pWords->SetFieldValue("wfreq",kf);
  248. pWords->Update();
  249. kf=pWords->GetFieldValue("wid");
  250. }
  251. else {// 如果这个词在词库中还不存在
  252. long recn=pWords->GetRecordCount(); // 查现有记录个数
  253. pWords->AddNew(); // 增加一条空白记录
  254. pWords->SetFieldValue("word",kw); // 设置word字段的值为当前词语
  255. kf=freq; // 对变量kf进行赋值
  256. pWords->SetFieldValue("wfreq",kf); // 设置freq字段的值
  257. kf.lVal=recn+1; // 在当前表中最后一条记录后添加一条新记录
  258. pWords->SetFieldValue("wid",kf); // 设置 wid字段的值
  259. pWords->Update(); // 更新数据库中的数据
  260. }
  261. return kf.lVal; // 返回该词语的 wid 信息(词语代号)
  262. }
  263. long CMyDictionary :: Insert(CString w, CString t, long freq)
  264. {// 向词库中words表和poss表分别插入一个词以某种词性出现的次数,freq的缺省值为1
  265. if(w.GetLength()>MaxWordLength || w=="" || t.GetLength()>4 || t=="")
  266. return -1;
  267. long i=Insert(w); // 先更新词表中的词频信息,将该词的出现次数加1
  268. COleVariant kt(t,VT_BSTRT), kwi(i,VT_I4), kf;
  269. pTags->SetCurrentIndex("widTag");
  270. if(pTags->Seek("=",&kwi,&kt)) {
  271. kf=pTags->GetFieldValue("pfreq"); // 获取当前记录的pfreq值
  272. kf.lVal+=freq;
  273. pTags->Edit();
  274. pTags->SetFieldValue("pfreq",kf); // 设置poss表中pfreq中的值
  275. pTags->Update();
  276. kf=pTags->GetFieldValue("pid"); // 获取当前记录的pid值
  277. }
  278. else {
  279. long recn=pTags->GetRecordCount();
  280. pTags->AddNew();
  281. pTags->SetFieldValue("pos",kt); // 设置poss表中pos字段的值
  282. kf=freq;
  283. pTags->SetFieldValue("pfreq",kf); // 设置poss表中pfreq字段的值
  284. pTags->SetFieldValue("wid",kwi); // 设置poss表中wid字段的值
  285. kf.lVal=recn+1; // 在当前表中最后一条记录后添加一条新记录
  286. pTags->SetFieldValue("pid",kf); // 设置poss表中pid字段的值
  287. pTags->Update();
  288. }
  289. return kf.lVal;// 返回词语的词性标记序号值pid(词性标记代号)
  290. }
  291. CString CMyDictionary::GetTagOfWord(CString w)
  292. { //获取一个词语的词性标记
  293. CString tag="";
  294. long i;
  295. i=GetWordID(w);
  296. if(i==-1)
  297. tag="n"; // 所有未登录词的词性暂且假定为n
  298. pTags->SetCurrentIndex("wid");
  299. COleVariant kwi(i,VT_I4),kt;
  300. if(!pTags->Seek("=",&kwi))
  301. return tag;
  302. // else { // 取该词在词库中第一个词性标记
  303. // kt=pTags->GetFieldValue("pos");
  304. // tag=kt.bstrVal;
  305. // }
  306. while(!pTags->IsEOF()) {// 取该词所有词性标记,切词后,将一个词所有的词性标记
  307. // 加到分词符/后面
  308. kwi=pTags->GetFieldValue("wid");
  309. if(kwi.lVal!=i)
  310. break; // 如果当前词只有一个词性,并且标记为g,也会输出这个结果
  311. kt=pTags->GetFieldValue("pos");
  312. tag=kt.bstrVal; // 这条语句是为了只输出一个词性标记结果而添加的
  313. // if(tag!="") { // 被注释的语句是用来输出所有的词性标记
  314. if(tag!="g") { // 这里是只输出一个词性标记,并且该标记不是语素
  315. // tag=tag+"-"+kt.bstrVal;
  316. return tag;
  317. }
  318. else
  319. // tag=tag+kt.bstrVal;
  320. pTags->MoveNext();
  321. }
  322. return tag;
  323. }
  324. /////////////////////////////////////////////////////////
  325. /////////////////////////////////////////////////////////
  326. // 访问姓名表的成员函数代码开始
  327. double CMyDictionary:: GetFee(CString name, BOOL full)
  328. { // 在词库姓名表中查找姓氏(第二个参数为TRUE)或人名(第二个参数为FALSE)的费用
  329. if(full) {
  330. COleVariant kwl(name.Left(2), VT_BSTRT), kw2(name.Mid(2), VT_BSTRT), kf;
  331. pNames->SetCurrentIndex("name");
  332. if(pNames->Seek("=",&kwl,&kw2)) {
  333. kf=pNames->GetFieldValue("fee");
  334. return kf.dblVal;
  335. }
  336. else
  337. return 20.0;
  338. }
  339. else {
  340. COleVariant kw(name,VT_BSTRT), kf;
  341. pNames->SetCurrentIndex("gname");
  342. if(pNames->Seek("=",&kw)) {
  343. kf=pNames->GetFieldValue("fee");
  344. return kf.dblVal;
  345. }
  346. else
  347. return 20.0;
  348. }
  349. }
  350. BOOL CMyDictionary::Insert(CString sName, CString gName,double f)
  351. {// 向词库中姓名表插入一个姓名
  352. if(sName.GetLength()>4 || gName.GetLength()>4) // 如果词串太长,超过字段宽度,失败
  353. return -1;
  354. COleVariant kw1(sName, VT_BSTRT), kw2(gName, VT_BSTRT);
  355. pNames->SetCurrentIndex("name");
  356. if(!pNames->Seek("=",&kw1,&kw2)) { // 如果姓名表中没有这个姓名,就插入
  357. pNames->AddNew();
  358. pNames->SetFieldValue("sname",kw1);
  359. pNames->SetFieldValue("gname",kw2);
  360. pNames->SetFieldValue("fee",f);
  361. pNames->Update();
  362. return TRUE;
  363. }
  364. else 
  365. return FALSE;
  366. }
  367. long CMyDictionary:: GetSnameFreq(CString hz)
  368. {// 从词库中取一个汉字作为姓使用的出现次数
  369. COleVariant kw(hz,VT_BSTRT),kf;
  370. pHanzi->SetCurrentIndex("hanzi");
  371. if(pHanzi->Seek("=",&kw)) {
  372. kf=pHanzi->GetFieldValue("snamefreq");
  373. return kf.lVal;
  374. }
  375. else 
  376. return -1;
  377. }
  378. long CMyDictionary:: GetGnameFreq(CString hz)
  379. {// 从词库中取汉字作为名使用的出现次数
  380. COleVariant kw(hz,VT_BSTRT),kf;
  381. pHanzi->SetCurrentIndex("hanzi");
  382. if(pHanzi->Seek("=",&kw)) {
  383. kf=pHanzi->GetFieldValue("gnamefreq");
  384. return kf.lVal;
  385. }
  386. else 
  387. return -1;
  388. }
  389. // 访问姓名表的成员函数代码结束
  390. //////////////////////////////////////////////////////
  391. //////////////////////////////////////////////////////