Thứ Hai, ngày 04 tháng 1 năm 2010

// // 1 comment

Định dạng chuỗi trong C#


Một trong những điều vất vả nhất của các ngôn ngữ lập trình cấp thấp đó chính là định dạng kiểu chuỗi. Nhưng trong C#, mọi chuyện sẽ thật đơn giản!

Để So sánh Định dạng chuỗi trong C ta làm như sau:

char szOutput[256];
sprintf(szOutput, "At loop position %d.\n", i);

Lệnh sprintf thông qua 1 vùng đệm ra, 1 chuỗi định dạng và bất kỳ còn số nào của tham số để thay thế vào chuỗi định dạng đó. điều này hay gây ra lỗi tràn vùng đệm.

Tương đương với Lệnh sprintf trong C# là String.Format, sẽ lấy 1 chuỗi có định dạng và 1 tham số. Nó trả về 1 chuỗi và bởi vì bạn không truyền thông qua vùng đệm nên không sợ bị lỗi tràn vùng đệm như trong C. ta xem câu lệnh sau:

string outputString = String.Format("At loop position {0}.\n", i);

Vì vậy, tại sao lại không có các kiểu tham số định dạng mà có các tham số đặc tả những kiểu mà bạn cần định dạng nhỉ? Đối tượng CLR có những siêu dữ liệu (matadata) mà thể hiện tất cả những gì mà bạn cần và mỗi đối tượng đều có một phương thức ToString() chuẩn để trả về kiểu string của đối tượng đó.

Phương thức ToString có thể chấp nhận 1 tham số kiểu string mà tham số đó sẽ thông báo định dạng của đối tượng đó. Khi chúng ta dùng lệnh String.Format, chuỗi định dạng sẽ được truyền sau vị trí đó. Ví dụ: "{0:##}". các kí tự trong dấu ngoặc nhọn bắt đầu bằng {index của tham số [căn lề] : [Kiểu định dạng]}. Nếu Căn lề là số dương, thì chuỗi string sẽ được căn phải so với độ dài của chuỗi. Còn nếu là số âm thì sẽ được căn bên trái.

Các Kiểu Định Dạng

Quả thực, khi nói như vậy cũng rất là khó hiểu, nhưng khi thực hành, thì các bạn sẽ thấy đơn giản hơn rất nhiều. Có thể nói đó là lí do tại sao các sinh viên việt nam rất thông minh và học giỏi, nhưng khi bước vào thực tiễn công việc lại rất bỡ ngỡ.

Quay trở lại vấn đề, không có quá nhiều định dạng dành cho kiểu chuỗi. Đối với kiểu string, chỉ đơn giản là định dạng căn lề. Bạn hãy xem ví dụ sau nhé:

example output
String.Format("--{0,10}--", "test"); -- test--
String.Format("--{0,-10}--", "test"); --test --

các kiểu định dạng số

Định dạng kiểu số là một loại độc lập. Ví dụ, định dạng một kí tự tiền tệ để hiển thị giá trị tiền của laptop sẽ trả về giá trị như sau: £9.99. Chúng ta hãy xem bảng giới thiệu bên dưới:

specifier type format output
(double 1.2345)
output
(int -12345)
c currency {0:c} £1.23 -£12,345.00
d decimal
(whole number)
{0:d} System.FormatException -12345
e exponent / scientific {0:e} 1.234500e+000 -1.234500e+004
f fixed point {0:f} 1.23 -12345.00
g general {0:g} 1.2345 -12345
n number {0:n} 1.23 -12,345.00
r round trippable {0:r} 1.23 System.FormatException
x hexadecimal {0:x4} System.FormatException ffffcfc7

Các bạn hãy để ý rằng chuỗi định dạng thường bắt đầu với các ký tự đầu của các kiểu mà bạn muốn chuyển sang.

Tùy biến cho định dạng kiểu số:

specifier type format output
(double 1234.56)
0 zero placeholder {0:00.000} 1234.560
# digit placeholder {0:#.##} 1234.56
. decimal point placeholder {0:0.0} 1234.6
, thousand separator {0:0,0} 1,235
% percentage {0:0%} 123456%

ta thấy, trong việc định dạng cho kí tự, có rất nhiều các kí tự ngăn cách và được chia thành các nhóm khác nhau: Kí tự 0 thay thế cho kí tự thừa bằng số 0, kí tự # thay thế cho các vị trí định dạng bằng các con số, dấu chấm (.) , dấu phẩy (,) và kí tự % ...

String.Format("{0:£#,##0.00;(£#,##0.00);Nothing}", value);

chuỗi lệnh trên nếu ta truyền vào một giá trị là 1234.56 thì giá trị trả về sẽ là "£1,240.00". và nếu các con số là 0 thì chuỗi kết quả nhận được sẽ là chuỗi "Nothing".

Định dạng ngày tháng:

Định dạng theo kiểu ngày phụ thuộc thông tinh Culture được truyền vào. Các ví dụ sau sẽ thể hiện rõ hơn các đặc tả về định dạng ngày tháng:

specifier type output
(June 8, 1970 12:30:59)
d Short Date 08/06/1970
D Long Date 08 June 1970
t Short Time 12:30
T Long Time 12:30:59
f Full date and time 08 June 1970 12:30
F Full date and time (long) 08 June 1970 12:30:59
g Default date and time 08/06/1970 12:30
G Default date and time (long) 08/06/1970 12:30:59
M Day / Month 8 June
r RFC1123 date string Mon, 08 Jun 1970 12:30:59 GMT
s Sortable date/time 1970-06-08T12:30:59
u Universal time, local timezone 1970-06-08 12:30:59Z
Y Month / Year June 1970

Bên trên là định dạng ngày tháng theo UK, còn nếu theo kiểu việt thường dùng thì ta dùng lệnh sau:

ví dụ định dạng ngày tháng cho một giá trị trong gridview hay datalist ta dùng lệnh : <%# Eval("value", "{0: dd/MM/yyyy}") %>

Định dạng ngày tháng tùy biến:

specifier type output
(June 8, 1970 12:30:59)
dd Day 08
ddd Short Day Name Mon
dddd Full Day Name Monday
hh 2 digit hour 12
HH 2 digit hour (24 hour) 12
mm 2 digit minute 30
MM Month 06
MMM Short Month name Jun
MMMM Month name June
ss seconds 59
tt AM/PM PM
yy 2 digit year 70
yyyy 4 digit year 1970
: seperator, e.g. {0:hh:mm:ss} 12:30:59
/ seperator, e.g. {0:dd/MM/yyyy} 08/06/1970

trên đây là một số các định dạng thông thường mà chúng ta hay dùng.

Thông Tin Culture

string.format cũng cung cấp 1 số hàm mà chấp nhận các tham số CultureInfo, như là IFormatProvider. Điều này rất quan trọng khi bạn cố gắng viết các đoạn mã linh động và mang tính chất hình thái. Ví dụ, tên của tháng sẽ thay đổi theo định dạng ngôn ngữ và văn hóa đang chạy trên máy của chúng ta. Thật là đơn giản khi chỉ cần dùng câu lệnh String.Format, và các hàm Overloaded khác. Nếu bạn không cần chỉ rõ 1 culture, bạn có thể dùng System.Globalization.CultureInfo.InvariantCulture, nó sẽ đặt định dạng của bạn theo kiểu English, khác với culture đang dùng hiện tại.

1 comments:

Nặc danh nói...

Bài viết bổ ích quá, Cám ơn anh đã chia sẻ cho mọi người, nếu được anh lên cập nhật cả các ví dụ nữa sẽ dễ hiểu hơn.