(作者:finallyly 出处:博客园 转载请注明作者和出处)
把汉字转换成拼音,实际上是一个非技术活,无外乎查表而已。可能由于汉字拼音转换表资源比较宝贵的缘故,网络上开源的转换程序比较少。另外,网络上给出的码表,可能不能覆盖全部的多音字,生僻字,所以基于此类码表写成的程序,也就有一定的局限性。
本文给出一份完毕的,将汉字转换成无声调标注的拼音的设计思路、全部代码并且给出一份在一定程度上可用的汉字拼音转换表。
首先指出本文部分参考了 《Python返回汉字的汉语拼音(原创) 》的汉字拼音转换表以及大概思路。
下面步入正轨
汉语拼音转换表的物理存储格式:(汉字+空格+汉字对应的拼音,多个候选读音用哪个空格隔开)
程序中的转换表用MAP保存,其数据格式为map<wstring,vector<string>>,wstring:键值;vector<string> 候选读音
1. 将硬盘中的码表读入内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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. 将单个汉字转换成拼音的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } |
1 | 3. 将汉字字符串转换成对应的拼音字符串(重点函数) |
1 | 此份代码可以将任意汉字串转换成拼音。但是,工作侧重点是将汉语人名转换成拼音形式,从而构造启发式查询。 |
1 | 考虑到多音字,生僻字等多种情形,为了让转换成的拼音字符串更具鲁棒性,我们在转换后的拼音串中加入了若干正则表达式 |
1 | 比如我们将“刘禹锡”转换成”LIU.*?YU.*?XI”。这样形成的拼音字符串既可以和含有“liuyuxi”网页匹配,又可以和含有”LIU YUXI”网页匹配。 |
1 | 汉语字符串中含有多音字的时候,可以形成多个候选读音。由于我们事先并不知道那些字是多音字,所有我们不可能事先确定一个汉字串究竟有多少种候选读音。 |
1 | 这里采用的办法是:生成一个图来表示每个汉字对应的后续读音,以及这些读音之间的有向连接关系。 |
1 | 然后用求有向图上任意两点间的所有路径的算法见《<a href= "http://www.cnblogs.com/finallyliuyu/archive/2011/04/18/2019534.html" >求两点之间所有路径的算</a>法》,求出一个汉字字符串所对应的所有候选读音。 |
1 | |
1 | <a href= "http://images.cnblogs.com/cnblogs_com/finallyliuyu/201105/201105162159215935.png" ><img title= "image" style= "border: 0; display: inline" height= "78" alt= "image" src= "https://images.cnblogs.com/cnblogs_com/finallyliuyu/201105/201105162159221725.png" width= "244" border= "0" ></a> |
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | /************************************************************************/ /*获得一汉字字符串的拼音串 */ /************************************************************************/ 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; } |
1 | |
1 | |
1 | |
1 | 其他辅助函数见<a href= "http://www.cnblogs.com/finallyliuyu/archive/2011/05/16/2048138.html" >《小谈汉字转换成拼音辅助函数和辅助类》</a> |
1 | 汉字2拼音转换表 https: //files.cnblogs.com/finallyliuyu/mycodebook.rar |
1 | 主调函数: |
1 | StringManipulation strp;<br> map<wstring,vector<string>>h2ptable;<br> strp.FormatPinYinMap(h2ptable);<br>vector<string>result=strp.Han2Py( "陈阿娇" ,h2ptable);<br> for (vector<string>::iterator it=result.begin();it!=result.end();it++)<br> {<br> cout<<*it<<endl;<br> } |
1 | 效果: |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
标签:
C++汉字转换成拼音
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
2010-05-16 scipy 知识碎片