1 前言
如果你熟悉Microsoft Foundation Classes(MFC)的CString,Windows Template Library(WTL)的CString或者Standard Template Library(STL)的字符串類,那麼你對String.Format方法肯定很熟悉。在C#中也經常使用這個方法來格式化字符串,比如下面這樣:
x = y = h = String.Format(
在我的機器上,可以得到下面的輸出:
item 16 sells at ¥3.57
也許你的機器上的輸出和這個不太一樣。這是正常的,本文稍後就會解釋這個問題。
在我們日常使用中,更多的是使用Console.WriteLine方法來輸出一個字符串。其實String.Format和Console.WriteLine有很多共同點。兩個方法都有很多重載的格式並且采用無固定參數的對象數組作為最後一個參數。下面的兩個語句會產生同樣的輸出。
Console.WriteLine( , , , , , , , , , u = String.Format(, , , , , , , , ,
輸出如下:
Hello 123 45.67 True Q 4 5 6 7 8 Hello 123 45.67 True Q 4 5 6 7 8
2 字符串格式
String.Format和WriteLine都遵守同樣的格式化規則。格式化的格式如下:"{ N [, M ][: formatString ]}", arg1, ... argN,在這個格式中:
1) N是從0開始的整數,表示要格式化的參數的個數
2) M是一個可選的整數,表示格式化後的參數所占的寬度,如果M是負數,那麼格式化後的值就是左對齊的,如果M是正數,那麼格式化後的值是右對齊的
3) formatString是另外一個可選的參數,表示格式代碼
argN表示要格式化的表達式,和N是對應的。
如果argN是空值,那麼就用一個空字符串來代替。如果沒有formatString,那麼就用參數N對應的ToString方法來格式化。下面的語句會產生同樣的輸出:
Main(, ,
輸出是:
123 123 123
也可以通過String.Format得到同樣的輸出。
s = .Format( t = .Format(, u = .Format(,
因此有如下結論:
(,M)決定了格式化字符串的寬度和對齊方向
(:formatString)決定了如何格式化數據,比如用貨幣符號,科學計數法或者16進制。就像下面這樣:
Console.WriteLine(, , ); Console.WriteLine(, , );
輸出是
123 456 123 456
也可以合並這些表達式,先放一個逗號,再放一個冒號。就像這樣:
Console.WriteLine(, , );
000123 000456
我們可以用這種格式化特性來對齊我們的輸出:
Console.WriteLine(, ,, , , , );
輸出是:
Name Salary ---------------- Bill 123456 Polly 7890
3 格式化標識符
標准的數學格式字符串用於返回通常使用的字符串。它們通常象X0這樣的格式。X是格式化標識符,0是精度標識符。格式標識符號共有9種,它們代表了大多數常用的數字格式。就像下表所示:
如果我們使用下面的表達方式,讓我們看看會發生什麼
Main( i = , i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i);
精度控制標識控制了有效數字的個數或者十進制數小數的位數。
Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i);
R(圓整)格式僅僅對浮點數有效。這個值首先會用通用格式來格式化。對於雙精度數有15位精度,對於單精度數有7位精度。如果這個值可以被正確地解析回原始的數字,就會用通用格式符來格式化。如果不能解析回去的話,那麼就會用17位精度來格式化雙精度數,用9位精度來格式化單精度數。盡管我們可以在圓整標識符後面添加有效數字的位數,但是它會被忽略掉。
d = , d); Console.WriteLine(, d);
如果標准格式化標識符還不能滿足你。你可以使用圖形化格式字符串來創建定制的字符串輸出。圖形化格式化使用占位符來表示最小位數,
最大位數,定位符號,負號的外觀以及其它數字符號的外觀。就像下表所示
看下面的例子:
i = , i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); = -, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); = , i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i); Console.WriteLine(, i);
所有的基礎類型都有ToString方法,它是從object類型中繼承過來的。所有的數值類型都有Parse方法,它用字符串為參數,並且返回相等的數值。比如
Main( i = .Parse( j = Int32.Parse( d = Double.Parse( s =
輸出如下:
i = 12345 j = 12345 d = 1234500.00 s = 12345
在缺省狀況下,某些非數字字符是可以存在的。比如開頭和結尾的空白。逗號和小數點,加號和減號,因此,下面的Parse語句是一樣的
t = g = ||||, g);
輸出都是這樣:
g = -1234567.89
注意到,如果你要使用NumberStyles,就要添加對System.Globalization的引用,然後就可以使用不同NumberStyles的組合或者其中的任意一種。如果你想兼容貨幣符號,就需要使用重載的Parse方法,它們采用了NumberFormatInfo對象作為一個參數,然後你可以設置NumberFormatInfo的CurrencySymbol屬性來調用Parse方法,比如:
u = = = h =, h);
上面的代碼有如下輸出:
h = -1234567.89
除了NumberFormatInfo,還可以使用CultureInfo類。CultureInfo代表了某種特定的文化,包括文化的名字,書寫的方式,日歷的格式。對於某種特定文化的操作是非常普遍的情況,比如格式化日期和排序。文化的命名方式遵從RFC1766標准,使用<語言代碼2>-<國家/地區碼2>的方式,其中的<語言代碼2>是兩個小寫的字母,它們來自ISO639-1;<國家/地區碼2>是兩個大寫字母,它們來自ISO3166。比如,美國英語是“en-US"。英國英語是"en-GB"。特立尼達和多巴哥英語是"en-TT"。例如,我們可以創建一個美國英語的CultureInfo對象並且基於這種文化將數字轉換成字符串。
k = = CultureInfo( v = k.ToString(
輸出是:
$12,345.00
要注意到,我們使用了重載的ToString方法,它把第一個格式化字符串當成第一個參數,將一個CultureInfo對象(執行了IFormatProvider對象)作為第二個參數。這兒有第二個例子,對於丹麥人來說:
CultureInfo dk = CultureInfo( w = k.ToString(
輸出是:
kr 12.345,00
一個日期對象有個叫Ticks的屬性。它存儲了自從公元1年的1月1號上午12點開始的,以100納秒為間隔的時間。比如,Ticks值等於31241376000000000L表示公元100年,星期五,1月1號,上午12點這一時間。Ticks總是以100納秒為間隔遞增。
DateTime的值以存儲在DateTimeFormatInfo實例裡面的標准或者自定義的方式來表示。為了修改一個日期顯示的方式,DateTimeFormatInfo實例必須要是可寫的,以便我們寫入自定義的格式並且存入屬性中
Main(=
代碼會產生下面的輸出
23/06/2001 17:55:10 date = 23/06/2001 00:00:00, time = 17:55:10.3839296
下表列出了標准的格式字符串以及相關的DateTimeFormatInfo屬性
DateTimeFormatInfo.InvariantInfo屬性得到了默認的只讀的DateTimeFormatInfo實例,它與文化無關。你可以創建自定義的模式。要注意到的是InvariantInfo不一定和本地的格式一樣。Invariant等於美國格式。另外,如果你向DateTime.Format方法傳遞的第二個參數是null,DateTimeFormatInfo將會是默認的CurrentInfo。比如
Console.WriteLine(dt.ToString(,
06/23/2001 23/06/2001
對比選擇InvariantInfo和CurrentInfo的。
(Console.Read() == ===, dtfi));
輸出是:
[I]nvariant or [C]urrent Info?: I 01/03/2002 03/01/2002 Thursday, 03 January 2002 Thursday, 03 January 2002 12:55 Thursday, 03 January 2002 12:55:03 01/03/2002 12:55 01/03/2002 12:55:03 January 03 Thu, 03 Jan 2002 12:55:03 GMT 2002-01-03T12:55:03 12:55 12:55:03 2002-01-03 12:55:03Z Thursday, 03 January 2002 12:55:03 01/03/2002 2002 January 03-Jan-02 [I]nvariant or [C]urrent Info?: C 03/01/2002 03/01/2002 03 January 2002 03 January 2002 12:55 03 January 2002 12:55:47 03/01/2002 12:55 03/01/2002 12:55:47 03 January Thu, 03 Jan 2002 12:55:47 GMT 2002-01-03T12:55:47 12:55 12:55:47 2002-01-03 12:55:47Z 03 January 2002 12:55:47 03/01/2002 January 2002 03-Jan-02
/******************************************************************************************
*【Author】:flyingbread
*【Date】:2007年1月18日
*【Notice】:
*1、本文為原創技術文章,首發博客園個人站點(http://flyingbread.cnblogs.com/),轉載和引用請注明作者及出處。
*2、本文必須全文轉載和引用,任何組織和個人未授權不能修改任何內容,並且未授權不可用於商業。
*3、本聲明為文章一部分,轉載和引用必須包括在原文中。
******************************************************************************************/