.net中的字符串处理

    字符串在.net编程中是我们进行数据处理的常用数据类型,面对日常工作中复杂的数据处理要求,我们需要对字符串进行许多操作,比如查找,替换,复制等等,还有字符串的模式匹配。

    .net中对字符串进行处理的类有System.String和System.Text命名空间中的类。

1:string 类和StringBuilder类

     string类可以创建字符串,string类是一个引用类型,它的数据是分配在托管堆上的,假如我们创建一个字符串变量A并给它赋值B后,.net会先检测B字符串的大小,并在托管堆上给B分配足够B用的内存空间,不会太大也不会太小。初始化后A变量所指向引用B,而且B就不会再改变。如果我们要改变A变量的值为C,.net会再在托管堆上给C分配足够C用的内存空间,再把A变量的指针指向C,原来的在托管堆中的B没有变量引用,就会等待clr的回收。这样的工作方式是十分耗资源的。因为来回反复的字符串操作就来回反复的在托管堆上创建内存区域,回收内存区域。所以对字符串进行诸如复制、替换等文字处理时是十分消耗资源的。

    所以操作字符串我们不用string类的方法,微软给我们一个更好操作字符串的类,就是位于System.Text命名空间中的StringBuilder类。这个类也是引用类型的。上面的例子我们拿StringBuilder来做一遍。假如我们创建一个StringBuilder字符串变量A并给他赋值B后,托管堆会分配给B更多更大的内存空间,在这个足够大的内存空间里我们可以进行字符串操作,所有的操作数据结果只会在这个已经分配好的空间内进行,不会再次创建新的空间来消耗资源。除非我们在创建B的时候给的内存空间不够大。当然我们可以再创建StringBuilder对象的时候显式的指定空间的大小。理论上StringBuilder可以分配到的空间是20亿个。StringBuilder在我们起初创建内存空间不足时会自动进行判断,并自动把内存空间加大原来的一倍。

   所以我们可以用string类来存储和显示字符串,用StringBuilder类来操作字符串。

   下面是string类和stringbuilder类的一些常用方法。

   

 

2:格式化字符串:

  字符串的操作不仅仅是我们平常的把字符串按照原样打出来,这也满足不了我们日常生活工作中的需要。比如一个时间2006.05.1显示为问题,英国是05/01/2006,01/05/2006,再比如我们小学经常计算加减乘除用的公式,这些都需要我们把字符串进行变形显示输出,.net提供了格式化字符串的方法。最常用的是string.format和stringbuilder.format方法。所有的要进行格式化操作的类都实现了IFmattable接口,这个接口只有一个方法契约,就是tostring方法,这个方法有两个参数string ToString(string format,IFormatProvider formatProvider )。string类要实现格式化字符串,就实现了此接口实现了这个接口规定的tostring方法。前面所说的string.format和stringbuilder.format方法其实内部还是用的这个tostring()方法进行格式化的。而我们经常在控制台程序中用到的console.write()方法和console.writeline()方法进行格式化时内部也是用的string.format和stringbuilder.format方法进行格式化包装。

            double d = 99.99;
            int i = 9999;
            Console.Write("the double is {0} and the int contains {1}", d, i);
            Console.ReadKey();

下面来看一下Console.Write("the double is {0} and the int contains {1}", d, i);的执行过程。    

1:首先,console.write方法会把其参数整个传给他里面的实现方法string.format方法。

public virtual void WriteLine(string format, object arg0, object arg1)
{
    this.WriteLine(string.Format(this.FormatProvider, format, new object[] { arg0, arg1 }));
}

 

   

2:然后string.format方法用调用其自己里面的实现方法stringbuilder.format方法。为什么会是这个方法呢?我们前面说过如果我们要操作字符串要用高效的stringbuiler类。stringbuilder也是完全接受了string.format方法穿过来的参数列表。利用它的stringbuilder.AppendFormat方法来对传过来的字符串进行格式化操作,我们知道要执行格式化操作,必须要求格式化的对象实现了IFoamttable接口之后,才可以调用这个对象的tostring重载方法,进行格式化操作。所以stringbuilder.AppendFormat方法内部会对传过来的要进行个会刷操作的对象进行检查,确定了其是否已经实现了IFoamttable接口,如果实现就继续。

[SecuritySafeCritical]
public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}

 

  

[SecuritySafeCritical]
public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    int num = 0;
    int length = format.Length;
    char ch = '\0';
    ICustomFormatter formatter = null;
    if (provider != null)
    {
        formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter));
    }
Label_0096:
    while (num < length)
    {
        ch = format[num];
        num++;
        if (ch == '}')
        {
            if ((num < length) && (format[num] == '}'))
            {
                num++;
            }
            else
            {
                FormatError();
            }
        }
        if (ch == '{')
        {
            if ((num < length) && (format[num] == '{'))
            {
                num++;
            }
            else
            {
                num--;
                break;
            }
        }
        this.Append(ch);
    }
    if (num == length)
    {
        return this;
    }
    num++;
    if (((num == length) || ((ch = format[num]) < '0')) || (ch > '9'))
    {
        FormatError();
    }
    int index = 0;
    do
    {
        index = ((index * 10) + ch) - 0x30;
        num++;
        if (num == length)
        {
            FormatError();
        }
        ch = format[num];
    }
    while (((ch >= '0') && (ch <= '9')) && (index < 0xf4240));
    if (index >= args.Length)
    {
        throw new FormatException(Environment.GetResourceString("Format_IndexOutOfRange"));
    }
    while ((num < length) && ((ch = format[num]) == ' '))
    {
        num++;
    }
    bool flag = false;
    int num4 = 0;
    if (ch == ',')
    {
        num++;
        while ((num < length) && (format[num] == ' '))
        {
            num++;
        }
        if (num == length)
        {
            FormatError();
        }
        ch = format[num];
        if (ch == '-')
        {
            flag = true;
            num++;
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
        }
        if ((ch < '0') || (ch > '9'))
        {
            FormatError();
        }
        do
        {
            num4 = ((num4 * 10) + ch) - 0x30;
            num++;
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
        }
        while (((ch >= '0') && (ch <= '9')) && (num4 < 0xf4240));
    }
    while ((num < length) && ((ch = format[num]) == ' '))
    {
        num++;
    }
    object arg = args[index];
    StringBuilder builder = null;
    if (ch == ':')
    {
        num++;
        while (true)
        {
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
            num++;
            switch (ch)
            {
                case '{':
                    if ((num < length) && (format[num] == '{'))
                    {
                        num++;
                    }
                    else
                    {
                        FormatError();
                    }
                    break;

                case '}':
                    if ((num < length) && (format[num] == '}'))
                    {
                        num++;
                    }
                    else
                    {
                        num--;
                        goto Label_0250;
                    }
                    break;
            }
            if (builder == null)
            {
                builder = new StringBuilder();
            }
            builder.Append(ch);
        }
    }
Label_0250:
    if (ch != '}')
    {
        FormatError();
    }
    num++;
    string str = null;
    string str2 = null;
    if (formatter != null)
    {
        if (builder != null)
        {
            str = builder.ToString();
        }
        str2 = formatter.Format(str, arg, provider);
    }
    if (str2 == null) { IFormattable formattable = arg as IFormattable; if (formattable != null) { if ((str == null) && (builder != null)) { str = builder.ToString(); } str2 = formattable.ToString(str, provider); } else if (arg != null) { str2 = arg.ToString(); } }
    if (str2 == null)
    {
        str2 = string.Empty;
    }
    int repeatCount = num4 - str2.Length;
    if (!flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    this.Append(str2);
    if (flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    goto Label_0096;
}

 

 

  

到此为止我们的console.write()重载方法已经执行完毕了,当然里面还有很多细节,有兴趣的朋友可以用reflector来反编译代码研究。上面的代码来自reflector。另外,如果我们要对自己的类加上格式化功能,我们也可以实现IFormattable接口。常见的格式说明符,大家可以上网搜一下。

 

   

 

 

转载于:https://www.cnblogs.com/mushu/archive/2012/02/21/2361308.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值