CODE-將地址中的阿拉伯數字轉為中文大寫
8 |
前幾天同事討論到要將地址資料中的阿拉伯數字都轉成中文大寫(一二三四...),我想起了前些時候看到的Microsoft Visual Studio International Feature Pack 2.0就內建了數字轉中文大寫的功能,試作如下。
程式主要是用Regex去比對出數字(\d+)的部分,逐一換成中文大寫。而更換時我用算位置的方法而不直接用Replace,以免把"12弄123號"搞成"十二弄十二3號";也因為要算位置,加上每次更換完字串長度可能會改變,所以也不能直接用foreach (Match m in Regex.Matches(…))把所有數字挑出來一次處理,必須用while (Match.Success)個個擊破。[2009-12-23更新: 以下寫法不夠精簡,另外有三百"一"十少一的問題,請改參考下方的改良版]
using System;
using System.Text.RegularExpressions;
using Microsoft.International.Formatters;
using System.Globalization;
namespace TestChtNumber
{
class Program
{
static void Main(string[] args)
{
string addr = "台北市中正區重慶南路1段122號";
Match m;
while ((m=Regex.Match(addr, "\\d+")).Success)
{
int n = int.Parse(m.Value);
string t =
EastAsiaNumericFormatter.FormatWithCulture("Ln", n,
null, new CultureInfo("zh-TW"));
//"L"-大寫,壹貳參... "Ln"-一二三... "Lc"-貨幣,同L
addr = addr.Substring(0, m.Index) + t +
addr.Substring(m.Index + m.Value.Length);
}
Console.WriteLine(addr);
Console.Read();
}
}
}
得到結果: 台北市中正區重慶南路一段一百二十二號
很好用吧!! 另外,元件也支援簡繁轉換的功能,是另一項天上掉下來的禮物,不要錯過了。
【延伸閱讀】
- Microsoft Visual Studio International Feature Pack - 支援多國語系的元件
- [C#]Visual Studio International Feature Pack 2.0 與阿拉伯數字轉繁中格式範例
【更新2009/12/23】感謝Dino與Phoenix的補充,讓我這條老狗又學到新把戲了(MatchEvaluator是好物呀!),以下我想到為解決三百"一"十問題的修正版,歡迎大家批評指教!
【更新2015/04/12】感謝YinChang補充,再加入「拾萬」要轉為「壹拾萬」之邏輯。
using System; using System.Text.RegularExpressions; using Microsoft.International.Formatters; using System.Globalization; namespace TestNumber { class Program { static void Main(string[] args) { for (int i = 0; i < 2000; i++) { Console.Write(FormatChineseNumber(i, false) + " "); } Console.WriteLine(FormatChineseNumber( string.Format("中華民國{0}年{1}月{2}日", DateTime.Today.Year - 1911, DateTime.Today.Month, DateTime.Today.Day), false)); Console.WriteLine(FormatChineseNumber(12.345M, false)); Console.WriteLine(FormatChineseNumber(3100000M, true)); Console.WriteLine(FormatChineseNumber(100000M, true)); Console.Read(); } /// <summary> /// 將字串的數字部分轉為中文大寫 /// </summary> /// <param name="s">原始字串</param> /// <param name="moneyChar"> /// 是否使用金額大寫,true時使用"壹貳參肆...", false時則為"一二三四..." /// </param> /// <returns>轉換後字串</returns> static string FormatChineseNumber(string s, bool moneyChar) { return Regex.Replace(s, "\\d+", m => { int n = int.Parse(m.Value); return FormatChineseNumber(n, moneyChar); }); } /// <summary> /// 修正EastAsiaNumericFormatter.FormatWithCulture出現"三百十"之問題, /// 本函數會將其修正為三百一十的慣用寫法 /// 2015-04-12更新,增加拾萬改為壹拾萬邏輯 /// </summary> /// <param name="n">要轉換的數字</param> /// <param name="moneyChar"> /// 是否使用金額大寫,true時使用"壹貳參肆...", false時則為"一二三四..." /// </param> /// <returns>轉為中文大寫的數字</returns> static string FormatChineseNumber(decimal n, bool moneyChar) { //"L"-大寫,壹貳參... "Ln"-一二三... "Lc"-貨幣,同L string t = EastAsiaNumericFormatter.FormatWithCulture( moneyChar ? "L" : "Ln", n, null, new CultureInfo("zh-TW")); string pattern = moneyChar ? "[^壹貳參肆伍陸柒捌玖]拾" : "[^一二三四五六七八九]十"; string one = moneyChar ? "壹" : "一"; string res = Regex.Replace(t, pattern, m => { return m.Value.Substring(0, 1) + one + m.Value.Substring(1); }); //拾萬需補為壹拾萬 if (moneyChar && res.StartsWith("拾")) { res = "壹" + res; } return res; } } } |
Comments
# by chuck
原來還有這種東西喔 真好用EastAsiaNumericFormatter.FormatWithCulture
# by Dino
透過黑大理解到 Microsoft Visual Studio International Feature Pack 2.0 的功能了! 不過我覺得 Regex 的做法 這樣可能會更好: -------------- string addr = "台北市中正區重慶南路1段122號"; string tran = Regex.Replace(addr, @"\d+", delegate(Match match) { int n = int.Parse(match.Value); return EastAsiaNumericFormatter.FormatWithCulture("Ln", n, null, new CultureInfo("zh-TW")); }); --------------
# by Phoenix
原來已經有人知道.Net Regex的秘密能力了@@ 用Lambda Expression再簡化程式碼。 ------------------------------------------ string addr = "台北市中正區重慶南路1段122號"; addr = Regex.Replace(addr, "\\d+", m => EastAsiaNumericFormatter.FormatWithCulture( "Ln", int.Parse(m.Value), null, new CultureInfo("zh-TW"))); Console.WriteLine(addr); Console.Read();
# by Dino
To Phoenix, 讚!
# by Jeffrey
to Dino, Phoenix, 感謝補充,我又學到新東西囉(灑花~~)。我在三百"一"十改良版中已融入MatchEvaluator+Lambda的做法,謝謝兩位!
# by YinChang
感謝分享關於所提的"310"會被轉成"三百十"的bug, 補充說明一下轉大寫貨幣要注意一下(剛好被客戶抓到), 如:"拾萬元整"正確是"壹拾萬元整" 應該是同一bug,需多判斷開頭為"拾"需在前頭補上"壹"
# by Jeffrey
to YinChang, 已在程式再加入「拾萬」補為「壹拾萬」邏輯,感謝你的補充讓程式更完整。
# by Gemo
發現使用.NET 6實作時發現 原本指定的CultureInfo(“zh-CHT)會被assign它的Parent, zh-Hant 但後面的if條件卻沒有zh-Hant 然後就會出現"The specified format is not supported in this culture.