zoukankan      html  css  js  c++  java
  • 小谈“汉字转换成拼音(不带声调)”

    (作者:finallyly 出处:博客园 转载请注明作者和出处)

       把汉字转换成拼音,实际上是一个非技术活,无外乎查表而已。可能由于汉字拼音转换表资源比较宝贵的缘故,网络上开源的转换程序比较少。另外,网络上给出的码表,可能不能覆盖全部的多音字,生僻字,所以基于此类码表写成的程序,也就有一定的局限性。

      本文给出一份完毕的,将汉字转换成无声调标注的拼音的设计思路、全部代码并且给出一份在一定程度上可用的汉字拼音转换表。

    首先指出本文部分参考了原创  《Python返回汉字的汉语拼音(原创) 》的汉字拼音转换表以及大概思路。

    下面步入正轨

    汉语拼音转换表的物理存储格式:(汉字+空格+汉字对应的拼音,多个候选读音用哪个空格隔开)

    @XBVHWN([EIW8S89[C@BD1Z

    程序中的转换表用MAP保存,其数据格式为map<wstring,vector<string>>,wstring:键值;vector<string> 候选读音

    1. 将硬盘中的码表读入内存

    void StringManipulation::FormatPinYinMap(map<wstring,vector<string >>&hptable)
    {
    	ifstream ifile("mycodebook.txt");
    	
    	string line;
    	while (getline(ifile,line))
    	{
    		if (!line.empty())
    		{   wstring wsResult=String2Wstring(line);
    			vector<wstring> goodWordstemp;
    			boost::split(goodWordstemp,wsResult,boost::is_any_of(" "));
    			wstring mykey=goodWordstemp[0];
    			vector<string>myval;
    			for(vector<wstring>::iterator it=goodWordstemp.begin()+1;it!=goodWordstemp.end();it++)
    			{  
    				myval.push_back(Wstring2String(*it));
    				
    
    
    
    			}
    			if (!hptable.count(mykey))
    			{
    				hptable[mykey]=myval;
    			}
    
    
    		}
    
    
    
    
    
    	}
    
    }

    2. 将单个汉字转换成拼音的代码

    vector<string>StringManipulation::HZ2Py(wstring character,map<wstring,vector<string> >& hptable)
    {
    
    	vector<string>candidates;
    	if (hptable.count(character))
    	{
    		candidates=hptable[character];
    
    	}
    	else
    	{
    		candidates.push_back("[A-Z]+");
    
    	}
    	return candidates;
    
    }
    3. 将汉字字符串转换成对应的拼音字符串(重点函数)
    此份代码可以将任意汉字串转换成拼音。但是,工作侧重点是将汉语人名转换成拼音形式,从而构造启发式查询。
    考虑到多音字,生僻字等多种情形,为了让转换成的拼音字符串更具鲁棒性,我们在转换后的拼音串中加入了若干正则表达式
    比如我们将“刘禹锡”转换成”LIU.*?YU.*?XI”。这样形成的拼音字符串既可以和含有“liuyuxi”网页匹配,又可以和含有”LIU YUXI”网页匹配。
    汉语字符串中含有多音字的时候,可以形成多个候选读音。由于我们事先并不知道那些字是多音字,所有我们不可能事先确定一个汉字串究竟有多少种候选读音。
    这里采用的办法是:生成一个图来表示每个汉字对应的后续读音,以及这些读音之间的有向连接关系。
    然后用求有向图上任意两点间的所有路径的算法见《求两点之间所有路径的算法》,求出一个汉字字符串所对应的所有候选读音。
     
    image 
     
    /************************************************************************/
    /*获得一汉字字符串的拼音串                                                                     */
    /************************************************************************/
    vector<string> StringManipulation::Han2Py(string shan,map<wstring,vector<string>>&hptable)
    {
    	vector<string>result;
    	GraphRepresentation gr;
    	gr.Vertex[0]="@";
    	int mycount=0;//是否添加“正则边”
    	int prevsize=0;//上一个汉字有几个读音
    	int laslabel=0;//上一次节点编号的最大值
    	if (!shan.empty())
    	{
    		wstring whan=String2Wstring(shan);
    		for (wstring::iterator it=whan.begin();it!=whan.end();it++)
    		{
    			wstring tmp;
    			tmp.assign(1,*it);
    			vector<string>tmpcandidates=HZ2Py(tmp,hptable);
    			if(mycount==0)
    			{ 
    				for (int i=0;i<tmpcandidates.size();i++ )
    				{
    					gr.Vertex[i+laslabel+1]=tmpcandidates[i];
    					gr.GraphR[make_pair(0,i+laslabel+1)]="&";
    
    				}
    				prevsize=tmpcandidates.size();
    				laslabel=tmpcandidates.size();
    
    			}
    			else
    			{
    				for (int i=0;i<tmpcandidates.size();i++ )
    				{
    					gr.Vertex[i+laslabel+1]=tmpcandidates[i];
    					for (int j=laslabel;j>laslabel-prevsize;j--)
    					{
    						gr.GraphR[make_pair(j,i+laslabel+1)]=".*?";
    					}
    					
    
    				}
    				laslabel+=tmpcandidates.size();
    				prevsize=tmpcandidates.size();
    				
    
    
    
    
    			}
    			mycount++;
    
    		}
    		gr.Vertex[laslabel+1]="@";
    		for (int j=laslabel;j>laslabel-prevsize;j--)
    		{
    			gr.GraphR[make_pair(j,laslabel+1)]="&";
    		}
    		vector<vector<int>>paths;
    		gr.GetPaths(paths,0,laslabel+1);
    		for (vector<vector<int>>::iterator it=paths.begin();it!=paths.end();it++)
    		{  
    			deque<int>tmpque;
    			string singlecandidate;
    			for (vector<int>::reverse_iterator rit=it->rbegin();rit!=it->rend();rit++)
    			{   
    				tmpque.push_back(*rit);
    				
    				if (tmpque.size()==2)
    				{
    					int tmp1=tmpque.front();
    					tmpque.pop_front();
    					singlecandidate+=gr.Vertex[tmp1];
    					int tmp2=tmpque.front();
    					string edge=gr.GraphR[make_pair(tmp1,tmp2)];
    					singlecandidate+=edge;
    					
    
    				
    				}
    				
    				
    					
    				
    				
    		}  
    			TrimString(singlecandidate,"@");
    			TrimString(singlecandidate,"&");
    			result.push_back(singlecandidate);
    		}
    
    
    
    	}
    	
      return result;
    	
    }
    
     
     
     
    其他辅助函数见《小谈汉字转换成拼音辅助函数和辅助类》
    汉字2拼音转换表 https://files.cnblogs.com/finallyliuyu/mycodebook.rar
    
    主调函数:
    StringManipulation strp;
     map<wstring,vector<string>>h2ptable;
     strp.FormatPinYinMap(h2ptable);
    vector<string>result=strp.Han2Py("陈阿娇",h2ptable);
     for (vector<string>::iterator it=result.begin();it!=result.end();it++)
     {
      cout<<*it<<endl;
     }
    效果:
     
     
     
     
     
     
     
  • 相关阅读:
    php获取真实ip地址原理及实现
    关于DateTime计算某个日期过后的多少天之后的日期
    关于get_include_path()和set_include_path()的问题
    LinQ In Action 学习第三章
    LinQ In Action 学习第二章
    LinQ in Action 学习第一章 例子。
    asp.net create windows application and setup service.
    JS alert()、confirm()、prompt()的区别
    php获取用户 地区 、ip地址
    购物车相关 js
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/2048133.html
Copyright © 2011-2022 走看看