zoukankan      html  css  js  c++  java
  • .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为格式组件,用于将对象格式化为想要的字符串。

  • 相关阅读:
    二分图的部分关系
    二分图的部分关系
    日常训练赛 Problem C – Complete Naebbirac’s sequence
    日常训练赛 Problem C – Complete Naebbirac’s sequence
    J
    J
    Python strip()方法
    Python startswith()方法
    Python splitlines()方法
    Python split()方法
  • 原文地址:https://www.cnblogs.com/lsxqw2004/p/1375202.html
Copyright © 2011-2022 走看看