文字是信息的主要表达方式,因此文字处理是计算机的一项重要功能之一。现在来深入研究C#中字符串的各种特性、正则表达式的基本概念以及如何用正则表达式进行文本匹配。
1.char结构
C#中的字符用System命名空间中的Char结构实现,每个Char占用2字节空间,用于存储字符的Unicode编码。C#专门设计了char关键字用来声明字符变量,char关键字相当于Char的别名,这里主要介绍一下Char结构的方法。
private void analyzeButton_Click(object sender, EventArgs e)
{ char character = Convert.ToChar(inputTextBox.Text); //字符串转换为字符
string output="";
output += "为数字:" + Char.IsDigit(character) + "\r\n";
output += "为字母:" + Char.IsLetter(character) + "\r\n";
output += "为小写:" + Char.IsLower(character) + "\r\n";
output += "为大写:" + Char.IsUpper(character) + "\r\n";
output += "为标点:" + Char.IsPunctuation(character) + "\r\n";
output += "为符号:" + Char.IsSymbol(character) + "\r\n";
output += "转大写:" + Char.ToUpper(character) + "\r\n";
output += "转小写:" + Char.ToLower(character) + "\r\n";
outputTextBox.Text = output;
}
2.String类
字符串由System 命名空间中的String 类实现,由于字符串的应用非常广泛,C#专门设计了string 关键字,它相当于String 的别名。
(1)索引器和Length属性
.NET 为String 类设计了索引器,这相当于把String 看作Char 数组,所以我们可以像数组那样使用字符串,字符串sentence 相当于一个字符数组。例如:
string sentence = "Hello!";
Console.WriteLine("The letters in \"Hello\" are:");
for (int i = 0; i < sentence.Length; i++)
{
char letter = sentence[i];
Console.Write(letter + " ");
}
注意:如果索引越界,系统将会抛出IndexOutOfRangeException 异常。
(2)复制字符串
共有三种方法:
*赋值运算符***=**,赋值运算符进行的是引用传递,它不会复制整个字符串,而仅仅将原变量的引用传递给目标变量,从而使两个变量指向同一个字符串。例如:
string sentence1 = "How do you do!";
string sentence2 = sentence1;
**Copy()**方法,String 类的Copy()方法也可将一个string 变量的值赋给另一个string 变量,它与赋值运算符的区别是,Copy()方法会创建一份新的字符串,两个变量指向不同的字符串常量。
**CopyTo()**方法,用于把字符串的一部分复制到另一个字符数组,这段代码把字符串“someone”中的子串“me”复制到目标字符数组的第3 到4 位,并覆盖原有内容。
string source = "someone";
char[] destination = { '*', '*', '*', '*', '*', '*', '*', '*'};
int sourceIndex = 2;
int destinationIndex = 3;
int count = 2;
source.CopyTo(sourceIndex, destination, destinationIndex, count);
//输出目标字符数组
for (int i = 0; i < destination.Length; i++)
{ Console.Write(destination[i]); }
(3)比较字符串
有四种方法比较两个字符串是否相等:
*相等运算符***==**,用“==”运算符直接比较两个字符串是否相等,比较是 区分大小写的。
**Equals()**方法,与运算符“==”的功能相同,当两个字符串相等时返回true, 不相等时返回false。
*静态***Equals()**方法,String 类还重载了一个静态的Equals()方法,它的参数是两个string 对象,当两个参数相等时返回true,不相等时返回false。
**CompareTo()**方法,用来比较两个字符串的大小,比较规则是位于字母表前面的字符小于后面的字符,先比较两个字符串的第一个字符,如果相等,就去比较第二个字符,如此下去,直到比较出大小为止。如果better < best,方法返回﹣1,如果better = best,方法返回0,如果better > best,方法返回1,在按名称排序等处会经常用到。例如:
string string6 = "better";
string string7 = "best";
if (string6.CompareTo(string7) == -1)
{
Console.WriteLine(string6 + " < " + string7);
}
else if (string6.CompareTo(string7) == 0)
{
Console.WriteLine(string6 + " = " + string7);
}
else { Console.WriteLine(string6 + " > " + string7); }
(4)字符串首尾匹配
下面的两种方法用于验证字符串是否以特定的子串开头或结尾。
*String类的*StartsWith()**方法,用来判断字符串是否以特定的子串开头。
string [] strings ={ "started", "starting", "ended", "ending" };
//判断字符串是否以"st"开头
for (int i = 0; i < strings.Length; i++)
{ if(strings[i].StartsWith("st"))
{ Console.WriteLine("{0} starts with st", strings[i]); }
}
*String类的*EndsWith()**方法,用来判断字符串是否以特定的子串结尾。
string[] strings ={ "started", "starting", "ended", "ending" };
//判断字符串是否以"ed"结尾
for (int i = 0; i < strings.Length; i++)
{ if(strings[i].EndsWith("ed"))
{ Console.WriteLine("{0} ends with ed", strings[i]); }
}
(5)定位字符或字符串
有三种方法可以找到指定字符(或子串)在字符串中的位置。
String *类的***IndexOf()**方法,可以找到指定字符(或子串)在字符串中第一次出现的位置,如果找不到指定的字符(或子串),返回﹣1。
string sentence = "Each bird love to hear himself sing.";
int index1 = sentence.IndexOf('o');
int index2 = sentence.IndexOf("love");
Console.WriteLine("First o is located at index {0}", index1);
Console.WriteLine("First you is located at index {0}", index2);
结果是11、10。
还可以指定搜索的起始位置:
string sentence = "Each bird love to hear himself sing.";
int index1 = sentence.IndexOf('o', 3);
int index2 = sentence.IndexOf("love", 3);
Console.WriteLine("First o starting at 3 is located at index {0}", index1);
Console.WriteLine("First love starting at 3 is located at index {0}",index2);
结果是11、10。
不但可以指定搜索的起始位置,还可以指定从起始位置起向后搜索多少个字符。
string sentence = "Each bird love to hear himself sing.";
int index1 = sentence.IndexOf('o',3,10);
int index2 = sentence.IndexOf("love",3,10);
Console.WriteLine("First o in the 10 positions starting at 3 is
located at index {0}", index1);
Console.WriteLine("First love in the 10 positions starting at 3 is
located at index {0}", index2);
结果是11、-1。
String *类的***LastIndexOf()**方法,可以找到指定字符(或子串)在字符串中最后一次出现的位置,如果找不到则返回﹣1,LastIndexOf()方法从后向前搜索。
string sentence = "Each bird love to hear himself sing.";
int index1 = sentence.LastIndexOf('o');
int index2 = sentence.LastIndexOf("love");
Console.WriteLine("Last o is located at index {0}", index1);
Console.WriteLine("Last love is located at index {0}", index2);
同样,也可以指定搜索的起始位置以及从起始位置开始向前搜索多少个字符。
string sentence = "Each bird love to hear himself sing.";
//指定从起始位置开始向前搜索多少个字符
int index3 = sentence.LastIndexOf('o', 25, 10);
int index4 = sentence.LastIndexOf("love", 25, 10);
Console.WriteLine("Last o in the 8 positions starting at 15is
located at index {0}", index3);
Console.WriteLine("Last love in the 8 positions starting at 15 is
located at index {0}", index4);
结果是16、-1。
String *类的***IndexOfAny()**方法,可以同时搜索多个指定字符,搜索到其中任何一个即停止。
string s = "Each bird love to hear himself sing.";
char[] searchLetters ={ 'a', 'o' };
int index1 = s.IndexOfAny(searchLetters);
int index2 = s.IndexOfAny(searchLetters, 5);
int index3 = s.IndexOfAny(searchLetters, 15, 8);
Console.WriteLine("The frist letter is {0} at index {1}", s[index1], index1);
Console.WriteLine("The frist letter is {0} at index {1}", s[index2], index2);
Console.WriteLine("The frist letter is {0} at index {1}", s[index3], index3);
无论搜索到字母a 还是字母o,方法都会立即停止,返回该字母的索引。结果为1、11、16。
*类似的***LastIndexOfAny()**方法,从末尾开始,同时搜索多个指定字符,搜索到其中任何一个即停止。
(6)截取子串
String 类的Substring()方法可以从字符串中截取子串。
string sentence = "Each bird love to hear himself sing.";
string sub = sentence.Substring(10);
Console.WriteLine("Substring from index 10 to end is {0}", sub);
上面的程序截取字符串sentence中从位置10开始到尾部为止的子串。当然,还可以指定截取字符串的长度。
string sentence = "Each bird love to hear himself sing.";
string sub = sentence.Substring(10,5);
Console.WriteLine("Substring in the 4 positions starting at 10 is {0}", sub);
上面的程序截取了字符串sentence中从位置10开始的5个字符。
(7)拆分、组合字符串
通过*String类的*Split()**方法,可以把字符串拆分为若干个子串,比如以空格为分隔符可将句子拆分为单词。
string str = "Each bird love to hear himself sing.";
char [] separator = new char[]{' '}; //以空格为分隔符
string [] words = str.Split(separator);
foreach(string word in words)
{ Console.WriteLine(word);}
上面的程序中以空格为分隔符把字符串str分解为6个单词,保存在字符串数组words中。如果有多种分隔符,只需把它们放到字符数组或字符串数组中即可。
string str = "Each bird, love to, hear himself sing.";
char[] separator = new char[]{ ' ', ',' }; //以空格或逗号为分隔符
string[] words = str.Split(separator);
foreach (string word in words)
{ Console.WriteLine(word);}
上面运行的结果分别为:Each bird love to hear himself sing. 和 Each bird love to hear himself sing.。可以看出第二段程序结果出现了空的字符串,可以通过添加一个StringSplitOptions参数去掉空字串,StringSplitOptions 枚举包含两个枚举项,枚举项RemoveEmptyEntries 省略空数组,枚举项None 保留空数组。
string str = "Each bird, love to, hear himself sing.";
char[] separator = new char[] { ' ', ',' };
string[] words = str.Split(separator, StringSplitOptions.RemoveEmptyEntries);
foreach (string word in words)
{ Console.WriteLine(word);}
与 Split()相反,Join()方法能通过分隔符把若干个字符串连接起来。
string[] words = { "Each", "bird", "love", "to", "hear", "himself", "sing." };
string str = String.Join(" ", words);
Console.WriteLine(str);
(8)更改大小写
String 类的ToUpper()方法能将字符串中的小写字母转换为大写字母。String 类的ToLower()方法能将字符串中的大写字母转换为小写字母。例如:
string string1 = "ok,GOOD";
string string2 = string1.ToUpper();
string string3 = string1.ToLower();
(9)修改字符串
使用String类的Insert()、Replace()、Remove()等方法可以“修改”字符串,这些方法都会生成并返回一个新的字符串。
String string1= "tree";
string string2=string1.Insert(1, "h");
string string3="fine";
string string4=string3.Replace(‘e’, ‘d’);
string string5=string3.Replace(“in”, “ac”); //将fine的in替换为ac
string string6=“young”;
string string7=string6.Remove(3); //删除从位置3开始到末尾的所有字符
string string8=string6.Remove(1,2); //删除了从位置1开始的2个字符
(10)插入格式化变量
String类的Format()方法可以在字符串中插入变量,并可设置变量的格式:
int i=360,j=60;
string result=string.Format(“{0,6}\n+{1,3}\n-----\n{2,6}”,i,j,i+j);
Console.WriteLine(result);
3.StringBuilder类
String类使用起来非常方便,但它的对象是“不可修改的”,修改String类对象实际上创建了一个新的字符串。
string mySentence=”Welcome to”;
mySentence=mySentence+”Beijing!”;
Console.WriteLine(mySentence);
这里创建了一个新的string对象来存储字符串“Welcome to Biejing!”,并删除原来的旧字符串,如果要对字符串进行成百上千次修改,就要成百上千次创建新string对象,这种方法显然效率太低了。然而使用System.Text命名空间的StringBuilder类,可以对字符串本身直接修改,这是一个非常强大的字符串类,它的对象是可变字符串。可以三种方式声明三个StringBuilder型字符串变量,其初始容量有所不同:
StringBuilder sb1 = new StringBuilder(); //默认为16个字符
StringBuilder sb2 = new StringBuilder(10); //初始容量为10个字符
StringBuilder sb3 = new StringBuilder("Hello Kitty!"); //默认分配16个字符容量
除非显式指定,StringBuilder的初始容量总是16,如果字符串的长度大于16,则StringBuilder的初始容量为字符串的长度,显然StringBuilder 型字符串的长度(Length)和容量(Capacity)是两个不同概念。当初始容量不足时,该怎么办呢?我们可使用StringBuilder 类的EnsureCapacity()方法增加容量。。EnsureCapacity()方法的参数为多少,StringBuilder的容量就增加到多少。如果指定长度小于当前字符数,则将尾部多余的字符截去;如果指定长度大于当前字符数,则在字符串尾部添加空格。但要注意,Length 不能比Capacity 大。StringBuilder 类有如下五个方法可实现不同的字符操作功能。
(1)Append()方法
通过 StringBuilder 类的Append()方法可以向字符串尾部添加字符,StringBuilder 类提供了19 个重载Append()方法,可以添加多种类型的数据。
StringBuilder sb = new StringBuilder("Kitty is ");
int intValue = 3;
sb.Append(intValue);
string stringValue = " years old";
sb.Append(stringValue);
char charValue = ',';
sb.Append(charValue);
char[] charArray = new char[]{ ' ', 's', 'h', 'e', ' ', 'i', 's', ' ' };
sb.Append(charArray);
double doubleValue = 2.5;
sb.Append(doubleValue);
sb.Append("Kg. That is ");
bool boolValue = true;
sb.Append(boolValue);
sb.Append('!');
Console.WriteLine(sb);
当容量不足时,调用 Append()方法会使容量增加,Append()方法以“翻倍补余”的方式增加容量,即比较追加后字符串长度和当前容量的二倍,新容量为二者中较大者。
(2)AppendFormat()方法
通过 StringBuilder 类的AppendFormat()方法可以向字符串尾部添加指定格式的字符,例如:
StringBuilder sb = new StringBuilder();
decimal i = 19.23M;
decimal j = 73.7M;
sb.AppendFormat("{0,8:C2}\n+{1,7:C2}\n---------\n{2,8:C2}", i, j, i + j);
(3)Insert()方法
StringBuilder类提供了18个重载的Insert()方法,能在字符串的任何位置插入各种类型的数据。
StringBuilder sb = new StringBuilder("Kitty yesr old, she is Kg,That is !");
Console.WriteLine(“old sb={0}”,sb);
string stringValue=”is”;
sb.Insert(6,stringValue);
int intValue=3;
sb.Insert(9,intValue);
char charValue=’s’;
sb.Insert(15,charValue);
double doubleValue=2.5;
sb.Insert(28,doubleValue);
bool boolValue=true;
sb.Insert(42,boolValue);
Console.WriteLine(“new sb={0}”,sb);
结果新的字符串变为:Kitty is 3yesr sold, she is 2.5Kg,That is True!
(4) Replace()方法
通过StringBuilder类的Replace()方法可以将字符串的字符(或子中)替换为其他字符(或子串)。
StringBuilder sb=new StringBuilder(“Happy birthday Jack!”);
Console.WriteLine(“old sb={0}”,sb);
sb.Replace(“Jack”,”Kitty”);
Console.WriteLine(“new sb={0}”,sb);
(5)Remove()方法
通过StringBuilder类的Remove()方法可以删除字符串中指定位置上的字符。
StringBuilder sb = new StringBuilder(”Har vard is a famous university.”);
Console.WriteLine("old sb = {0}", sb);
sb.Remove(13, 7);
Console.WriteLine("new sb = {0}", sb);
上面的语句删除了从位置13 开始的7 个字符。