[C#]簡單快速將各種數值字數轉成數字(string to int)

相信大家在寫程式的時候,一定有非常多的機會要將數值字數(numeric string)轉成 int 或 float型別的值,但數值字數可能不是很乾淨,有時還會有千分位、貨幣符號、前後有空白、甚至不是10進位,這樣轉換就有點累,像千分位或貨幣符號以前我是用 Replace 將 , $ 等符號刪除後再轉換,但如果你是使用.Net Framework 2.0 以上其實就不用那麼麻煩,內建就有功能幫你處理這些雜七雜八的東西,讓我們來看看怎麼做吧。

相信大家在寫程式的時候,一定有非常多的機會要將數值字數(numeric string)轉成 int 或 float型別的值,但數值字數可能不是很乾淨,有時還會有千分位、貨幣符號、前後有空白、甚至不是10進位,這樣轉換就有點累,像千分位或貨幣符號以前我是用 Replace 將 , $ 等符號刪除後再轉換,但如果你是使用.Net Framework 2.0 以上其實就不用那麼麻煩,內建就有功能幫你處理這些雜七雜八的東西,讓我們來看看怎麼做吧。

 

使用 int.Parse 或 int.TryParse

沒看錯就是 int.Parse ,使用 int.Parse 就可以做到含有千分位、貨幣符號的 String 轉型。

可能你會說我騙你,那想必沒有看看 Parse 這個方法(Method) 的其他參數,Parse 其中有一個參數 System.Globalization.NumberStyles 列舉型別(Enum)就是用來宣告說傳入的 string 的樣允許式,而NumberStyles的成員如下表:

名稱 說明
None 一定要剛剛好是10進位整數數字。
AllowLeadingWhite 數字的前方允許有空白。
AllowTrailingWhite 數字的後方允許有空白。
AllowLeadingSign 數字的前方允許有正負號。
AllowTrailingSign 數字的後方允許有正負號。
AllowParentheses 允許有一對括住數字的括弧,括號表示要剖析的字串代表負數。
AllowDecimalPoint 數值字串可以有小數點。
AllowThousands 數值字串可以包含群組分隔符號。
AllowExponent 數值字串可以採用指數標記法。
AllowCurrencySymbol 數值字串可以包含貨幣符號。
AllowHexSpecifier 數值字串使用十六進位值,但不能在前方加上"0x" 或 "&h"。

以下是組合成員:

名稱 說明
Integer AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign。
HexNumber AllowLeadingWhite | AllowTrailingWhite | AllowHexSpecifier。
Number AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign | AllowDecimalPoint | AllowThousands。
Float AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowDecimalPoint | AllowExponent。
Currency 除了AllowExponent 和 AllowHexSpecifier 之外的所有樣式。
Any 除了AllowHexSpecifier 之外的所有樣式。

這只是簡表,詳細內容請看[MSDN]NumberStyles 列舉型別

而 int.Parse 預設使用的 NumberStyles 是 Integer,Integer 只允許前後有空白與加減的樣式,所以傳入其他。

 

還有其他如 decimal.Parse、float.Parse、byte.Parse、short.Parse 等等數字型的 ValueType 都支援使用 NumberStyles,因為其實他們都是用同一隻 Class 來處理轉換,只是使用的 NumberStyles 不同而已,如 decimal.Parse 預設使用的值為 NumberStyles.Currency 。

而 TryParse 是在轉換時比較好的方法,因為 Parse 是值的格式不正確就會丟出 Exception 如果程式沒有寫好可能會使程式關閉,但 TryParse 就不一樣,值的格式不正確只有不回傳轉換後的值而已,不會造成大太的災難(不過也不一定,因為可能原本遇期用 TryParse 接收轉換值的變數一定會有值,但轉換失敗又沒有做其他的處理,最後可能還是產生了 NullReferenceException,要避免這樣的問題發生,可以參考防禦式編程(Defensive programming)的精神)。

 

使用範例

//含有千分位
int value1 = int.Parse("1,000,000", NumberStyles.AllowThousands);		
int value2 = (int)decimal.Parse("1,000,000"); //當然用decimal.Parse也可以,只是要轉型

//但有小數就不能用int.Parse會失敗
int value3 = (int)decimal.Parse("1,000,000.50", NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint);	

//有貨幣符號也可以,但$與數字不能分開,但使用電腦的文化設定
int value4 = int.Parse("NT$1,000,000", NumberStyles.AllowCurrencySymbol | NumberStyles.AllowThousands);

//也可以使用不同國家的文化設定
int value5 = int.Parse("$1,000,000", NumberStyles.Any, CultureInfo.GetCultureInfo("en")); //美國	
int value6 = int.Parse("¥1,000,000", NumberStyles.Any, CultureInfo.GetCultureInfo("ja")); //日本

//指數
int value7 = int.Parse("1E+6", NumberStyles.AllowExponent);

//括弧
int value8 = int.Parse("(1,000,000)", NumberStyles.AllowParentheses | NumberStyles.AllowThousands);

//16進位
int value9 = int.Parse("F4240",NumberStyles.HexNumber);

//前後空白
int value10 = int.Parse("  1000000  ",NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite);

//但百分值不支援,要額外處理
int str =  "10.5%";
if (str.IndexOf('%')>-1)
{
	int value11 = decimal.Parse(str.TrimEnd(new char[] {'%',' '})) / 100M;		
}

//2或8進位,要使用另一個 Method
int value12 = Convert.ToInt32("11110100001001000000", 2);
int value13 = Convert.ToInt32("3641100", 8);

//如果懶惰可以這樣寫,只是效能會差一點點
int value14 = (int)decimal.Parse("1,000,000", NumberStyles.Any);

參考資料

[MSDN]NumberStyles 列舉型別

[Wikipedia]Defensive programming