如何把string解析為int?[C#]
How to Parse a string to an int? [C#]
Writen by Allen Lee
今天無意中碰到将字元轉換為整型的問題。發現了Convert.ToInt32()這個函數在網絡上搜尋後發現下面的文章總體感覺自己的水準還相差很遠啊!
Q:如何把string解析為int?
A:簡單的方法有三種:
Q:這三種方法有什麼不同?
A:一個簡單的回答是:
如果解析失敗,Int32.Parse(source)總會抛出異常;Convert.ToInt32(source)在source為null的情況下不會抛出異常而是簡單的傳回0給調用方;而Int32.TryParse(source, result)則無論如何都不抛出異常,隻會傳回true或false來說明解析是否成功,如果解析失敗,調用方将會得到0值。
Q:如果我要解析的字元串的字面數值不是十進制的話,那麼從這些方法中得到的傳回值是有問題的。有什麼方法解決?
A:那麼你就需要這些方法的對應重載版本了,一個簡單的方法是使用Convert類的
其中fromBase的值隻能為2、8、10或者16,用于指定進制方式。如果fromBase不是指定的數值或者value不為十進制而又帶有字首正負号,就會抛出ArgumentException。
當然,你還可以通過為Int32類的
指定NumberStyles.AllowHexSpecifier或者NumberStyles.HexNumber為第二個參數來解析十六進制字面值的字元串,此時,你需要引用System.Globalization命名空間。
或者使用Int32類的
并指定NumberStyles.AllowHexSpecifier或者NumberStyles.HexNumber為第二個參數,null為第三個參數來解析十六進制字面值的字元串。你當然也應該引用System.Globalization命名空間。
這裡有一點要提醒的是,無論使用Parse或者TryParse方法來解析十六進制,字元串都不能出現0x或0X字首,否則将會抛出異常。
Q:如果我要把使用科學記數法表示的string轉換為int又該如何呢?
A:你可以通過把NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent(把兩個NunberStyles枚舉進行位運算,其中前者說明可能存在小數點,而後者則說明可能存在科學記數法的指數符号)作為第二個參數傳遞給Int32類的
或者
如果解析出來的結果與int不相容的,就要考慮把結果儲存在别的類型了。例如"1.412e2"就應該把解析結果存放到float或者double或者decimal類型的變量裡,當然,你也應該使用與儲存變量相對應的類型的方法來解析:
整個字元串表達式應該沒有任何任何空格,否則将有可能抛出異常。
科學記數法的格式為[{+|-}]m.dddddd{e|E}[{+|-}]xx,可以分解為以下幾種形式:
- [-]m.dddddde+xx
- [-]m.dddddde-xx
- [-]m.ddddddE+xx
- [-]m.ddddddE-xx
下面列舉一些不能正常解析的:
- "1.412 e3"
- "1.412E 3"
- "1.412e +3"
- "141200E- 2"
Q:如何處理待解析string裡所包含的空格?
A:對于字元串的字首或字尾空格,你同樣有多種選擇,一般情況下,你可以直接使用String類的
來取掉頭尾可能包含的空格:
又或者,你使用NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite來告訴Parse或TryParse待解析字元串的頭尾可能包含着空格。
如果待解析的字元串使用科學記數法來表示,那麼你可以
其中NumberStyles.Float告訴Parse方法待解析的字元串可能字首或字尾的空格、字首正負号、(十進制)小數點、科學記數法指數表示等。
Q:如何處理貨币字元串的解析?
A:你可以通過指定NumberStyles.Currency來告訴Parse或TryParse待解析的字元串是貨币樣式的。NumberStyles.Currency說明待解析字元串可能包含字首或字尾空格、字首正負号、十進制小數點、千分位符号、字面數值可能為整數或小數等:
但貨币樣式字元串不能帶有任何十六進制符号。另外,貨币樣式字元串格式的相關設定以Region and Languages Options(區域與語言選項)裡面的設定為基準。
Q:如果我更改系統的Region and Languages Options(區域與語言選項)裡面的設定,但又希望不按照裡面的設定來解析字元串呢?
A:這個時候就輪到NumberFormatInfo類出場了,這個類能夠讓你無需對系統的設定作任何修改而直接告訴相關的方法如何處理字元串裡的相關符号。
對應上圖,我們通過NumberFormatInfo的相關屬性來設定Customerize Regional Options(自定義區域選項)中Currency(貨币)頁籤裡的相關設定:
NumberFormatInfo | Currency(貨币) |
CurrencySymbol | Currency symbol(貨币符号) |
CurrencyPositivePattern | Positive currency format(貨币正數格式) |
CurrencyNegativePattern | Negative currency format(貨币符号格式) |
CurrencyDecimalSeparator | Decimal symbol(小數點) |
CurrencyDecimalDigits | No. of digits after decimal(小數數位) |
CurrencyGroupSeparator | Digit grouping symbol(數字分組符号) |
其中,Customerize Regional Options(自定義區域選項)中Currency(貨币)頁籤裡的Digit grouping(數字分組)需要結合NumberFormatInfo的CurrencyGroupSeparator和CurrencyGroupSizes兩個屬性來設定。而NumberFormatInfo的CurrencyPositivePattern和CurrencyNegativePattern屬性的設值是有限制的:
CurrencyPositivePattern | |
Value | Associated Pattern |
$n | |
1 | n$ |
2 | $ n |
3 | n $ |
CurrencyNegativePattern | |
Value | Associated Pattern |
($n) | |
1 | -$n |
2 | $-n |
3 | $n- |
4 | (n$) |
5 | -n$ |
6 | n-$ |
7 | n$- |
8 | -n $ |
9 | -$ n |
10 | n $- |
11 | $ n- |
12 | $ -n |
13 | n- $ |
14 | ($ n) |
15 | (n $) |
Q:設定好的NumberFormatInfo的執行個體應該怎麼使用?
A:NumberFormatInfo是IFormatProvider接口的一個實作,你可以把NumberFormatInfo的執行個體作為參數傳遞給對應的重載方法。
Q:那麼,Customerize Regional Options(自定義區域選項)中Numbers(數字)頁籤裡的設定是否也能通過NumberFormatInfo的對應屬性來設定?
A:不全是,其中Display leading zeros(零起始顯示)、List separator(清單分隔符)、Measurement system(度量衡系統)這三項沒有;Negative number format(負數格式)需要同時結合使用NumberFormatInfo的NegativeSign、NumberDecimalDigits、NumberDecimalSeparator等來設定;其他的都能在NumberFormatInfo中找到與之對應的屬性。
Q:那麼,Display leading zeros(零起始顯示)、List separator(清單分隔符)、Measurement system(度量衡系統)這三項在哪裡有對應的設定呢?
A:很抱歉,到目前為止我也找不到對應的地方來設定,如果你或者其他人找到了,請務必告訴我。(不過,你可以通過RegionInfo.IsMetric這個隻讀屬性來檢測目前系統是否使用Metric(公制)度量系統。)
Q:如果我無法推斷待解析的字元串應該使用哪一個或多個NumberStyles枚舉呢?
A:這種情況一般不會發生,待解析的字元串肯定是有一定的目的或用途的,這些目的或用途就是字元串字面樣式的限制,而NumberStyles枚舉的作用就是說明這種限制的。當然,如果你目前确實無法推斷,那麼你可以使用NumberStyles.Any枚舉。
Q:在具體的編碼過程中,我如何知道應該選擇哪一種方法來解析字元串呢?
A:就我個人來說,我會:
- 首先,你得清楚你所使用的CLR版本是否提供某種方法的支援,例如,TryParse是.NET 2.0或以上才支援的。
- 其次,你可以通過方法的重載簽名來選擇,如果你要解析非十進制的字元串,Convert.ToInt32可能是你唯一的選擇,除了十進制和十六進制,你可以用它來解析二進制、八進制,但你不能用Int32.Parse或Int32.TryParse來解釋這些進制的字元串。當然如果是十進制或者十六進制就哪種方法都可以。
- 另外,如果你需要使用NumberStyles枚舉來告知相關方法待解析的字元串的樣式,那麼Convert.ToInt32就幫不了你了,此時你應該選擇Int32.Parse或者Int32.TryParse相應的重載。
- 再次,如果你不希望在你的代碼裡處理異常,那麼Int32.TryParse可能是你唯一的選擇,你可能根據它的傳回至來判斷解析是否成功,進而決定是否使用解析結果。但如果你希望透過異常機制通知調用方解析失敗,那麼Int32.Parse或者Convert.ToInt32都是不錯的選擇。
- 最後,選擇準則不可能唯一或者通用的的,你可能會在實踐總結出适合你自己的選擇準則,如果你有更好的選擇方法,請你也告訴我一聲。
Q:在.NET裡面,如果要将string解析為其它的基元類型(Primitive Type)是否也有類似的方法?
A:是的,在.NET裡面,我們為這些基元類型提供了Convert.ToPrimitiveType、PrimitiveType.Parse、PrimitiveType.TryParse(.NET 2.0或以上)方法,用于把string解析成對應的基元類型,當然,你得首先保證待解析的string字面值與對應的基元類型相容。這些基元類型是(括号中是對應的C#關鍵字):SByte (sbyte), Byte (byte), Int16 (short), UInt16 (ushort), Int32 (int), UInt32 (uint), Int64 (long) , UInt64 (ulong), Char (char), Single (float), Double (double) , Boolean (bool), Decimal (decimal)。另外,.NET也提供了把string解析為DateTime結構的方法,除了有上面提到的三種形式(Convert.ToDateTime、DateTime.Parse、DateTime.TryParse)之外,我們還可以使用DateTime.TryParseExact。所有的這些方法都是大同小異,差别在于對字元串字面值格式(包括其所包含符号)的規定,有興趣的話,你可以參考以下MSDN的文檔或者其他專題資料。
本為轉自部落格園http://www.cnblogs.com/allenlooplee/archive/2004/11/16/64254.aspx
int result = Int32.Parse( " $1,412 " , NumberStyles.Currency);
int result = Int32.Parse( " 1.412e3 " , NumberStyles.Float);
int result = Int32.Parse(textBox1.Text, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite);
int result = Int32.Parse(textBox1.Text.Trim());
public string Trim();
double result = Double.Parse( " 1.412e2 " , NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent);
public static bool TryParse( string s, NumberStyles style, IFormatProvider provider, out int result);
public static int Parse( string s, NumberStyles style);
public static bool TryParse( string s, NumberStyles style, IFormatProvider provider, out int result);
public static int Parse( string s, NumberStyles style);
string source = " 0x1412 " ; // 這裡的0x(或0X)字首是可選的。
int result = Convert.ToInt32(source, 16 );
public static int ToInt32( string value, int fromBase);
string source = " 1412 " ;
int result = 0 ;
// 使用Convert.ToInt32(string value);
result = Convert.ToInt32(source);
// 使用Int32.Parse(string value);
result = Int32.Parse(source);
// 使用Int32.TryParse(string s, out int result);
Int32.TryParse(source, out result);