第4章 操作字符串

开发人员在实际开发过程中,对字符串的操作是经常遇到的,其中涉及字符串拼接、拆分、比较、替换等操作。Visual C#对于文字的处理大多是通过对字符和字符串的操作来进行的,同时还为开发人员提供了功能强大的函数。本章向读者介绍C#中的字符串操作,首先介绍C#字符串类型,然后结合实例讲解字符串的各种操作,最后介绍正则表达式和C# 4.0新特性之智能提示的改进。

4.1 C#字符串类型

Visual C#提供了String类型,String和StringBuilder两种类来对字符串进行处理。string是.NET Framework中String的别名,string也是C#基本类型,String是Visual C#中一个功能非常强大、用途非常广泛的基类。string与String实质上没什么区别,只是在C#的编译时,会自动的把string转化为System.String,多做一次转换。因此,在编码时推荐使用String。StringBuilder类主要用于长字符串的操作,StringBuilder表示可变字符串,它允许用户有效地对字符串的字符执行动态操作,有效地缩减字符串的大小或者更改字符串中的字符。

4.1.1 格式化字符串

格式化字符串是指字符串可以按照设定的格式输出显示。在C#字符串操作中,经常在类和结构中执行ToString()方法来显示给定变量的内容。但是,根据实际需求,用户常常希望以各种可能的方式显示变量的内容,在不同的文化或地区背景中有不同的格式。例如.NET System.DateTime基类,用格式化字符串操作可以把日期显示为2010-5-26、2010年5月26日、5月6日、2010年5月等格式。格式化字符串可以用ToString()方法和Format()方法。

(1)ToString()格式:

    Public string ToString(string format)

参数说明:

❑ format:用来指定字符串所要格式化的形式。

❑ ToString()是对实例对象本身进行格式化。

用法:

    double num=1.23456      //定义double变量num
    num.ToString(C)         //把num格式化为货币格式的字符

(2)Format()格式:

    Public static string Format(string format, object obj)

❑ 参数说明:format用来指定字符串所要格式化的形式。Obj表示要被格式化的对象。

❑ 返回值:format的一个副本。

用法:

    DateTime dt = DateTime.Now;              //获取系统当前日期
    string strB = string.Format("{0:D}", dt);//格式化成短日期格式

1.格式化数字

首先介绍数字的格式化,表4-1所示是数字格式字符的相关说明。

表4-1 格式化数字符属性表

【实例4-1】本例将创建一个控制台应用程序,实现格式化数字。

(1)创建控制台应用程序。

启动Visual Studio 2010,选择“文件”→“新建”菜单命令,在“新建”选项卡中选择“项目”,创建一个名称为“4.1”的控制台应用程序。

(2)在控制台项目Program.cs文件的main函数中输入下面代码:

    01   static void Main(string[] args)
    02        {
    03          double val=Math.PI;
    04          Console.WriteLine(val.ToString( ));
    05          Console.WriteLine(val.ToString("C"));
    06          Console.WriteLine(val.ToString("E"));
    07          Console.WriteLine(val.ToString("F3"));
    08          int val1 = 65535;
    09          Console.WriteLine(val1.ToString("D"));
    10          Console.WriteLine(val1.ToString("x"));
    11          Console.WriteLine(val1.ToString("X"));
    12          Single val2 = 0.123F;
    13          Console.WriteLine(val2.ToString("p"));
    14          Console.WriteLine(val2.ToString("p1"));
    15          System.Console.ReadLine();//读取Enter键之后,关闭控制台应用程序
    16        }

【代码解析】第4~14行按照不同的格式将数字格式化输出。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-1所示。

图4-1 格式化数字输出结果

2.格式化日期

格式化日期字符属性表如表4-2所示。

表4-2 格式化日期字符属性表

【实例4-2】本例将创建一个控制台应用程序,实现格式化数字的例子,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   static void Main(string[] args)
    02   {
    03          DateTime dt = DateTime.Now;
    04          Console.WriteLine(dt.ToString( ));
    05          Console.WriteLine(dt.ToString("d"));
    06          Console.WriteLine(dt.ToString("D"));
    07          Console.WriteLine(dt.ToString("f"));
    08          Console.WriteLine(dt.ToString("F"));
    09          Console.WriteLine(dt.ToString("g"));
    10          Console.WriteLine(dt.ToString("G"));
    11          Console.WriteLine(dt.ToString("M"));
    12          Console.WriteLine(dt.ToString("R"));
    13          Console.WriteLine(dt.ToString("s"));
    14          Console.WriteLine(dt.ToString("t"));
    15          Console.WriteLine(dt.ToString("T"));
    16          Console.WriteLine(dt.ToString("u"));
    17          Console.WriteLine(dt.ToString("U"));
    18          Console.WriteLine(dt.ToString("y"));
    19          System.Console.ReadLine();//读取Enter键之后,关闭控制台应用程序
    20   }

【代码解析】第4~18行按照不同的日期格式将当前日期格式化输出。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-2所示。

图4-2 格式化日期输出结果

4.1.2 比较字符串

C#中字符串的比较用String类实现,String类提供了多种方法对字符串进行比较,这里重点对常用4种方法进行介绍,分别是Compare()、CompareTo()、CompareOrdinal()、Equals()。

1.Compare()方法

Compare()方法用来比较两个字符串是否相等,Compare()提供了将当前字符串对象与另一个字符串或对象进行全面比较的方法,此方法识别区域性。可以使用此方法来比较两个字符串或两个字符串的子串。另外,还提供了考虑或忽略大小写与区域性差异的重载。Compare()方法是CompareTo()方法的静态版本。Compare()方法有很多个重载方法,下面介绍最常用的方法。格式:

    Public int Compare(string str1,string str2)

❑ 参数说明:str1和str2代表要比较的两个字符串。

❑ 返回值:如果str1等于str2则返回0,如果str1大于str2则返回1,如果str1小于str2返回-1。

Tips

比较字符串,并不是比较字符串的长度,而是从首字符开始逐个比较字符的大小,如果已分出大小则结束比较,大于则返回1,小于则返回-1,如果相等则继续比较下一个字符直到分出大小或到字符串尾,如仍相等则返回0。

字符的大小,如果是英文字母按照a到z的顺序依次增大,也就是a小于b,小写字母小于大写字母,小写字母大于单个数字字符;如果是汉字比较,则比较汉语拼音字母的大小。

【实例4-3】本例将创建一个控制台应用程序,声明两个字符串变量,然后使用Compare方法比较两个字符串大小,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace Ch4Demo2
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string str1, str2;                            //声明两个字符串str1、str2
    14             str1="张三";
    15             str2="李四";
    16             Console.WriteLine(string.Compare(str1, str2));//比较两字符串,输出比较结果
    17             str2 = "张三";
    18             Console.WriteLine(string.Compare(str1, str2));
    19             str2 = "张昭";
    20             Console.WriteLine(string.Compare(str1, str2));
    21             System.Console.ReadLine();                    //读取“Enter”键之后,关闭控制台应用程序
    22
    23          }
    24      }
    25   }

【代码解析】第16行使用Compare()函数比较两字符串,输出比较结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-3所示。

图4-3 比较字符串Compare()方法输出结果

2.CompareTo()方法

CompareTo()方法与Compare()方法相似,都可以比较两个字符串是否相等,不同的是CompareTo()方法以实例对象本身与指定的字符串作比较。格式:

    public int CompareTo (string str)

❑ 参数说明:str表示与此字符串相比较的字符串。

❑ 返回值:返回值与Compare()方法相同。

【实例4-4】本例将创建一个控制台应用程序,声明两个字符串变量,然后使用CompareTo()方法比较两个字符串大小,在控制台项目Program.cs文件的main函数中输入下面代码。

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace Ch4Demo2
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string str1, str2;                        //声明两个字符串str1、str2
    14             str1="张三";
    15             str2="李四";
    16             Console.WriteLine(str1.CompareTo(str1));  //比较两字符串,输出比较结果
    17             Console.WriteLine(str1.CompareTo(str2));
    18             Console.WriteLine(str2.CompareTo(str1));
    19             System.Console.ReadLine();                //读取“Enter”键之后,关闭控制台应用程序
    20          }
    21      }
    22   }

【代码解析】第16行使用CompareTo()函数比较两字符串,输出比较结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-4所示。

图4-4 比较字符串CompareTo()方法输出结果

3.Equals()方法

Equals()方法主要用于比较两个字符串是否相同,如果相同返回值为true,否则为false。只要使用“=”运算符,就会调用Equals()方法,Equals()方法与“=”是等价的。其常用的两种语法格式如下:

    Public bool Equals (string str)
    Public static bool Equals(string str1,string str2)

❑ 参数说明:str表示与实例比较的字符串。str1和str2表示要进行比较的两个字符串。

❑ 返回值:如果两个值相同,则为true,否则为false。

【实例4-5】本例将创建一个控制台应用程序,声明两个字符串变量,然后使用Equals(  )方法比较两个字符串是否相同,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace Ch4Demo2
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string str1, str2;                        //声明两个字符串str1、str2
    14             str1="张三";
    15             str2="李四";
    16               Console.WriteLine(str1.Equals(str1));   //比较两字符串,
                              输出比较结果
    17             Console.WriteLine(string.Equals(str1,str2));
    18             System.Console.ReadLine();                //读取“Enter”键之后,
                              关闭控制台应用程序
    19
    20          }
    21      }
    22   }

【代码解析】第16行使用Equals()函数比较两个字符串,输出比较结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-5所示。

图4-5 比较字符串Equals()方法输出结果

4.CompareOrdinal()方法

CompareOrdinal()方法比较两个字符串对象而不考虑本地区域性。其常用语法格式如下:

    Public int CompareOrdinal (string str1,string str2)

❑ 参数说明:str1和str2代表要比较的两个字符串。

❑ 返回值:如果str1等于str2则返回0,如果不等则返回str1减去str2的值。

【实例4-6】本例将创建一个控制台应用程序,声明两个字符串变量,然后使用CompareOrdinal()方法比较两个字符串是否相同,如果str1等于str2则返回0,如果不等则返回str1减去str2的值,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace Ch4Demo2
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string str1, str2;                                  //声明两个字符串str1、str2
    14             str1="e";
    15             str2="b";
    16             Console.WriteLine(string.CompareOrdinal(str1,str2));//比较两字符串,输出比较结果
    17             str2 = "e";
    18             Console.WriteLine(string.CompareOrdinal(str1, str2));
    19             str2 = "a";
    20             Console.WriteLine(string.CompareOrdinal(str1, str2));
    21             System.Console.ReadLine();           //读取“Enter”键之后,关闭控制台应用程序
    22          }
    23      }
    24   }

【代码解析】第16行使用CompareOrdinal()函数比较两个字符串,输出比较结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-6所示。

图4-6 比较字符串CompareOrdinal()方法输出结果

4.1.3 连接字符串

C#为开发用户提供了两种方法实现字符串的连接,第一种使用“+”号连接字符串,这种方法使用起来非常简单,但在连接过程中会将新的组合字符串分配新的空间,在一个较大的循环中会占用过多的资源,因此“+”号一般适用于低数量级字符串连接;另一种使用StringBuild类的Append()方法来连接字符串,此方法对字符串的处理效率要比“+”号高很多,如果对大量字符串进行连接,建议使用Append()方法。下面详细介绍这两种方法。

1.“+”号连接字符串

“+”号用来连接两个字符串,使用格式如str1+str2。

【实例4-7】本例将创建一个控制台应用程序,控制台输出两个字符串的连接,在控制台项目Program.cs文件的main函数中输入下面代码。

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq
    04   using System.Text;
    05
    06   namespace StrAdd
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12             string str, str1, str2;         //声明三个字符串str,str1,str2变量
    13             str1 = "Hello";
    14             str2 = "World";
    15             str = str1 + str2;              //字符串连接
    16             Console.WriteLine(str);
    17             System.Console.ReadLine();      //读取“Enter”键之后,关闭控制台应用程序
    18          }
    19      }
    20   }

【代码解析】第15行将两个字符串连接在一起。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的【启动调试】按钮,显示结果如图4-7所示。

图4-7 运行结果

2.Append()方法连接字符串

Append()方法属于StringBuild类,该方法的功能是使用实例对象本身与指定的字符串连接,语法格式如下:

    Public StringBuild CompareTo (char[ ] str)

❑ 参数说明:str代表要连接的字符串。

❑ 返回值:该方法返回一个StringBuild对象。

【实例4-8】本例将创建一个控制台应用程序,控制台输出两个字符串的连接,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq
    04   using System.Text;
    05
    06   namespace StrAdd
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string  str1, str2;                       //声明两个字符串str1、str2变量
    14             StringBuilder sb=new StringBuilder();     //实例化StringBuilder类对象sb
    15             str1 = "Hello";
    16             str2 = "World";
    17             sb.Append(str1);                          //字符串连接
    18             sb.Append(str2);                          //字符串连接
    19             Console.WriteLine(sb.ToString());
    20             System.Console.ReadLine();                //读取“Enter”键之后,关闭控制台应用程序
    21          }
    22      }
    23   }

【代码解析】第14行实例化StringBuilder类对象sb。第17~18行将两个字符串使用StringBuilder的对象连接在一起。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-8所示。

图4-8 运行结果

4.1.4 复制字符串

在程序开发中可能经常需要对字符串进行复制操作,C#提供了Copy()和CopyTo()方法来实现对字符串的复制,这两个方法都属于String类。下面详细介绍这两种方法。

1.CopyTo()方法

CopyTo()方法将指定段中的字符复制到目标字符数组的指定段中。复制StringBuilder类的实例的内容可以使用CopyTo()方法,语法格式如下:

    public void CopyTo(int sourceIndex,char[ ] destination,int destinationIndex,int count)

参数说明:

❑ sourceIndex指定开始复制字符的位置。

❑ destination指定要将字符复制到的字符数组。

❑ destinationIndex指定要将字符复制到的destination参数中的起始位置。

❑ count指定要复制的字符数。

【实例4-9】本例将创建一个控制台应用程序,在控制台项目程序中,把str1字符串“Hello World”中的“World”复制到str2中,并在str2中从第2个元素开始存放,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq
    04   using System.Text;
    05
    06   namespace StrCopy
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12            string str1 = "Hello World";
    13            char[] str2 = new char[20];           //定义字符数组
    14            str1.CopyTo(6,str2, 1, 5);            //从第7个字符开始,复制5个字符
    15            Console.WriteLine(str2);              //输出字符串
    16            System.Console.ReadLine();            //读取“Enter”键之后,关闭控制台应用程序
    17          }
    18      }
    19   }

【代码解析】第14行从第7个字符开始,复制5个字符。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-9所示。

图4-9 运行结果

2.Copy()方法

Copy()方法创建一个与指定的String具有相同值的String的新实例,此方法是一个静态方法,其语法格式如下:

    public static string Copy(string str)

❑ 参数说明:str为要复制的String。

❑ 返回值:与str具有相同值的新String。

【实例4-10】本例将创建一个控制台应用程序,在控制台项目程序中,把str1字符串“Hello World”,复制到str2中,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq
    04   using System.Text;
    05
    06   namespace StrCopy
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12            string str1 ,str2;
    13            str1 = "Hello World";
    14            str2=String.Copy(str1);          //将字符串str1复制到str2中
    15            Console.WriteLine(str2);         //输出字符串
    16            System.Console.ReadLine();       //读取“Enter”键之后,关闭控制台应用程序
    17          }
    18      }
    19   }

【代码解析】第14行将字符串str1复制到str2中。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-10所示。

图4-10 运行结果

4.1.5 截取字符串

C#提供了Substring()方法来截取字符串,该方法属于String类。通过Substring()可以截取字符串中指定位置和指定长度的字符。其语法格式如下:

    Public string Substring(int startIndex,int length)

❑ 参数说明:startIndex指定要截取子字符串起始位置的索引;length指定要截取的长度。

❑ 返回值:返回一个String,它等于此实例中从startIndex开始的长度为length的子字符串,如果startIndex等于此实例的长度且length为零,则为空。

【实例4-11】本例将创建一个控制台应用程序,声明两个string类型的变量str1和str2,并将str1赋值为“C#截取字符串实例”,然后使用Substring方法从str1字符串的索引2处开始截取5个字符,然后输出,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace Strsub
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12             string str1, str2;              //声明两个字符串变量str1、str2
    13             str1 = "C#截取字符串实例";      //赋值
    14             str2=str1.Substring(2,5);       //截取字符串
    15             Console.WriteLine(str2);        //输出截取结果
    16             System.Console.ReadLine();      //读取“Enter”键之后,关闭控制台应用程序
    17          }
    18      }
    19   }

【代码解析】第14行截取字符串。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-11所示。

图4-11 运行结果

4.1.6 替换字符串

C#为开发人员提供了Replace()方法来实现字符串的替换,Replace()方法可以替换掉一个字符串中的某些特定字符或者子串。其语法格式如下:

    Public string Replace(char OldChar,char NewChar)
    Public string Replace(string OldValue,string NewValue,)

参数说明如表4-3所示。

表4-3 Replace方法参数表

第一种格式主要用于替换字符串中的单个字符,第二种格式主要替换字符串中的子串。当然子串也可以是单个字符,即也可以用第二种格式实现单个字符的替换。下面用实例来说明。

【实例4-12】本例将创建一个控制台应用程序,声明一个string类型变量str1,并赋值为“Hello Boys”;然后使用Replace方法的第一种语法格式将字符串str1中的“o”替换成“#”,使用第二种语法格式将字符串str1中的“Boys”替换成“Girls”,使用第二种语法格式将字符串str1中的“o”替换为“test”;最后分别输出替换后的字符串,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace SrtReplace
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12
    13             string str1, str2,str3,str4;              //声明4个字符串变量
                              str1、str2、str3、str4
    14             str1 = "Hello Boys";                      //赋值
    15             str2=str1.Replace('o','#');               //替换单个字符
    16             str3 = str1.Replace("Boys", "Girls");     //替换字符串
    17             str4 = str1.Replace("o", "test");         //替换字符串
    18             Console.WriteLine(str2);                  //输出替换结果
    19             Console.WriteLine(str3);                  //输出替换结果
    20             Console.WriteLine(str4);                  //输出替换结果
    21             System.Console.ReadLine();                //读取“Enter”键之后,关闭控制台应用程序
    22          }
    23      }
    24   }

【代码解析】第15行替换单个字符,第16行替换字符串。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-12所示。

图4-12 替换字符串输出结果

4.1.7 分割字符串

在程序设计过程中经常需要分割字符串,如获取字符串“河南,山东,广东,四川,江苏”中的单个省份,这就需要对字符串进行分割。C#提供了String类的Split方法来实现,该方法用于分割字符串,其返回值是包含所有分割子字符串的数组对象,可以通过数组取得所有分割的子字符串。Split方法语法格式如下:

    Public string [ ] Split(char[ ]separator);

❑ 参数说明:separator为一个字符数组,用于包含分隔符。

❑ 返回值:返回一个数组,数组中存放分割后的单个子字符串,这些子字符串由separator中的一个或多个字符分割。

下面用实例来说明。

【实例4-13】本例将创建一个控制台应用程序,声明一个string类型变量str1,赋值为“河南,山东,广东,四川,江苏”,分割变量str1,并输出分割后的字符串,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05
    06   namespace ChrSplit
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12             string str1;                              //声明字符串变量str1
    13             string[ ] str2=new string[20];            //声明长度为20的字符数组变量
    14             str1 = "河南,山东,广东,四川,江苏";    //赋值
    15             char[ ] sp = { ',', '.' };                //分割字符
    16             str2=str1.Split(sp);                      //分割字符串
    17             for (int i = 0; i < str2.Length; i++)
    18             {
    19                 Console.WriteLine(str2[i]);           //输出分割结果
    20             }
    21          System.Console.ReadLine();                   //读取“Enter”键之后,关闭控制台应用程序
    22          }
    23      }
    24   }

【代码解析】第15~16行分割字符串。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-13所示。

图4-13 Split分割字符输出结果

4.2 正则表达式

本节将介绍正则表达式的概念、正则表达式的作用及表达式的操作,然后利用一些例子来解释正则表达式的用法。

正则表达式是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串,一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。它主要用来对字符串进行检验和操作,正则表达式功能非常强大。正则表达式常见运用是验证用户所输入信息格式是否正确,例如验证邮件地址是否合法可以用此正则表达式“[\w\.-]+(\+[\w-]*)?@([\w-]+\.)+[\w-]+”。当然正则表达式不仅仅是用于验证,可以说只要运用字符串的地方都可以使用正则表达式。

C#中正则表达式拥有一套语法规则,常见语法包括字符匹配、重复匹配、字符定位、转义匹配和其他高级语法(字符分组、字符替换和字符决策)。接下来详细介绍C#表达式语法规则。

1.字符匹配语法(见表4-4)

表4-4 字符匹配语法表

2.重复匹配语法(见表4-5)

表4-5 重复匹配语法表

3.字符定位语法(见表4-6)

表4-6 字符定位语法表

4.转义匹配语法(见表4-7)

表4-7 转义匹配语法表

要想真正用好正则表达式,正确地理解各语法规则非常重要。下面的一节中将向读者介绍正则表达的用法操作。

4.2.1 基本的正则表达式操作

通过上面正则表达式概念和语法规则的介绍,读者已经了解正则表达式的语法基础,接下来介绍如何构建正则表达式。C#中使用正则表达式需要引用命名空间“System.Text.Regular Expressions”,该命名空间包括了8个基本的类:Capture、CaptureCollection、Group、GroupCollection、Match、MatchCollection、Regex和RegexCompilationInfo。各类的说明如表4-8所示。

表4-8 正则表达式类说明

构建正则表达式经常需要用到Regex类,Regex类中包括一些常用方法:IsMatch()、Replace()、Split()、Replace()、Split()和操作字符串中4.1.6、4.1.7节所介绍的功能基本相同,这里详细介绍IsMatch()方法。

IsMatch()方法用来判断字符串是否满足正则表达式要求,如果满足返回True,相反则返回False,语法格式如下:

    Public bool IsMatch(String input,String pattern)

❑ 参数说明:input为输入字符串,即需要比较的字符串;pattern为正则表达式。

❑ 返回值:输入字符串满足正则表达式要求返回True,否则返回False。

【实例4-14】本例将创建一个控制台应用程序,使用正则表达式判断电话号码是否为北京地区的电话号码。首先北京地区电话区号为“010”,后面电话号码位数为8,例如“01088888888”。使用正则表达式的语法规则可进行限定,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05   using System.Text.RegularExpressions;
    06
    07   namespace RegExpMatch
    08   {
    09      class Program
    10      {
    11          static void Main(string[] args)
    12          {
    13             string str1,str2,strreg;                  //声明字符串变量str1,str2,strreg
    14             strreg = "010\\d{8,8}";                   //正则表达式
    15             str1 = "01012345678";                     //赋值电话号码
    16             str2 = "02012345678";                     //赋值电话号码
    17             Console.WriteLine("是否北京电话号码
    18             "+Regex.IsMatch(str1,strreg).ToString()); //输出判断结果
    19             Console.WriteLine("是否北京电话号码"+Regex.IsMatch(str2,strreg).ToString());
    20              输出判断结果
    21            System.Console.ReadLine();                 //读取“Enter”键之后,关闭控制台应用程序
    22          }
    23      }
    24   }

【代码解析】第14行初始化正则表达式,第17行判断输出结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-14所示。

图4-14 IsMatch方法输出结果

接下来就用Regex类对象来构建正则表大达式,Regex对象的构造函数包括两个重载,一个是不含参数的构造函数,另外一个是含有参数的构造函数,格式如下:

    基本形式Regex(string pattern);
    重载形式Regex(string pattern,RegexOptions);

参数说明:

❑ pattern是指正则表达式。

❑ RegexOptions属于枚举类型,包括IgnoreCase(忽略大小写)、ReghtToLeft(从右向左)、None(默认)、CultureInvariant(忽略区域)、Multline(多行模式)和SingleLine(单行模式)。

【实例4-15】本例将创建一个控制台应用程序,构建一个正则表达式判断输入的电子邮箱地址是否合法。首先读者可以分析一下电子邮箱的格式,例如“123xyz@163.com”,可以看出“@”之前是任意单字字符,可以用“\w”加以匹配,“@”和“.”之间也是任意单字字符,整个正则表达式可以写成“\\w{1,}@\\w{1,}\\.”,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05   using System.Text.RegularExpressions;
    06
    07   namespace StrRegex
    08   {
    09      class Program
    10      {
    11          static void Main(string[] args)
    12          {
    13             string str1,strreg;                                 //声明字符串变量str1、strreg
    14             strreg = "\\w{1,}@\\w{1,}\\.";                      //正则表达式
    15             Regex Emain_reg = new Regex(strreg);               //实例化Regex类对象
    16             do                                                   //循环输入,直到输入合法邮箱地址
    17             {
    18                 Console.WriteLine("请输入电子邮箱地址");
    19                 str1 = Console.ReadLine();
    20                 if (Emain_reg.IsMatch(str1) == true)
    21                 {
    22                    Console.WriteLine("恭喜,你输入的邮箱地址合法");//输出判断结果
    23                    break;                                        //输入合法地址则结束循环
    24                 }
    25                 else
    26                    Console.WriteLine("对不起,你输入的,邮箱地址有误");//输出判断结果
    27             }
    28             while (true);                                       //无条件循环
    29             System.Console.ReadLine();                //读取“Enter”键之后,关闭控制台应用程序
    30          }
    31      }
    32   }

【代码解析】第14行初始化正则表达式,第15行实例化Regex类对象,第20行判断输入的邮箱是否合法。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-15所示。

图4-15 电子邮箱验证输出结果

4.2.2 深入了解正则表达式

通过4.2.1节介绍读者了解了正则表达式的构建,可以按照正则表达式语法规则写出简单的正则表达式,这一节将更加深入地介绍正则表达式的使用。

1.二选一匹配

C#正则表达式中的“(|)”符号可以实现对字符的其中之一进行匹配,像[a-z]也是一种匹配,只不过它只能匹配单个字符,而“(|)”则提供了更大的范围。例如(ab|xy)表示匹配ab或匹配xy。注意“|”与“()”在此是一个整体。下面提供一些简单的实例。

【实例4-16】本例将创建一个控制台应用程序,正则表达式二选一匹配实例如下,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System.Linq;
    02   using System.Text;
    03   using System.Text.RegularExpressions;
    04   namespace Ch4Demo2
    05   {
    06      class Program
    07      {
    08          static void Main(string[] args)
    09          {
    10            string str1,str2,str3,strreg;         //声明字符串变量str1、
                        str2、str3、strreg
    11             strreg = "hello (boy|girl)s";        //正则表达式
    12             str1 = "hello boys";                 //赋值
    13             str2 ="hello girls";                 //赋值
    14             str3 = "hello boy and girls";        //赋值
    15           Console.WriteLine(Regex.IsMatch(str1,strreg).ToString());      //输出判断结果
    16           Console.WriteLine(Regex.IsMatch(str2,strreg).ToString());      //输出判断结果
    17           Console.WriteLine(Regex.IsMatch(str3,strreg).ToString());      //输出判断结果
    18           System.Console.ReadLine();             //读取“Enter”键之后,关闭控制台应用程序
    19          }
    20      }
    21   }

【代码解析】第11行初始化正则表达式,第15行输出判断结果。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-16所示。

图4-16 二选一匹配输出结果

2.贪婪与非贪婪

C#中正则表达式的引擎是贪婪的,只要模式允许,它将匹配尽可能多的字符。例如,“.”匹配任意字符,“*”匹配0个或多个字符,“+”匹配一个或多个字符。通过在“重复描述字符”(*、+)后面添加“?”,可以将匹配模式改成非贪婪。

【实例4-17】本例将创建一个控制台应用程序,使用正则表达式匹配以“s”结束的字符串,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05   using System.Text.RegularExpressions;
    06   namespace Regtl
    07   {
    08      class Program
    09      {
    10          static void Main(string[] args)
    11          {
    12             string str1;                              //声明字符串变量str1
    13             str1 = "hello boys and girls";            //赋值
    14             Regex strreg1 = new Regex(@".*s");        //实例化Regex类对象
    15             if(strreg1.IsMatch(str1))
    16              {
    17                  Console.WriteLine("匹配结果:" +
                      strreg1.Match(str1).Value); }
    18                  Regex strreg2 = new Regex(@".*?s");  //实例化Regex类对象
    19                  if(strreg2.IsMatch(str1))
    20                  {
    21                  Console.WriteLine("匹配结果:" +
                      strreg2.Match(str1).Value);
    22                  }
    23                 System.Console.ReadLine();             //读取“Enter”键之后,关闭控制台应用程序
    24              }
    25          }
    26      }
    27   }

【代码解析】第14行实例化Regex类对象,第19~22行进行匹配判断。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-17所示。

图4-17 贪婪与非贪婪输出结果

Tips

“Regex strreg1 = new Regex(@".*s")”语句实例化一个Regex类对象,正则表达式为“.*s”,表示以s结束的任意字符串,@非正则表达式成员,它的作用与转义字符“\”、的作用相同,如下面两条语句等价。

    string x="D:\\test\\test.cs";
    string y = @"D:\test\\test.cs";

Match()方法查找第一次满足正则表达式的字符串,由于贪婪匹配,所以Match()方会匹配整个字符串,也就是图中的第一次输出结果,当使用非贪婪匹配“.*?s”时,Match()方法查到“hello boys”满足正则表达式条件而结束。

“?”能强制量词尽可能少地匹配字符,常用的非贪婪字符有:“*?”、“+?”、“??”、“{n}?”、“{m,n}?”等。

3.捕获和反向引用

正则表达式引擎会记忆“()”中匹配到的内容,作为一个“组”叫做捕获组,并且可以通过索引的方式进行引用。捕获组(capturegroup)就像是正则表达式中的变量。捕获组可以捕获正则表达式中的字符模式,并且由正则表达式后面的编号或名称来引用。

说明:

❑ ():用来捕获其中的字符串

❑ \数字:用编号来引用

【实例4-18】本例将创建一个控制台应用程序,运行正则表达式匹配字符串“A<i>quantifier</i>canbe<big>greedy</big>”中的“<></>”内容。分析可知<i>与</i>可以捕获组加以引用,在控制台项目Program.cs文件的main函数中输入下面代码:

    01   using System;
    02   using System.Collections.Generic;
    03   using System.Linq;
    04   using System.Text;
    05   using System.Text.RegularExpressions;
    06
    07   namespace Ch4Demo2
    08   {
    09      class Program
    10      {
    11          static void Main(string[] args)
    12          {
    13             string str1;                                             //声明字符串变量str1
    14             str1 = "A<i>quantifier</i>canbe<big>greedy</big>";      //赋值
    15             Regex strreg1 = new Regex(@"<(\w+)>.*</\1>");           //实例化Regex类对象
    16             if (strreg1.IsMatch(str1))
    17             {
    18                 Console.WriteLine("匹配数:"+strreg1.Matches(str1).Count.ToString());
    19                 Console.WriteLine("匹配结果1:" + strreg1.Match(str1).Value);
    20                 Console.WriteLine("匹配结果2:" + strreg1.Match(str1). NextMatch().Value);
    21                 //输出结果
    22             }
    23            Regex strreg2 = new Regex(@".*?s");                      //实例化Regex类对象
    24             System.Console.ReadLine();                //读取“Enter”键之后,关闭控制台应用程序
    25          }
    26      }
    27   }

【代码解析】第15行实例化Regex类对象,第16~22行进行匹配判断。

【运行效果】代码编写完成之后,按“F5”键或者单击工具栏中的“启动调试”按钮,显示结果如图4-18所示。

图4-18 捕获和反向引用

Tips

“Regex strreg1 = new Regex(@”<(\w+)>.*</\1>“)”语句实例化一个Regex类对象,正则表达式 “<(\w+)>.*</\1>”可分为三部分。第一部分“<(\w+)>”匹配以字符“<”开始,以“>”结束,中间“(\w+)”代表任意字符;第二部分“.*”代表任意字符;第三部分“</\1>”,“\1”是在对第一部分中“(\w+)”的组引用。Matches()方法中的Count属性返回的是满足匹配的个数。利用Match()的NextMatch()方法可以输出下一个满足条件的匹配。

4.3 C# 4.0中的新特性:智能提示的改进

在Visual Studio 2008中,为一个对象选择属性时,它将根据输入的字母的顺序排列,为开发人员提供智能提示。而在Visual Studio 2010中它将向开发人员显示基于组的属性,例如,如果在文本框对象后键入text,它将向用户显示Text,TextChanged,TextMode。它也支持Pascal的智能提示,例如,用户输入TC,它将导航TextChanged成员。

为帮助示范这个Visual Studio 2010中的智能提示的改进,先来在Visual Studio 2008中做一个简单的例子,在Forms窗口中添加一个textBox控件,在后台代码设置其text属性,当键入tex时系统提示如图4-19所示。可以看出提示所有属性或方法都是以te开始的,如果开发人员使用的是text属性这个提示当然很好,但开发人员想使用AppendText()方法,这个提示就不行了。

图4-19 Visual Studio 2008的智能提示

Visual Studio 2010中做了修改,当在Visual Studio 2010中键入“tex”时,会发现Appendtext也显示在其中,如图4-20所示。这允许很快地看到与text相关的所有方法/属性/事件,更快地找到开发人需要的东西。

图4-20 Visual Studio 2010中的代码智能提示

1.搜寻关键词

Visual Studio 2010的这个新的智能提示过滤特性在搜寻任何成员时都会非常有用,无论成员的起始字母是什么。例如,如果想要设置textBox1的PrefeereHeight属性,但记不起来该怎么做,只要键入“textBox1.PrefeereHeight”,它就会自动地过滤掉其他的成员,而只留下含“paging”一词的成员,如图4-21所示。

图4-21 搜寻关键词

2.搜寻类型

Visual Studio 2010的这个新的智能提示过滤功能在快速寻找类和类型时也非常有用。例如,当键入“List”来声明一个变量时,编辑器会提供自动的过滤,显示名称中含有“List”一词的所有类型(包括IList<>和SortedList<>,它们的起始字母并不是“List”),如图4-22所示。这将极大地方便开发人员找到记不全的类型名称。

图4-22 搜寻类型

4.4 小结

本章介绍了C#中操作字符串和正则表达式的方法。首先介绍了C#字符串操作;然后结合实例讲解了字符串的格式化、字符串的比较、字符串的连接、字符串的复制截取等操作;另外还介绍了正则表达式的基本语法规则,通过实例向读者展示了正则表达式的用法;最后介绍了C# 4.0的新特性“智能提示的改进”。

4.5 练习

一、填空题

1.Visual C#提供了(  )和StringBuilder两种类来对字符串进行处理。

2.格式化字符串可以用ToString()方法和( )方法来实现。

3.Compare方法比较两字符串,如果两字符串相等,则返回的结果值为(  )。

4.Equals方法比较两字符串,如果两字符串相等,则返回的结果值为(  )。

5.Append()方法属于(  )类。

6.截取字符串Substring()方法属于(  )类。

7.分割字符串可以用String类的(  )方法来实现。

8.C#中使用正则表达式需要引用命名空间System.Text.(  )。

9.正则表达式字符“*” 表示匹配(  )个或多个字符。

10.使用正则表达式字符(  )可以将匹配模式改成非贪婪。

二、简答题

1.简述String和StringBuilder类的异同。

2.什么是正则表达式?。

三、上机题

1.使用C#创建一个控制台应用程序,获取当前日期,格式输出当前月日。

2.给定姓名字符串“张三,李四|王五、赵六”,要求编程取出字符串中的姓名,并输出显示。

3.写一个正则表达式,匹配字符串“<html> test </html>”。