fallwinters
fallwinters
采纳率50%
2016-07-23 01:39

【C#】菜鸟一枚,有关汉字转拼音的编程问题,谢!

已采纳

下面粘贴的是书上的源代码,有以下几个问题:
1.asc=M1*256+M2-65536 这个式子是什么含义?
2.为什么计算机内有自己的编码系统,还要自己去定义拼音编码数组和相对应的拼音数组呢?
3.这个编程的思路是怎样的呢?

菜鸟一枚,特别晕菜,希望给予指点。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace ChineseToABC
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("请输入要转换的内容:");
string str = Console.ReadLine();
Regex reg = new Regex("^[\u4e00-\u9fa5]$");//验证输入是否为汉字
byte[] arr = new byte[2];//定义字节数组
string pystr = "";//定义字符串变量并添加引用
char[] mChar = str.ToCharArray();//获取汉字对应的字符数组
Console.WriteLine("转换后的拼音:"+GetStr(mChar, pystr, reg, arr)+"\n");//返回获取到的汉字拼音
}
}
//定义拼音区编码数组
private static int[] getValue = new int[]
{
-20319,-20317,-20304,-20295,-20292,-20283,-20265,-20257,-20242,-20230,-20051,-20036,
-20032,-20026,-20002,-19990,-19986,-19982,-19976,-19805,-19784,-19775,-19774,-19763,
-19756,-19751,-19746,-19741,-19739,-19728,-19725,-19715,-19540,-19531,-19525,-19515,
-19500,-19484,-19479,-19467,-19289,-19288,-19281,-19275,-19270,-19263,-19261,-19249,
-19243,-19242,-19238,-19235,-19227,-19224,-19218,-19212,-19038,-19023,-19018,-19006,
-19003,-18996,-18977,-18961,-18952,-18783,-18774,-18773,-18763,-18756,-18741,-18735,
-18731,-18722,-18710,-18697,-18696,-18526,-18518,-18501,-18490,-18478,-18463,-18448,
-18447,-18446,-18239,-18237,-18231,-18220,-18211,-18201,-18184,-18183, -18181,-18012,
-17997,-17988,-17970,-17964,-17961,-17950,-17947,-17931,-17928,-17922,-17759,-17752,
-17733,-17730,-17721,-17703,-17701,-17697,-17692,-17683,-17676,-17496,-17487,-17482,
-17468,-17454,-17433,-17427,-17417,-17202,-17185,-16983,-16970,-16942,-16915,-16733,
-16708,-16706,-16689,-16664,-16657,-16647,-16474,-16470,-16465,-16459,-16452,-16448,
-16433,-16429,-16427,-16423,-16419,-16412,-16407,-16403,-16401,-16393,-16220,-16216,
-16212,-16205,-16202,-16187,-16180,-16171,-16169,-16158,-16155,-15959,-15958,-15944,
-15933,-15920,-15915,-15903,-15889,-15878,-15707,-15701,-15681,-15667,-15661,-15659,
-15652,-15640,-15631,-15625,-15454,-15448,-15436,-15435,-15419,-15416,-15408,-15394,
-15385,-15377,-15375,-15369,-15363,-15362,-15183,-15180,-15165,-15158,-15153,-15150,
-15149,-15144,-15143,-15141,-15140,-15139,-15128,-15121,-15119,-15117,-15110,-15109,
-14941,-14937,-14933,-14930,-14929,-14928,-14926,-14922,-14921,-14914,-14908,-14902,
-14894,-14889,-14882,-14873,-14871,-14857,-14678,-14674,-14670,-14668,-14663,-14654,
-14645,-14630,-14594,-14429,-14407,-14399,-14384,-14379,-14368,-14355,-14353,-14345,
-14170,-14159,-14151,-14149,-14145,-14140,-14137,-14135,-14125,-14123,-14122,-14112,
-14109,-14099,-14097,-14094,-14092,-14090,-14087,-14083,-13917,-13914,-13910,-13907,
-13906,-13905,-13896,-13894,-13878,-13870,-13859,-13847,-13831,-13658,-13611,-13601,
-13406,-13404,-13400,-13398,-13395,-13391,-13387,-13383,-13367,-13359,-13356,-13343,
-13340,-13329,-13326,-13318,-13147,-13138,-13120,-13107,-13096,-13095,-13091,-13076,
-13068,-13063,-13060,-12888,-12875,-12871,-12860,-12858,-12852,-12849,-12838,-12831,
-12829,-12812,-12802,-12607,-12597,-12594,-12585,-12556,-12359,-12346,-12320,-12300,
-12120,-12099,-12089,-12074,-12067,-12058,-12039,-11867,-11861,-11847,-11831,-11798,
-11781,-11604,-11589,-11536,-11358,-11340,-11339,-11324,-11303,-11097,-11077,-11067,
-11055,-11052,-11045,-11041,-11038,-11024,-11020,-11019,-11018,-11014,-10838,-10832,
-10815,-10800,-10790,-10780,-10764,-10587,-10544,-10533,-10519,-10331,-10329,-10328,
-10322,-10315,-10309,-10307,-10296,-10281,-10274,-10270,-10262,-10260,-10256,-10254
};
//定义拼音数组
private static string[] getStr = new string[]
{
"A","Ai","An","Ang","Ao","Ba","Bai","Ban","Bang","Bao","Bei","Ben",
"Beng","Bi","Bian","Biao","Bie","Bin","Bing","Bo","Bu","Ba","Cai","Can",
"Cang","Cao","Ce","Ceng","Cha","Chai","Chan","Chang","Chao","Che","Chen","Cheng",
"Chi","Chong","Chou","Chu","Chuai","Chuan","Chuang","Chui","Chun","Chuo","Ci","Cong",
"Cou","Cu","Cuan","Cui","Cun","Cuo","Da","Dai","Dan","Dang","Dao","De",
"Deng","Di","Dian","Diao","Die","Ding","Diu","Dong","Dou","Du","Duan","Dui",
"Dun","Duo","E","En","Er","Fa","Fan","Fang","Fei","Fen","Feng","Fo",
"Fou","Fu","Ga","Gai","Gan","Gang","Gao","Ge","Gei","Gen","Geng","Gong",
"Gou","Gu","Gua","Guai","Guan","Guang","Gui","Gun","Guo","Ha","Hai","Han",
"Hang","Hao","He","Hei","Hen","Heng","Hong","Hou","Hu","Hua","Huai","Huan",
"Huang","Hui","Hun","Huo","Ji","Jia","Jian","Jiang","Jiao","Jie","Jin","Jing",
"Jiong","Jiu","Ju","Juan","Jue","Jun","Ka","Kai","Kan","Kang","Kao","Ke",
"Ken","Keng","Kong","Kou","Ku","Kua","Kuai","Kuan","Kuang","Kui","Kun","Kuo",
"La","Lai","Lan","Lang","Lao","Le","Lei","Leng","Li","Lia","Lian","Liang",
"Liao","Lie","Lin","Ling","Liu","Long","Lou","Lu","Lv","Luan","Lue","Lun",
"Luo","Ma","Mai","Man","Mang","Mao","Me","Mei","Men","Meng","Mi","Mian",
"Miao","Mie","Min","Ming","Miu","Mo","Mou","Mu","Na","Nai","Nan","Nang",
"Nao","Ne","Nei","Nen","Neng","Ni","Nian","Niang","Niao","Nie","Nin","Ning",
"Niu","Nong","Nu","Nv","Nuan","Nue","Nuo","O","Ou","Pa","Pai","Pan",
"Pang","Pao","Pei","Pen","Peng","Pi","Pian","Piao","Pie","Pin","Ping","Po",
"Pu","Qi","Qia","Qian","Qiang","Qiao","Qie","Qin","Qing","Qiong","Qiu","Qu",
"Quan","Que","Qun","Ran","Rang","Rao","Re","Ren","Reng","Ri","Rong","Rou",
"Ru","Ruan","Rui","Run","Ruo","Sa","Sai","San","Sang","Sao","Se","Sen",
"Seng","Sha","Shai","Shan","Shang","Shao","She","Shen","Sheng","Shi","Shou","Shu",
"Shua","Shuai","Shuan","Shuang","Shui","Shun","Shuo","Si","Song","Sou","Su","Suan",
"Sui","Sun","Suo","Ta","Tai","Tan","Tang","Tao","Te","Teng","Ti","Tian",
"Tiao","Tie","Ting","Tong","Tou","Tu","Tuan","Tui","Tun","Tuo","Wa","Wai",
"Wan","Wang","Wei","Wen","Weng","Wo","Wu","Xi","Xia","Xian","Xiang","Xiao",
"Xie","Xin","Xing","Xiong","Xiu","Xu","Xuan","Xue","Xun","Ya","Yan","Yang",
"Yao","Ye","Yi","Yin","Ying","Yo","Yong","You","Yu","Yuan","Yue","Yun",
"Za", "Zai","Zan","Zang","Zao","Ze","Zei","Zen","Zeng","Zha","Zhai","Zhan",
"Zhang","Zhao","Zhe","Zhen","Zheng","Zhi","Zhong","Zhou","Zhu","Zhua","Zhuai","Zhuan",
"Zhuang","Zhui","Zhun","Zhuo","Zi","Zong","Zou","Zu","Zuan","Zui","Zun","Zuo"
};
private static string GetStr(char[] mChar, string pystr, Regex reg, byte[] arr)
{
int asc = 0, M1 = 0, M2 = 0;
for (int j = 0; j < mChar.Length; j++)
{
if (reg.IsMatch(mChar[j].ToString()))//如果输入的是汉字
{
arr = System.Text.Encoding.Default.GetBytes(mChar[j].ToString());
M1 = (short)(arr[0]);
M2 = (short)(arr[1]);
asc = M1 * 256 + M2 - 65536;
if (asc > 0 && asc < 160)
{
pystr += mChar[j];
}
else
{
switch (asc)
{
case -9254:
pystr += "Zhen"; break;
case -8985:
pystr += "Qian"; break;
case -5463:
pystr += "Jia"; break;
case -8274:
pystr += "Ge"; break;
case -5448:
pystr += "Ga"; break;
case -5447:
pystr += "La"; break;
case -4649:
pystr += "Chen"; break;
case -5436:
pystr += "Mao"; break;
case -5213:
pystr += "Mao"; break;
case -3597:
pystr += "Die"; break;
case -5659:
pystr += "Tian"; break;
default:
for (int i = (getValue.Length - 1); i >= 0; i--)
{
if (getValue[i] <= asc)//判断汉字的拼音区编码是否在指定范围内
{
pystr += getStr[i];//如果不超出范围则获取对应的拼音
break;
}
}
break;
}
}
}
else//如果不是汉字
{
pystr += mChar[j].ToString();//如果不是汉字则返回
}
}
return pystr;
}
}
}

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • caozhy 回答这么多问题就耍赖把我的积分一笔勾销了 5年前

    asc=M1*256+M2-65536
    一个汉字的内码有两个字节(这里仅仅讨论GB2312,不适用别的编码),可以用两个数字M1 M2表示,M2表示低字节,M1表示高字节。-65536是对它整体取补码,汉字内码规定,最高位必须是1。
    我们用10进制打比方,一个2位数可以用2个1位数表示,比如27,可以知道M1=2,M2=7,现在怎么根据M1 M2还原回27呢?是不是2*10+7=27?(M1*10+M2)
    一个10进制数字表示0~9,所以上一位就要乘以10。类似的,一个字节表示0~255(2的8次方-1),所以是M1*256+M2
    还要自己去定义拼音编码数组和相对应的拼音数组呢
    如果你看下GB编码表就知道了,对于常用字,字的内码是根据拼音的顺序排列的,所以我们可以用查表的方法得到它的拼音,但是这个方法有缺陷,就是对于冷僻字,内码单独按照笔划排列,所以用这个方法是存在问题的。

    点赞 1 评论 复制链接分享
  • Google_huchun 行书开发 5年前

    一个汉字的内码有两个字节(这里仅仅讨论GB2312,不适用别的编码),可以用两个数字M1 M2表示,M2表示低字节,M1表示高字节。-65536是对它整体取补码,汉字内码规定,最高位必须是1。
    我们用10进制打比方,一个2位数可以用2个1位数表示,比如27,可以知道M1=2,M2=7,现在怎么根据M1 M2还原回27呢?是不是2*10+7=27?(M1*10+M2)
    一个10进制数字表示0~9,所以上一位就要乘以10。类似的,一个字节表示0~255(2的8次方-1),所以是M1*256+M2
    还要自己去定义拼音编码数组和相对应的拼音数组呢
    如果你看下GB编码表就知道了,对于常用字,字的内码是根据拼音的顺序排列的,所以我们可以用查表的方法得到它的拼音,但是这个方法有缺陷,就是对于冷僻字,内码单独按照笔划排列,所以用这个方法是存在问题的。

    点赞 评论 复制链接分享
  • qq_35827033 qq_35827033 5年前

    #endregion 二级汉字
    587 #region 变量定义
    588 // GB2312-80 标准规范中第一个汉字的机内码.即"啊"的机内码
    589 private const int firstChCode = -20319;
    590 // GB2312-80 标准规范中最后一个汉字的机内码.即"齄"的机内码
    591 private const int lastChCode = -2050;
    592 // GB2312-80 标准规范中最后一个一级汉字的机内码.即"座"的机内码
    593 private const int lastOfOneLevelChCode = -10247;
    594 // 配置中文字符
    595 //static Regex regex = new Regex("[\u4e00-\u9fa5]$");
    596
    597 #endregion
    598 #endregion
    599
    600 ///
    601 /// 取拼音第一个字段
    602 ///

    603 ///

    604 ///

    605 public static String GetFirst(Char ch)

    606 {
    607 var rs = Get(ch);

    608 if (!String.IsNullOrEmpty(rs)) rs = rs.Substring(0, 1);
    609

    610 return rs;

    611 }
    612
    613 ///
    614 /// 取拼音第一个字段
    615 ///
    616 ///
    617 ///
    618 public static String GetFirst(String str)
    619 {
    620 if (String.IsNullOrEmpty(str)) return String.Empty;
    621
    622 var sb = new StringBuilder(str.Length + 1);
    623 var chs = str.ToCharArray();
    624
    625 for (var i = 0; i < chs.Length; i++)
    626 {
    627 sb.Append(GetFirst(chs[i]));
    628 }
    629

    630 return sb.ToString();
    631 }
    632

    633 ///
    634 /// 获取单字拼音
    635 ///
    636 ///
    637 ///
    638 public static String Get(Char ch)
    639 {
    640 // 拉丁字符

    641 if (ch <= '\x00FF') return ch.ToString();
    642
    643 // 标点符号、分隔符

    644 if (Char.IsPunctuation(ch) || Char.IsSeparator(ch)) return ch.ToString();
    645
    646 // 非中文字符

    647 if (ch < '\x4E00' || ch > '\x9FA5') return ch.ToString();
    648
    649 var arr = Encoding.GetEncoding("gb2312").GetBytes(ch.ToString());
    650 //Encoding.Default默认在中文环境里虽是GB2312,但在多变的环境可能是其它
    651 /ar arr = Encoding.Default.GetBytes(ch.ToString());
    652 var chr = (Int16)arr[0] * 256 + (Int16)arr[1] - 65536;
    653
    654 //***// 单字符--英文或半角字符

    655 if (chr > 0 && chr < 160) return ch.ToString();
    656 #region 中文字符处理
    657
    658 // 判断是否超过GB2312-80标准中的汉字范围
    659 if (chr > lastChCode || chr < firstChCode)
    660 {
    661 return ch.ToString();;
    662 }
    663 // 如果是在一级汉字中
    664 else if (chr <= lastOfOneLevelChCode)
    665 {
    666 // 将一级汉字分为12块,每块33个汉字.
    667 for (int aPos = 11; aPos >= 0; aPos--)
    668 {
    669 int aboutPos = aPos * 33;
    670 // 从最后的块开始扫描,如果机内码大于块的第一个机内码,说明在此块中
    671 if (chr >= pyValue[aboutPos])
    672 {
    673 // Console.WriteLine("存在于第 " + aPos.ToString() + " 块,此块的第一个机内码是: " + pyValue[aPos * 33].ToString());
    674 // 遍历块中的每个音节机内码,从最后的音节机内码开始扫描,
    675 // 如果音节内码小于机内码,则取此音节
    676 for (int i = aboutPos + 32; i >= aboutPos; i--)
    677 {
    678 if (pyValue[i] <= chr)
    679 {
    680 // Console.WriteLine("找到第一个小于要查找机内码的机内码: " + pyValue[i].ToString());
    681 return pyName[i];
    682 }
    683 }
    684 break;
    685 }
    686 }
    687 }
    688 // 如果是在二级汉字中
    689 else
    690 {
    691 int pos = Array.IndexOf(otherChinese, ch.ToString());
    692 if (pos != decimal.MinusOne)
    693 {
    694 return otherPinYin[pos];
    695 }
    696 }
    697 #endregion 中文字符处理
    698
    699 //if (chr < -20319 || chr > -10247) { // 不知道的字符

    700 // return null;

    701

    702 //for (var i = pyValue.Length - 1; i >= 0; i--)
    703 //{

    704 // if (pyValue[i] <= chr) return pyName[i];//这只能对应数组已经定义的

    705 //}

    706

    707 return String.Empty;
    708 }
    709
    710 ///
    711 /// 把汉字转换成拼音(全拼)
    712 ///
    713 /// 汉字字符串
    714 /// 转换后的拼音(全拼)字符串
    715 public static String Get(String str)
    716 {
    717 if (String.IsNullOrEmpty(str)) return String.Empty;
    718

    719 var sb = new StringBuilder(str.Length * 10);
    720 var chs = str.ToCharArray();
    721

    722 for (var j = 0; j < chs.Length; j++)
    723 {
    724 sb.Append(Get(chs[j]));
    725 }
    726

    727 return sb.ToString();
    728 }

    点赞 评论 复制链接分享