您的位置:首页 > 编程语言 > C#

C#字符串和正则表达式

2015-10-03 18:34 393 查看

0.string类

简单字符串操作用string类,对应IL中的System.String类,有很多足够常用的字符串操作,但是频繁操作效率非常低下,所以其它方式的字符串操作同样必不可缺。每次生成一个新的实例都要申请新的堆资源,和回收旧的资源。

1.StringBuilder

频繁更改:频繁创建字符串和多次创建较长的字符串,那么需要用System.TextStringBuilder类提高性能。可以指定最大Capacity,当前长度是Length,当没有指定最大长度时候,那么会翻倍递增内存。但是只提供了Replace,Append/AppendFormat,Remove的字符串操作。StringBuilder不能转换为String(隐式和显式都不行),唯一转换为String的方法是ToString函数。简单的字符串用string即可。
StringBuilder实例代码:

static void Main()
{
// StringBuilder实际用的长度是Length,当前容量是Capacity超过了会加倍,
// 只读属性MaxCapacity是最大容易超过了会报错。
// StringBuilder(150, 1000)150是Capacity后面的1000是MaxCapacity
StringBuilder greetingBuilder =
new StringBuilder("Hello from all the guys at Wrox Press. ", 150);
greetingBuilder.Append("We do hope you enjoy this book as much as we enjoyed writing it");

for(int i = (int)'z'; i>=(int)'a' ; i--)
{
char old1 = (char)i;
char new1 = (char)(i+1);
greetingBuilder = greetingBuilder.Replace(old1, new1);
}

for(int i = (int)'Z'; i>=(int)'A' ; i--)
{
char old1 = (char)i;
char new1 = (char)(i+1);
greetingBuilder = greetingBuilder.Replace(old1, new1);
}

Console.WriteLine("Encoded:\n" + greetingBuilder);
Console.ReadLine();
}

2.IFormattable接口的ToString函数

格式化:格式化字符串使用两个有效的接口,称为IFormatProvider和IFormattable来处理。

Console.WriteLine就是调用了String.Format方法来格式化的,String.Format构造格式化的字符串调用了StringBuilder构造函数和StringBuilder的AppendFormat方法,AppendFormat方法会首先检查对象实现了IFormattable接口就调用ToString(string format, IFormatProvider formatProvider),测试失败会调用对象Object.ToString()。

所以自定义类和结构,重写了Object.ToString就可以在Console.WriteLine中输出。所有的基元类型都实现了IFormattable接口。
如果要自定义的类和结构,不调用Object.ToString方法格式化,那么需要实现IFormattable接口的string ToString(string format, IFormatProvider formatProvider)方法。

例如:

class MainEntryPoint
{
static void Main()
{
Vector v1 = new Vector(1,32,5);
Vector v2 = new Vector(845.4, 54.3, -7.8);
// 传入:IJK,:VE,:N格式化说明字符
Console.WriteLine("\nIn IJK format,\nv1 is {0,30:IJK}\nv2 is {1,30:IJK}", v1, v2);
Console.WriteLine("\nIn default format,\nv1 is {0,30}\nv2 is {1,30}", v1, v2);
Console.WriteLine("\nIn VE format\nv1 is {0,30:VE}\nv2 is {1,30:VE}", v1, v2);
Console.WriteLine("\nNorms are:\nv1 is {0,20:N}\nv2 is {1,20:N}", v1, v2);

Console.ReadLine();
}
}

// 需要继承System.IFormattable接口
struct Vector : IFormattable
{
public double x, y, z;

public Vector(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
// 重写System.IFormattable的string ToString(string format, IFormatProvider formatProvider)函数
// IFormatProvider formatProvider类型系统默认根据当前文化背景提供,不需要处理。
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString();
string formatUpper = format.ToUpper();
switch (formatUpper)
{
case "N":
return "|| " + Norm() + " ||";
case "VE":
return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
case "IJK":
StringBuilder sb = new StringBuilder(x.ToString(), 30);
sb.Append(" i + ");
sb.Append(y.ToString());
sb.Append(" j + ");
sb.Append(z.ToString());
sb.Append(" k");
return sb.ToString();
default:
return ToString();
}
}

3.RegularExpressions

正则表达式:对于字符串复杂的查找,替换,提取某个类型的或者具体的字符串,那么可以用正则表达式来处理,在System.Text.RegularExpressions命名空间中。

正则表达式中的字符串查找替换提取删除操作,都可以使用String和StringBuilder来做到,但是有时候字符串操作比较复杂,需要大量的这些基本字符串的操作,如果用正则表达式,则可以用很少的代码解决。

正则表达式经典应用:
1)字符串模式验证,例如是否是邮箱模式,是否是有效的身份证。

2)多个元组直接存储需要的信息,或用或形式,提取出多个需要要的信息。

3)字符串的一些指定的替换。

js中的正则表达式:

RegExp对象由字符模式和搜索范围组成。

字符串模式的类型:

(1). 字符和模式,连续出现组合关系:字符串长度确定的模式(包括确定的字符串和模糊匹配的字符)"%d%d/%d%d/%d%d%d%d", “Jackson”,本身就是表达了与的关系。

(2).自定义逻辑组合/或/非:字符串模式中任意一个都遍历目标串的模式([], (),逻辑与或|, ^非),[AEIOUaeiou]匹配元音,“([a-z][A-Z][0-9])+”()是将几个或组合在一起匹配aB0。”[to|too|2]”;^在[]内为非,否则为定位符号;与可以用或来表达/[^\w\s]/g。

(3). 数量:字符模式个数的修饰,+,-,*,?,{n}元符号;“fo+”与football匹配,+为至少有一个或者多个这样的字符。

(4). 位置:字符串模式位置的修饰,^,$,\b, \B;”ar$”和car匹配。

(5). 转义符号\, “Th\*”与Th*匹配,常规模式在字符串中也要”\\s”,前面的\也是转义字符。

搜索范围有i, g, m:

i 执行对大小写不敏感的匹配。

g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。

m 执行多行匹配。

C#中使用正则表达式模式和js一致,要用模式中的\符号,那么需要将输入转换到字符串时候保持,所以需要"\\"或者@"\"。

C#中的正则表达式需要用到RegularExpressions命名空间,Regex对象, MatchCollection字符匹配后枚举结果,Match单个匹配字符串封装。

正则表达式使用实例:

using System;
using System.Text.RegularExpressions;

namespace Wrox.ProCSharp.RegularExpressionPlayaround
{
class MainEntryPoint
{
static void Main()
{
Find3();
Console.ReadLine();
}

static void Find1()
{
const string text = @"XML has made a major impact in almost every aspect of
software development. Designed as an open, extensible, self-describing
language, it has become the standard for data and document delivery on
the web. The panoply of XML-related technologies continues to develop
at breakneck speed, to enable validation, navigation, transformation,
linking, querying, description, and messaging of data.";

const string pattern = @"\bn\S*ion\b";
// matches正则表达式运算返回的结果
MatchCollection matches = Regex.Matches(text, pattern,
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);

// 输出结果
WriteMatches(text, matches);
}

static void Find2()
{
const string text = @"XML has made a major impact in almost every aspect of
software development. Designed as an open, extensible, self-describing
language, it has become the standard for data and document delivery on
the web. The panoply of XML-related technologies continues to develop
at breakneck speed, to enable validation, navigation, transformation,
linking, querying, description, and messaging of data.";

const string pattern = @"\bn";
MatchCollection matches = Regex.Matches(text, pattern,
RegexOptions.IgnoreCase);

WriteMatches(text, matches);
}

static void Find3()
{
// 1)从文本中提取出指定的模式
Console.WriteLine("从文本中提取出指定的模式");
const string urlText = "sljflsfj sfjlsjf fj http://blog.csdn.net/blues1021"; const string pattern = @"\b(\S+)://([^:]+)(?::(\S+))?\b";
MatchCollection matches = Regex.Matches(urlText, pattern,
RegexOptions.IgnoreCase);

WriteMatches(urlText, matches);

// 2)截取需要的字符串信息 类似C原因中的sscanf
// string url = "http://www.contoso.com:8080/letters/readme.html";
// const string pattern2 = @"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/";
Console.WriteLine("截取需要的字符串信息 类似C原因中的sscanf");
const string textCapture = "http://blog.csdn.net/blues1021";
const string patternCapture = @"^(?<proto>\w+)://?(?<address>[^/]+)/?(?<name>\S+)";
Regex r = new Regex(patternCapture,RegexOptions.None, TimeSpan.FromMilliseconds(150));
Match m = r.Match(textCapture);
if(m.Success)
{
string strProtocal = m.Result("${proto}");
string strAddress = m.Result("${address}");
string strName = m.Result("${name}");
Console.WriteLine("Parse Protocal: " + strProtocal + ", Address:" + strAddress + ", Name:" + strName );
// Console.WriteLine(m.Result("${proto}:${port}"));
}
}

static void WriteMatches(string text, MatchCollection matches)
{
Console.WriteLine("Original text was: \n\n" + text + "\n");
Console.WriteLine("No. of matches: " + matches.Count);
foreach (Match nextMatch in matches)
{
// nextMatch是当前匹配的字符的委托对象,Match.Index属性
int index = nextMatch.Index;
// Match.ToString功能
string result = nextMatch.ToString();

// 匹配在字符串中间,字符前面取5个字符索引长度,否则取当前字符索引长度,charsBefore是相对位置
int charsBefore = (index < 5) ? index : 5;
// 剩下的字符长度
int fromEnd = text.Length - index - result.Length;
// 剩下的字符长度太小了就是剩下字符长度,否则取5个长度
int charsAfter = (fromEnd < 5) ? fromEnd : 5;
// 需要展示的字符长度位置,目的是为了说明该查找提取出来的字符所在原来字符串中的位置。
int charsToDisplay = charsBefore + charsAfter + result.Length;

Console.WriteLine("Index: {0}, \tString: {1}, \t{2}",
index, result,
// 截取附近的字符串
text.Substring(index - charsBefore, charsToDisplay));

}
}
}
}了解更多的复杂字符串的正则表达式操作,.net也提供了相应的类GroupCollection,CaptureColleciton等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: