zoukankan      html  css  js  c++  java
  • 字符、字符串和文本处理

    1.1字符

    在.NET Framework中,字符都是用16位Unicode编码(UTF-16)的(编译时用UTF-16编码成2进制存到硬盘,程序运行时再用utf-16解码显示代码中的字符串,在内存中相应的字节流就是用UTF-16编码过的),也就是说所有字符都是占2个字节16位,这简化了国际化应用程序的开发。Unicode字符集有很多种编码方案,常用的有:

    UTF-16:所有字符被编码成2个字节

    UTF-8:十进制小于128的字符被编码成1个字节(可表示欧美地区使用的字符),128~2047的字符被编码成2个字节(可表示欧洲和中东语言),大于2047的字符被编码成3个字节(可表示东亚地区的语言)

    UTF-32:所有字符都被编码成4个字节

    Unicode字符集还有个ASCII编码方案,这种编码只能将小于128的16位字符转换成单字节,而其他超过127的字符都会丢失。

    GB2312等其他字符集(这些字符集可能只有一种同名编码方案)

    针对Char的一个实例,可以调用Char类型的静态方法GetUnicodeCategory,这个方法返回的是System.Globalization.UnicodeCategory枚举类型的一个值。这个值指出该字符是控制字符、货币符号、小写字母、大写字母、标点符号、数字符号 还是其他Unicode标准定义的符号。 其他一些静态方法如IsDigit、IsLetter、IsUpper、IsControl、IsSymol等都在内部调用了GetUnicodeCategory,并简单返回true或false。注意,所以这些方法要么获取单个字符作为参数,要么获取一个String以及目标字符在这个String中的索引作为参数。

    另外,可以调用静态方法ToLowerInvariant或者ToUpperInvariant以一种忽略语言文化的方式,将一个字符转化为小写或大写。如果调用ToLower和ToUpper方法,在转换时要使用与线程相关的语言文化信息,语言文化信息是这两个方法在内部查询System.Threading.Thread类的静态CurrentCulture属性来获得的。还可以向这些方法传递CultureInfo类的一个实例来具体指定一种语言文化。ToLower和ToUpper之所以需要语言文化信息,是因为字母的大小写转换是依赖于语言文化操作的。

    可以使用三种技术实现各种数值类型与Char实例的相互转换,下面按照优先顺序列出这些技术。

    *转型(强制类型转换)要将一个Char转换成一个数值(如Int32),最简单的方法是强制类型转换。在三种技术中,这种技术效率最高,因为编译器会生成IL(Intermediate Language中间语言)指令来执行转换,不必调用任何方法。

    *使用Convert类型 System.Convert类型提供了几个静态方法来实现Char和数值类型的相互转换。这些方法都以checked方式来执行转换,因此一旦发现转换造成数据丢失,就会抛出一个OverflowException异常。

    *使用IConvertible接口 Char类型和FCL中的所有数值类型都实现了IConvertible接口。该接口定义了像ToUInt16和ToChar这样的方法。但是这种技术效率最差,因为在值类型上调用一个接口方法,要求对实例进行装箱(Char和所有数值类型都是值类型)。如果某个类型不能转换(比如Char转换成Boolean),或者转换造成数据的丢失,IConvertible的方法会抛出一个System.InvalidCastException异常。

    以下代码简单演示如何使用这三种技术

     1             Char c;
     2             Int32 n;
     3 
     4             //使用C#强制转换技术实现数字与字符的相互转型
     5             c = (Char) 65;
     6             Console.WriteLine(c);       //显示"A"
     7 
     8             n = (Int32) c;
     9             Console.WriteLine(n);       //显示"65"
    10 
    11             c = unchecked((Char) (65536 + 65));
    12             Console.WriteLine(c);       //显示"A"
    13 
    14             //使用Convert实现数字与字符的相互转换
    15             c = Convert.ToChar(65);
    16             Console.WriteLine(c);       //显示"A"
    17 
    18             n = Convert.ToInt32(c);
    19             Console.WriteLine(n);       //显示"65"
    20 
    21             //演示Convert的范围检查
    22             try
    23             {
    24                 c = Convert.ToChar(70000);  //对16位来说太大
    25                 Console.WriteLine(c);   // 不执行
    26             }
    27             catch (OverflowException)
    28             {
    29                 
    30                 Console.WriteLine("Can't 70000 to a char!");
    31             }
    32 
    33             //使用IConvertible实现数字与字符的相互转换
    34             c = ((IConvertible) 65).ToChar(null);
    35             Console.WriteLine(c);       //显示"A"
    36 
    37             n = ((IConvertible) c).ToInt32(null);
    38             Console.WriteLine(n);       //显示"65"
    View Code

    1.2 System.String类型

    1.2.1 构造字符串

    一个String代表一个不可变的顺序字符集。String类型直接派生自Object,所以它是一个引用类型。因此String对象总是存在于堆上,永远不会跑到线程栈。许多编程语言都将String视为一个基元类型----可以再源代码中直接表示文本常量字符串(string s="hi"); 编译器将这些文本常量字符串放到模块的元数据中,并在运行时加载和引用它们。

    在C#中,不能使用new操作符从一个文本常量字符串构造一个String对象。

    对于换行符、回车符和退格符这样的特殊字符,C#采用的是C/C++开发人员熟悉的转义机制:

    1  // 包含回车符和换行符的字符串
    2 string s="hi
    there";
    3 
    4 //NewLine是System.Environment类型定义的一个属性,NewLine属性是依赖于平台的,它在任何平台上都能正确工作,建议使用这种方式
    5 string s="hi"+Environment.NewLine+"there";

    可以使用C#的+操作符将几个字符串连接成一个,如下所示:

    对于如下由好几个文本常量字符串组成的字符串:

    string s="hi"+" "+"there";
    
    //注意:编译器会在编译时连接它们,最终只会将一个字符串放到模块的元数据中
    对于如下由好几个非文本常量字符串组成的字符串:
    string s1="hi"; string s2="there"; string s=s1+s2; 
    
    //注意:对非文本常量字符串使用+操作符,连接会在运行时进行。
    若要在运行时将几个字符串连接到一起,应避免使用+操作符,因为它会在堆上创建多个字符串对象,而堆是需要回收的,从而影响性能。相反,应尽量使用System.Text.StringBuilder类型
    
    

    C#还提供了逐字字符串,通常用于指定文件或目录的路径,或与正则表达式配合使用。采取这种方式,引号之间的所有字符都会被视为字符串的一部分:

    1 //指定应用程序路径
    2 string file="C:\windows\System32\Notepad.exe";
    3 
    4 //使用逐字字符串来指定应用程序路径
    5 string file=@"C:windowsSystem32Notepad.exe";

    在字符串前添加@符号,使编译器知道字符串是一个逐字字符串,这告诉编译器将反斜杠视为文本常量,而不是转义符,使文件路径在源代码中更易读。

    1.2.2 字符串是不可变的

    string对象最重要的一个事实就是,它是不可变的,也就是说字符串一经创建便不能更改,不能变长,变短或修改其中任何字符。

    所以允许对一个字符串进行各种操作而不实质的改变字符串:

    1 string s="hiworld"; if(s.ToUperInvariant().Substring(0,2).EndsWith("EXE"))
    2 {
    3     ...
    4 }

    在此,ToUperInvariant()返回一个新的字符串,它没有修改s的字符,然后Substring(0,2)在ToUperInvariant()返回的新字符串的基础上又返回一个新字符串。 ToUperInvariant和Substring创建的两个临时字符串不会由应用程序代码长久的引用,垃圾回收器会在下次回收时回收它们的内存,如果执行大量的字符串操作,会在堆上创建大量的string对象,造成频繁的垃圾回收,从而损害应用程序的性能,要想高效率地执行大量字符串操作,请用StringBuilder类。

    使字符串不可变,还意味着在操纵或访问一个字符串时不会发生线程同步问题。

  • 相关阅读:
    走了
    地表最简单安装MySQL及配置的方法,没有之一
    周总结
    Codeforces 1323 div2题解ABC
    Code force-CodeCraft-20 (Div. 2) D. Nash Matrix 详解(DFS构造)
    LeetCode 1293. Shortest Path in a Grid with Obstacles Elimination
    LeetCode 1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    LeetCode 1291. Sequential Digits
    LeetCode 1290. Convert Binary Number in a Linked List to Integer
    LeetCode 91. Decode Ways
  • 原文地址:https://www.cnblogs.com/lwenwen/p/3278108.html
Copyright © 2011-2022 走看看