tracerll
TRACER_BX
2017-12-06 07:01
采纳率: 100%
浏览 5.6k

帮忙写一个正则表达式要求转换中文字为阿拉伯数字

字符串的格式为:十二斤,五十千克等,是数量+单位形式
替换完为:12斤,50千克等
不用考虑小数,但是要考虑零

C币不多了,求各位大神帮忙

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

15条回答 默认 最新

  • qq_27323623
    Yirujet 2017-12-07 07:18
    已采纳

    楼主,您所提问的问题其实不是难的,观察下中文的数值写法,“十”,“百”,“千”,“万”,“亿”这些修饰符其实是一个基数。主要修饰它前面的数字,
    有了前面的数字,只要想要的乘以对应的基数(10,100,1000,10000,100000000)再分别相加就可以得到对应的阿拉伯数字了,当然,中文数字对应的
    阿拉伯数字还是要自己判断的。这就是思路,有了思路,只需要编写捕获到中文数值中的数字,问题就迎刃而解啦。但是,有一点说明,对应一些复杂的
    中文数字的话,需要二次捕获数值再相加,例如前面的层数提到的 五千六百九十七万三千二百一十二斤,其中 五千六百九十七万。万修饰符前面的数字
    也是组合而来。所以得从 五千六百九十七中再捕获一次数字。具体实现如下(c#写法,控制台显示):
    正则如下:用于捕获中文数字
    ([零一二三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟亿]+亿)?零?([一二三四五六七八九十百千壹贰叁肆伍陆柒捌玖拾佰仟]+万)?零?([一二三四五六七八九十百壹贰叁肆伍陆柒捌玖拾佰][千仟])?零?([一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾][百佰])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖]?[十拾])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖])?

    代码如下:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Text.RegularExpressions;

    namespace regexp_help
    {
    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("请输入要转换的中文数量:");
    string strPreviousText = Console.ReadLine();
    string strRegExp = @"([零一二三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟亿]+亿)?零?([一二三四五六七八九十百千壹贰叁肆伍陆柒捌玖拾佰仟]+万)?零?([一二三四五六七八九十百壹贰叁肆伍陆柒捌玖拾佰][千仟])?零?([一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾][百佰])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖]?[十拾])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖])?";
    string strAllValue = "";
    string strSpecifier = "";
    int dFormatValue = 0;
    MatchCollection matchs = Regex.Matches(strPreviousText, strRegExp); //匹配中文数量
    strAllValue = matchs[0].ToString();
    strSpecifier = strPreviousText.Remove(0, matchs[0].ToString().Length);
    foreach (Match match in matchs)
    {
    int i = 0;
    GroupCollection groups = match.Groups;
    foreach (Group group in groups)
    {
    if (i != 0) {//首个捕获组不获取,因为它是整个数字文本
    if (group.ToString() != "")
    {
    dFormatValue += formatTextToNumber(group.ToString());
    }
    }
    i++;
    }
    }

            Console.WriteLine("转换后的文本:{0}", dFormatValue + strSpecifier);
            Console.ReadKey();
        }
    
        public static int formatTextToNumber(string strVal) {
            int dReturn = 0;
            if (strVal.Length == 1)
            {
                dReturn = getNumber(strVal);
            }
            else {
                string strNumber = strVal.Substring(0, strVal.Length - 1);
                string strSpecifier = strVal.Substring(strVal.Length - 1, 1);
                if (strVal.Length == 2)
                {
                    dReturn = getNumber(strNumber) * getBaseNumber(strSpecifier);
                }
    
                //复杂数字要递归取阿拉伯数字,如五百二十万,五百二十相对于“万”修饰符是组合数字
                if (strVal.Length > 2) {
                    string strRegExp = @"([零一二三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟亿]+亿)?零?([一二三四五六七八九十百千壹贰叁肆伍陆柒捌玖拾佰仟]+万)?零?([一二三四五六七八九十百壹贰叁肆伍陆柒捌玖拾佰][千仟])?零?([一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾][百佰])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖]?[十拾])?零?([一二三四五六七八九壹贰叁肆伍陆柒捌玖])?";
                    MatchCollection matchs = Regex.Matches(strNumber, strRegExp);  //匹配中文数量
                    foreach (Match match in matchs)
                    {
                        int i = 0;
                        GroupCollection groups = match.Groups;
                        foreach (Group group in groups)
                        {
                            if (i != 0)
                            {//首个捕获组不获取,因为它是整个数字文本
                                if (group.ToString() != "")
                                {
                                    dReturn += formatTextToNumber(group.ToString());
                                }
                            }
                            i++;
                        }
                    }
                    dReturn *= getBaseNumber(strSpecifier);
                }
            }
    
            return dReturn;
        }
    
        //获取单数字文本对应阿拉伯数字
        public static int getNumber(string strVal) {
            int dFormatValue = 0;
            switch (strVal)
            {
                case "一":
                case "壹":
                    dFormatValue = 1;
                    break;
                case "二":
                case "贰":
                    dFormatValue = 2;
                    break;
                case "三":
                case "叁":
                    dFormatValue = 3;
                    break;
                case "四":
                case "肆":
                    dFormatValue = 4;
                    break;
                case "五":
                case "伍":
                    dFormatValue = 5;
                    break;
                case "六":
                case "陆":
                    dFormatValue = 6;
                    break;
                case "七":
                case "柒":
                    dFormatValue = 7;
                    break;
                case "八":
                case "捌":
                    dFormatValue = 8;
                    break;
                case "九":
                case "玖":
                    dFormatValue = 9;
                    break;
                case "十":
                case "拾":
                    dFormatValue = 10;
                    break;
                default:
                    dFormatValue = 0;
                    break;
            }
            return dFormatValue;
        }
    
        //获取修饰符对用基数
        public static int getBaseNumber(string strVal) {
            int dFormatValue = 10;
            switch (strVal)
            {
                case "十":
                case "拾":
                    dFormatValue = 10;
                    break;
                case "百":
                case "佰":
                    dFormatValue = 100;
                    break;
                case "千":
                case "仟":
                    dFormatValue = 1000;
                    break;
                case "万":
                    dFormatValue = 10000;
                    break;
                case "亿":
                    dFormatValue = 100000000;
                    break;
                default:
                    dFormatValue = 10;
                    break;
            }
            return dFormatValue;
        }
    }
    

    }

    测试截图:
    测试图例1:
    图片说明
    测试图例2:
    图片说明
    测试图例3:
    图片说明

    点赞 评论
  • qq_35728177
    Tsui丶 2017-12-06 07:11

    正则有可以筛选特定中文的吗?不太清楚 不过你这种的话 对字符串循环一下 用个switch进行下替换就行了

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • zhangdandanpipi
    zhangdandanpipi 2017-12-06 07:13

    正则表达式实现起来有点难吧,你看看这个方法

    public double DecodeMoneyCn(string AText)
    {
    AText = AText.Replace("亿亿", "兆");
    AText = AText.Replace("万万", "亿");
    AText = AText.Replace("点", "元");
    AText = AText.Replace("块", "元");
    AText = AText.Replace("毛", "角");
    double vResult = 0;
    double vNumber = 0; // 当前数字
    double vTemp = 0;
    int vDecimal = 0; // 是否出现小数点
    foreach (char vChar in AText)
    {
    int i = "零一二三四五六七八九".IndexOf(vChar);
    if (i < 0) i = "洞幺两三四五六拐八勾".IndexOf(vChar);
    if (i < 0) i = "零壹贰叁肆伍陆柒捌玖".IndexOf(vChar);
    if (i > 0)
    {
    vNumber = i;
    if (vDecimal > 0)
    {
    vResult += vNumber * Math.Pow(10, -vDecimal);
    vDecimal++;
    vNumber = 0;
    }
    }
    else
    {
    i = "元十百千万亿".IndexOf(vChar);
    if (i < 0) i = "整拾佰仟万亿兆".IndexOf(vChar);
    if (i == 5) i = 8;
    if (i == 6) i = 12;
    if (i > 0)
    {
    if (i >= 4)
    {
    vTemp += vNumber;
    if (vTemp == 0) vTemp = 1;
    vResult += vTemp * Math.Pow(10, i);
    vTemp = 0;
    }
    else vTemp += vNumber * Math.Pow(10, i);
    }
    else
    {
    i = "元角分".IndexOf(vChar);
    if (i > 0)
    {
    vTemp += vNumber;
    vResult += vTemp * Math.Pow(10, -i);
    vTemp = 0;
    }
    else if (i == 0)
    {
    vTemp += vNumber;
    vResult += vTemp;
    vDecimal = 1;
    vTemp = 0;
    }
    }
    vNumber = 0;
    }
    }
    return vResult + vTemp + vNumber;
    }

    private void button1_Click(object sender, EventArgs e)
    {
    string[] vTestText = {
    "十二点五六",
    "一亿零一万零五",
    "四万万",
    "九十八亿七千六百五十四万三千二百一十",
    "五元一角四分", "壹佰元整",
    "三千五百万",
    "九块二毛"};
    foreach (string vText in vTestText)
    {
    Console.WriteLine("DecodeMoneyCn(\"{0}\")={1}", vText,
    DecodeMoneyCn(vText));
    }

    //输出
    //DecodeMoneyCn("十二点五六")=2.56
    //DecodeMoneyCn("一亿零一万零五")=100010005
    //DecodeMoneyCn("四万万")=400000000
    //DecodeMoneyCn("九十八亿七千六百五十四万三千二百一十")=9876543210
    //DecodeMoneyCn("五元一角四分")=5.14
    //DecodeMoneyCn("壹佰元整")=100
    //DecodeMoneyCn("三千五百万")=35000000
    //DecodeMoneyCn("九块二毛")=9.2
    //DecodeMoneyCn("一兆")=1000000000000
    

    }

    点赞 评论
  • what_you_want
    what_you_want 2017-12-06 07:14

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • wangzherongyao1
    wangzherongyao1 2017-12-06 07:23

    正则有可以筛选特定中文的吗?不太清楚 不过你这种的话 对字符串循环一下 用个switch进行下替换就行了

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • qq_41295134
    qq_41295134 2017-12-06 07:29

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • foralllove
    foralllove 2017-12-06 07:51

    str.replace("零", "0").replace("一", "1")....;

    点赞 评论
  • wangs_1998
    王小爽i 2017-12-06 07:57

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • qq_41295720
    慌乱 2017-12-06 08:04

    String newStr = "";
    switch(str){
    case: “零”: newStr +=0;

    ......
    default: newStr += str; //单位点等不处理
    }

    点赞 评论
  • Lucy_juice
    Lucy_juice 2017-12-06 08:06

    阿拉伯语可以在有道词典里转换出来,另word里的插入也有阿拉伯语字符,您可以尝试下。

    点赞 评论
  • weixin_40353693
    weixin_40353693 2017-12-06 08:28

    一个一个替换 replace("一",“1”)

    点赞 评论
  • qq_38130074
    qq_38130074 2017-12-06 08:32

    (?=.*(.*)|.*(.*))^[a-zA-Z0-9\u4e00-\u9fa5()()]*$|^[a-zA-Z0-9\u4e00-\u9fa5]*$
    匹配规则:
    1. 完全匹配输入中文,英文,数字以及英文半角括号和中文全角括号;
    2. 匹配如有括号必须成对;

    点赞 评论
  • qq_38130074
    qq_38130074 2017-12-06 08:35

    (?=.*(.*)|.*(.*))^[a-zA-Z0-9\u4e00-\u9fa5()()]*$|^[a-zA-Z0-9\u4e00-\u9fa5]*$
    匹配规则:
    1. 完全匹配输入中文,英文,数字以及英文半角括号和中文全角括号;
    2. 匹配如有括号必须成对;

    点赞 评论
  • miansi7149
    DEMO_INIT 2017-12-06 10:11

    小兄弟,問問題態度要端正,別話語中帶著譏諷.最近剛好在做正則表達式的分析,你這個用正則分析不出來的.中文不支持特定字符,一到十等等,也可能是我不知道.我可以給你提供個思路,很簡單就能解決你的問題:
    1字符串切割,"五十斤,六十克,三十千克" 單位是有限的,C語言有字符切割,函數strtok;
    2 得到若干個字符串"五十斤""六十克""三十千克" 然後 中文零到九對應0-9 十對應10;
    3這樣最多有十個switch case 語句;

    這樣做也不難.

    点赞 评论
  • qq_35728177
    Tsui丶 2017-12-07 01:15
     String str = "十二万零四百一十公斤";
            String newStr = "";
            for (int i = 0; i < str.length(); i++) {
                char st = str.charAt(i);
                switch (st) {
                case '零':
                    newStr += '0';
                    break;
                case '一':
                    newStr += '1';
                    break;
                case '二':
                    newStr += '2';
                    break;
                case '三':
                    newStr += '3';
                    break;
                case '四':
                    newStr += '4';
                    break;
                case '十':
                    if (i + 1 != str.length()) {
                        newStr += '1';
                    }
                    break;
                case '百':
                    break;
                case '千':
                    break;
                case '万':
                    break;
                default:
                    newStr += st;
                    break;
                }
            }
            System.out.println(newStr);
        }
    
    点赞 评论

相关推荐