C#字符串

来源:互联网 发布:内锥螺纹编程实例 编辑:程序博客网 时间:2024/05/08 22:06
无论使用何种类型的数据,也无论创建何种类型的应用程序,几乎毫无疑问地都要用到字符串。不管程序中的数据采用什么方式存储,对终端用户来说,他们只能理解人可读的文本数据。正因为如此,了解如何处理字符串,是每一位需要创建丰富和令人信服的应用程序的开发者都要掌握的基础知识。
除了介绍如何处理.NET框架中的字符串以外,这一章还将介绍正则表达式。正则表达式是格式化的代码段,它可用来验证一个字符串是否与给定的格式相匹配,并且可用于从表面上看来是自由文本的符号串中,抽取有意义的信息,例如从用户的输入字符串中抽取姓名,从输入的电话号码中抽取地区代码,或者从一个给定的URL字符串中抽取主机名等。
3.1 字符串
正确处理字符串是编写高质量应用程序所需要的基本技能。即使要处理的是数字信号或图像数据,终端用户也需要文本形式的信息反馈。本节将介绍.NET框架中的字符串,包括如何格式化字符串,如何操纵字符串,如何比较字符串,以及其他有用的字符串操作。
3.1.1 .NET框架中的字符串
在.NET框架和公共语言运行时(CLR)出现之前,开发者要在字符串的处理上耗费相当多的编程工作量。事实上,一个可重用的字符串例程库,是每一位C/C++程序员必备的编程工具箱。在不同的编程语言之间编写交换字符串数据的代码是困难的。例如,在Pascal语言中,字符串是一个存储于内存中的数组,数组的第一个元素指明了字符串的长度。而在C语言中,字符串是一个存储于内存中的可变长的数组,该数组的结束以ASCII字符null表示(在C语言中可用‘/0’表示)。
在.NET框架中,从存储结构上讲,字符串是不可变的值。这意味着当你用C#语言(或.NET 支持的任何其他语言)创建了一个字符串之后,字符串被存储于一个定长的结构中,以使CLR 的某些部分有更快的运行速度(本书的第16章将介绍与此有关的内容)。因此,当执行诸如字符串的比较操作,或者修改字符串中的某个字符时,CLR实际上为这个字符串创建了多个拷贝。
在C#中,字符串的声明与整数类型、浮点数类型的声明语法相同,如下面的代码段所示:
string x = "Hello World";
string y;
string z = x;
3.1.2 格式化字符串
在处理字符串时,一个常见的任务是对字符串格式化。当显示信息给用户时,经常需要显示诸如日期、时间、数字值、小数、货币值,甚至十六进制数值。C#中的字符串都具有显示这些信息类型及更多信息类型的能力。C#中的字符串的另一个强大特征是,如果使用标准的格式化工具,所输出的结果将具有本地意识。例如,如果程序为一个英国用户显示当前日期的一个缩写,那么对于一个美国用户,它显示的是符合美国用户习惯的另一个不同的日期缩写。
要创建一个格式化的字符串,所要做的是调用string类的format方法,并给该方法传递一个格式字符串作为参数,如下面一行代码所示:
string formatted = string.Format("The value is {0}", value);
占位符{0}指出value的输出值应该插入的位置。除了描述输出值的插入位置外,还可以指定输出值的输出格式。
通过使用定制的格式描述符,还可以将其他类型的数据转换为字符串。例如,下列语句用于将DataTime数据类型转换为一个定制的字符串:
DateTime.ToString("format specifiers");
表3.1列出了用于日期、时间、数字值和其他常用数据类型的格式描述符。
表3.1 DataTime类型定制的格式描述符
描述符
含义
d
显示一个月内的当前一天
dd
显示一个月内的当前一天,如果天的数值小于10,则前面补0
ddd
显示星期几的三字符缩写
dddd (+)
根据给定的Datatime值,显示星期几的全名
f (+)
显示秒数的最有效位,格式描述符中的f越多,有效位数就越多,这里的秒数
指的是累计时间的秒数,不是从最近的一分种开始计算的秒数
F (+)
与f (+)相同,不同之处是不显示结尾的0
g
显示给定DataTime值的纪元(例如“A.D.”)
h
显示小时数,显示范围为1~12
hh
显示小时数,显示范围为1~12,如果小时数小于10,前面补0
H
显示小时数,显示范围为0~23
HH
显示小时数,显示范围为0~23,如果小时数小于10,前面补0
m
显示分数,显示范围为0~59
mm
显示分数,显示范围为0~59,如果分数小于10,前面补0
M
显示月份数,显示范围为1~12
MM
显示月份数,显示范围为1~12,如果月份数小于10,前面补0
MMM
显示月份的三字符英文缩写
MMMM
显示月份的全英文名
s
显示秒数,显示范围为0~59
ss (+)
显示秒数,显示范围为0~59,如果秒数小于10,前面补0
t
对一个给定的时间,显示AM/PM的首字符
tt (+)
对一个给定的时间,显示AM/PM的全名
y/yy/yyy
对一个给定的时间,显示它的年份
z/zz/zzz (+)
对一个给定的时间,显示时区
看看下面的几行代码,这段代码演示了如何使用字符串的格式描述符来创建定制格式的日期和时间字符串:
DateTime dt = DateTime.Now;
Console.WriteLine(string.Format("Default format: {0}", dt.ToString()));
Console.WriteLine(dt.ToString("dddd dd MMMM, yyyy g"));
Console.WriteLine(string.Format("Custom Format 1: {0:MM/dd/yy hh:mm:sstt}", dt));
Console.WriteLine(string.Format("Custom Format 2: {0:hh:mm:sstt G//MT zz}", dt));
上面的代码段执行后,将产生如下的输出结果:
Default format: 9/24/2005 12:59:49 PM
Saturday 24 September, 2005 A.D.
Custom Format 1: 09/24/05 12:59:49PM
Custom Format 2: 12:59:49PM GMT -06
对于数字值,也可以应用定制的格式描述符。表3.2列出了可用于数字值的定制的格式描述符。
表3.2 定制的数字值格式描述符

描述符    含义
0 零占位符

#
数字占位符,如果给定的值中有某一位处在由#指出的位置,那么该位将
显示在格式化输出中
.
十进制点
,
千位分隔符
%
百分率描述符,被格式化的值在输出之前乘以100
E0/E+0/e/e+0/e0/E
科学计数法
'XX' 或"XX"
字面值,它们直接包含在格式化输出中,不经过相对位置的变换
;
负数、零和正数之间的条件分隔符
如果在格式字符串中定义了多个格式段,则可实现对数字值的输出格式的更细粒度的条件逻辑控制:
          ? 两个格式段—如果有两个格式段,那么第一段应用于所有的正数值(含0);第二段应用于负数值,当需要用圆括号将负数值括起来时,这是极为有用的,许多账目管理软件包有这样的要求。
          ? 三个格式段—如果有三个格式段,那么第一段应用于所有的正数值(不含0);第二段
应用于负数值;第三段应用于0。下面的几行代码举例说明了如何使用定制的数字格式描述符:
double dVal = 59.99;
double dNeg = -569.99;
double zeroVal = 0.0;
double pct = 0.23;
string formatString = "{0:$#,###0.00;($#,###0.00);nuttin}";
Console.WriteLine(string.Format(formatString, dVal));
Console.WriteLine(string.Format(formatString, dNeg));
Console.WriteLine(string.Format(formatString, zeroVal));
Console.WriteLine(pct.ToString("00%"));
以上代码产生下列输出结果:
$59.99
($569.99)
nuttin
23%
3.1.3 操纵和比较字符串
除了将各种类型的数据用不同的格式输出外,另一个与字符串有关的常见编程任务,是对字符串进行操纵和比较。字符串类型在底层的.NET框架的基础类库中实质上是一个类,记住这一点很重要。因为字符串类型是一个类,因此在程序中就可以调用它的方法,就像调用任何其他类的方法一样。
在调用字符串的方法时,既可以对字符串的字面值调用它的方法,也可以对字符串变量调用它的方法,如下面的代码所示:
int x = string.Length();
int y = "Hello World".Length();
表3.3简要描述了可用于获得字符串内部信息或对其进行操纵的常用方法。

表3.3 字符串实例对象的常用方法
方  法
说  明
CompareTo
比较两个字符串
Contains
返回一个布尔值,判断当前的字符串是否包含一个指定的子串
CopyTo
将一个字符串的子串拷贝至一个字符数组的指定位置
EndsWith
返回一个布尔值,判断当前字符串是否以一个指定的子串为结尾
Equals
判断一个字符串与另一个字符串是否相等,与‘= =’操作符的功能相同
IndexOf
返回在当前字符串中出现的一个指定子串的下标
IndexOfAny
返回在当前字符串的一个指定子串中,任何一个字符首次出现的位置下标
PadLeft
在当前字符串的头部填补空白符或其他Unicode字符,使字符串右对齐
PadRight
在当前字符串的末尾填补空白符或其他Unicode字符,使字符串左对齐
Remove
从当前字符串中删除指定数量的字符
Replace
将当前字符串中出现的指定字符或字符串替换为另一个指定的字符或字符串
Split
将当前的字符串拆分为一个字符串的数组,以指定的字符为拆分点
StartsWith
返回一个布尔值,表明该字符串是否以一个指定的子串开始
SubString
以开始点的位置和长度为参数,返回一个字符串的指定子串
ToCharArray
将字符串转换为一个字符数组
ToLower
将字符串中的所有字符转换为小写
ToUpper
将字符串中的所有字符转换为大写
Trim
删除从字符串首部到尾部中出现的一个给定的符号集合
TrimStart
执行Trim操作,但是只删除首部出现的一个给定的符号集合
TrimEnd
执行Trim操作,但是只删除尾部出现的一个给定的符号集合
看看下面的一段代码示例,这段程序展示了如何查询字符串的信息和操纵字符串:
string sourceString = "Mary Had a Little Lamb";
string sourceString2 = " Mary Had a Little Lamb ";
Console.WriteLine(sourceString.ToLower());
Console.WriteLine(string.Format("The string '{0}' is {1} chars long.",
sourceString,sourceString.Length));
Console.WriteLine(string.Format("Fourth word in sentence is : {0}",
sourceString.Split(' ')[3]));
Console.WriteLine(sourceString2.Trim());
Console.WriteLine("Two strings equal? " + (sourceString == sourceString2.Trim()));
上述代码产生如下的输出:
mary had a little lamb
The string 'Mary Had a Little Lamb' is 22 chars long.
Fourth word in sentence is : Little
Mary Had a Little Lamb
Two strings equal? True
3.1.4 StringBuilder类介绍
前面提到过,字符串在内存中是不可变的。这意味着,如果为了得到第三个字符串而连接两个字符串时,在一个短暂的时间内,CLR将会在内存中维护三个字符串的实例。比方说,假设你编写了如下的代码用于连接字符串:
string a = "Hello";
string b = "World";
string c = a + " " + c;
上面的代码在运行时实际存在四个字符串,包括它们占用的存储空间。为了缓解这种因字符串连接而带来的性能问题,同时为了给字符串连接操作给予编程工具支持,.NET框架提供了一个名为StringBuilder的类。
通过使用StringBuilder类来动态创建可变长字符串,可以避免因CLR中的字符串的不可变性而带来的问题,如此编写的代码通常会更容易阅读。让我们来看一看StringBuilder类在下面的代码中是如何发挥功能的:
StringBuilder sb = new StringBuilder();
sb.Append("Greetings!/n");
formatString = "{0:$#,###0.00;($#,###0.00);Zero}";
dVal = 129.99;
sb.AppendFormat(formatString, dVal);
sb.Append("/nThis is a big concatenated string.");
Console.WriteLine(sb.ToString());
上面的程序产生的输出结果为:
Greetings!
$129.99
This is a big concatenated string.
注意,在上面的程序示例中,/n的作用是在输出的字符串中插入一个换行符。 
原创粉丝点击