.Net学习难点讨论系列6 .Net中对字符串处理的方法

此文章在aieronghttp://www.cnblogs.com/aierong/archive/2005/04/26/145617.html基础上稍加改动。感谢原作者。

.Net提供了将数值、枚举或日期时间等数据类型表示为字符串的方法(依赖于给ToString()方法传入参数),也提供了(包括自定义解析过程)将字符串表示为某种类型的方法(类/对象名.Parse(string))。

格式化由格式说明符字符的字符串控制,该字符串指示如何表示基类型值;或者怎样将一个字符串解释为某个类型。

例如,格式说明符指示是否应该用科学记数法来表示格式化的数字;格式字符"C",表示货币格式等。(参考附录表格)

同时.NET Framework还使用区域性设置,以便用适合于特定区域性的形式表示基类型。

我们可以提供自定义的区域性设置,或者使用与当前线程关联的默认区域性设置。

例如,格式化货币类型的时候,区域性设置指定用于货币符号;格式化时间时根据区域设置来将一个字符串解释为DateTime型(DateTime.ParseExact()方法)。

本文主要介绍字符串格式控制

要是我们想拥有自己定义的格式化,.NET Framework也允许我们定义自己格式化方案和自定义区域性设置。例如:我想格式字符"MyFormat",来说明我自定义的格式,即在字符前加三个***,下文有代码示例。

提示:

关于数字格式字符串,可以参考类

System.Globalization.NumberFormatInfo

关于日期与时间格式字符串,可以参考类

System.Globalization.DateTimeFormatInfo

一个类要想实现格式化字符串输出需要实现Iformattable接口,先看看IFormattable接口的原型:

1 public interface IFormattable
2 {
3     string ToString(string format, IFormatProvider formatProvider);
4 }

参数说明:

  • format: 指定要使用的格式的 String,当为空引用时,表示使用为IFormattable实现的类型定义的默认格式。
  • formatProvider: 用于格式化该值的 IFormatProvider,当为空引用时,从操作系统的当前区域设置中获取格式信息的。

一些基本的值类型实现了该接口,例如: Int32 ,UInt32 , DateTime ,Guid ,类Enum。

其中的IFormatProvider接口的原型

1 public interface IFormatProvider
2 {
3     object GetFormat(Type formatType);
4 }

参数说明:

  • formatType: 一个对象,它指定要获取的格式对象的类型

NumberFormatInfo、DateTimeFormatInfo和CultureInfo实现IFormatProvider接口。

  • NumberFormatInfo: 提供数字格式信息,如用于小数分隔符和千位分隔符的字符,以及货币值中货币符号的拼写和位置。
  • DateTimeFormatInfo: 提供与日期相关和与时间相关的格式信息,如日期模式中月、日和年的位置。
  • CultureInfo: 包含特定区域性中的默认格式信息,其中包括数字格式信息以及与日期相关和与时间相关的格式信息。


再看看ICustomFormatter接口的原型:

1 public interface ICustomFormatter
2 {
3     string Format(string format, object arg, IFormatProvider formatProvider);
4 }

参数说明:

  • format: 包含格式规范的格式字符串。为空时 ,将使用默认格式规范。
  • arg: 要格式化的对象。其为空引用时,引发异常。
  • formatProvider : 一个IFormatProvider对象,它提供有关当前实例的格式信息。为空时,则忽略该参数。

代码示例:格式字符串"MyFormat",在字符前加三个***。

 1 using System;
 2 
 3 public class MyClass : IFormattable
 4 {
 5     Double d;
 6 
 7     public MyClass(Double d)
 8     {
 9         this.d = d;
10     }
11 
12     public string ToString(string format, IFormatProvider formatProvider)
13     {
14         return (format == "MyFormat") ?
15             "***" + d.ToString(formatProvider)
16             : d.ToString(format, formatProvider);
17     }
18 }
19 
20 class Program
21 {
22     public static void Main()
23     {
24         System.Globalization.CultureInfo culture = null;
25 
26         MyClass myClass = new MyClass(5);
27 
28         //当IFormatProvider为空时,调用的是当前线程关联的文化信息 
29         Console.WriteLine("显示当前线程关联的文化信息(中国)货币格式:{0}", myClass.ToString("C", null));
30 
31         culture = System.Globalization.CultureInfo.CurrentCulture;
32         Console.WriteLine("显示当前系统默认货币格式:{0}", myClass.ToString("C", culture));
33 
34         culture = new System.Globalization.CultureInfo("zh-HK");
35         Console.WriteLine("显示香港特别行政区货币格式:{0}", myClass.ToString("C", culture));
36 
37         Console.WriteLine("显示我自己定义的货币格式:{0}", myClass.ToString("MyFormat", null));
38 
39         Console.ReadLine();
40     }
41 }

输出结果:

显示中国货币格式:¥5.00

显示当前系统默认货币格式:¥5.0

显示香港特别行政区货币格式:HK$

显示我自己定义的货币格式:***5

以上示例中CultureInfo类的对象作为IFormatProvider类型的参数传入。自定义中调用了Double对象的ToString方法,因为Double对象也实现了IFormattable接口。

如果希望自定义格式化能在多个不同类使用,那么实现我们应该定义一个实现ICustomFormatter接口的类:

 1 using System;
 2 
 3 public class MyBaseFormat : ICustomFormatter, IFormatProvider
 4 {
 5     //如果format Type与当前实例类型相同,则为当前实例,否则为空引用 
 6     public object GetFormat(Type format)
 7     {
 8         if (format == typeof(ICustomFormatter))
 9             return this;
10         return null;
11     }
12 
13     //实现Format方法说明: 
14     //如果您的格式方法不支持格式,则确定正在设置格式的对象是否实现IFormattable接口。 
15     //如果实现,请调用对象的接口上的IFormattable.ToString方法。 
16     //否则,调用对象基类默认的Object.ToString方法。 
17     public string Format(string format, object arg, IFormatProvider provider)
18     {
19         if (format == null)
20         {
21             if (arg is IFormattable)
22                 return ((IFormattable)arg).ToString(format, provider);
23             return arg.ToString();
24         }
25         else
26         {
27             if (format == "MyBaseFormat")
28             {
29                 return "***" + arg.ToString();
30             }
31             else
32             {
33                 if (arg is IFormattable)
34                     return ((IFormattable)arg).ToString(format, provider);
35                 return arg.ToString();
36             }
37         }
38     }
39 }
40 
41 class Program
42 {
43     public static void Main()
44     {
45         string printString = String.Empty;
46         int i = 100;
47         MyBaseFormat myBaseFormat = new MyBaseFormat();
48 
49         printString = string.Format(myBaseFormat, "显示正常格式:{0}", i);
50         Console.WriteLine(printString);
51         printString = string.Format(myBaseFormat, "显示正常格式:{0:C}", i);
52         Console.WriteLine(printString);
53         printString = string.Format(myBaseFormat, "显示自定义格式{0:MyBaseFormat}", i);
54         Console.WriteLine(printString);
55 
56         Console.ReadLine();
57     }
58 }

输出如下:

显示正常格式:100

显示正常格式:¥100.00

显示自定义格式***100

总结:
1.如果需要您自己的格式化包含在某个类上,在该类上实现IFormattable接口。
2.如果希望自定义格式化并使它可供多个不同类使用,那么实现 ICustomFormatter接口。

下面的函数是一个在网上找的的使用IFormattable的例子:

 1 using System;
 2 
 3 /// <summary> 
 4 /// "点"类的定义。 
 5 /// </summary> 
 6 public class Point : IFormattable
 7 {
 8     /// <summary> 
 9     /// 点类的横纵坐标。 
10     /// </summary> 
11     private int m_x, m_y;
12 
13     public Point(int x, int y)
14     {
15         m_x = x;
16         m_y = y;
17     }
18 
19     #region IFormattable 成员
20     /// <summary> 
21     /// 用于生成格式字符串的函数。 
22     /// </summary> 
23     /// <param name="format">格式字符串。</param> 
24     /// <param name="formatProvider">区域格式信息对象。</param> 
25     /// <returns></returns> 
26     public string ToString(string format, IFormatProvider formatProvider)
27     {
28         string retString;
29         try
30         {
31             //判断格式字符串。 
32             switch (format.ToUpper())
33             {
34                 //自定义的通用格式。
35                 //"点"对象的字符串格式为:"(十进制数字,十进制数字)"。
36                 case "G":
37                     retString = string.Format(formatProvider, "({0},{1})", m_x, m_y);
38                     break;
39                 //自定义的标准格式。
40                 //"点"对象的字符串格式为:"<十进制数字,十进制数字>"。
41                 case "S":
42                     retString = string.Format(formatProvider, "<{0},{1}>", m_x, m_y);
43                     break;
44                 //自定义的默认格式。
45                 //"点"对象的字符串格式为:"(十六进制数字,十六进制数字)"。
46                 default:
47                     retString = string.Format(formatProvider, "({0:X},{1:X})", m_x, m_y);
48                     break;
49             }
50         }
51         catch (NullReferenceException)
52         {
53             //格式字符串为空,返回通用格式。 
54             retString = string.Format(formatProvider, "({0},{1})", m_x, m_y);
55         }
56         return retString;
57     }
58     #endregion
59 }
60 /// <summary> 
61 /// Test 的摘要说明。 
62 /// </summary> 
63 public class Test
64 {
65     public static void Main()
66     {
67         //定义一个点。 
68         Point p = new Point(13, 10);
69         //打印默认格式的点。 
70         Console.WriteLine("{0}", p);
71         //打印标准格式的点。 
72         Console.WriteLine("{0:S}", p);
73 
74         Console.ReadLine();
75     }
76 }

程序输出如下:

(13,10)

<13,10>

 注意:如果不实现IFormattable接口也可以用string.Format这些方法打印自定义类的对象,但string.Format方法只是调用object.ToString方法将类名打印出来。

下面是string.Format这些方法调用ToString的处理顺序:
1.如果要格式化的对象的值是 null,则返回空字符串 ("")。
2.如果要格式化的对象所属的类实现了 ICustomFormatter 接口,则调用ICustomFormatter.Format 方法。
3.如果前面的ICustomFormatter.Format 方法未调用,并且该类实现了 IFormattable 接口,则调用IFormattable.ToString 方法。
4.如果前面的步骤未格式化类型,则调用该类型的ToString方法(从 Object 类继承而来)。
然而,只有实现了IFormattable或ICustomFormatter这些接口才能识别我们自己定义的格式字符串,打印出我们想要的结果。

附录:

C#格式化数值结果表

字符

说明

示例

输出

C

货币

string.Format("{0:C3}", 2)

2.000

D

十进制

string.Format("{0:D3}", 2)

002

E

科学计数法

string.Format("{0:E}", 1.20E+001)

1.20E+001

G

常规

string.Format("{0:G}", 2)

2

N

用分号隔开的数字

string.Format("{0:N}", 250000)

250,000.00

X

十六进制

string.Format("{0:X000}", 12)

C

   

string.Format("{0:000.000}", 12.2)

012.200

string.Format()控制字符串缩进小技巧:

Sample

Generates

String.Format("->{1,10}<-", "Hello");

-> Hello<-

String.Format("->{1,-10}<-", "Hello");

->Hello <-

最后还有一些需要介绍的小技巧:

C# 中String.Format接收的标记,可以以任意顺序使用,且可以在格式字符串中替换任意次。

下面的例子的很好的解释了上文所述:

1 Console.WriteLine("The output is {1}, {0} and {1}.", "3", "6");

程序输出为:

The output is 6, 3 and 6.

具体格式项的语法如下:{index, alignment:format}

  • index为索引号,这是我们最常见的也是必须的。
  • alignment,可选项,表示格式化后的字符串占的长度,及左对齐还是右对齐(整数或负数),如果指定的长度比字符串短,则对齐设置会被忽略

如:

1 string str = "cnblogs";
2 Console.WriteLine("|{0,10}|",str);
3 Console.WriteLine("|{0,-10}|",str);

对齐效果如下:

|   cnblogs|

|cnblogs   |

format为格式组件,用于将对象格式化为想要的字符串。

原文地址:https://www.cnblogs.com/lsxqw2004/p/1375202.html