C#中的字符串, String类和StringBuilder类

Posted 苏州程序大白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#中的字符串, String类和StringBuilder类相关的知识,希望对你有一定的参考价值。

C#中的字符串, String类和StringBuilder类

1、简介

字符串对大多数计算机程序而言非常普遍. 像文字处理软件和网页应用程序这些程序类型 都广泛采用了字符串. 这使得处理这类应用程序的程序员在字符串处理的效率问题上需要花费额外的心思. 本章会研究C#处理字符串的方法, 分析如何使用String类, 最后还会介绍如何用StringBuilder类. 当程序需要对String对象进行许多改变时会用到StringBuilder类. 这是因为字符串和String对象都是不可改变的, 而StringBuilder对象则可变的. 会在章节内解释和说明细节。

2、String类的应用

字符串是字符的序列. 它可以包含字母, 数字和其他符号. 在C#中把字符序列用一对闭合的双引号包围起来就可以产生文字串. 下面是一些文字串的实例 :

“铁拳无敌俞大猷”

"故园亲侣如相问, 愧我边尘尚未收. "

“2019-05-08”

“mmcmillan@pulaskitech. edu”

字符串可以由来自Unicode 字符集的任何字符组成. 字符串也可以是没有字符而组成的. 这种特殊的字符串被称为是空字符串. 它的形式是由一对彼此相连的双引号构成的(""). 请千万记住这不是表示空格的字符串. 表示空格的字符串形式是" "。

C#中的字符串具有精神分裂的天性——即字符串既是原生类型(native type)又是一种类的对象. 实际上更准确的说法应该是可以把字符串作为原生数值来使用, 但是事实上每个产生的字符串都 是String 类的一个对象. 稍后会说明原因。

2.1、创建String对象

创建字符串的dao, a写法如下所示 :

string name = “Jennifer Ingram”;

当然, 也可以使用两条语句中先声明变量然后再进行赋值. 字符串声明代码的写法看上去就像一个常规的变量, 但是实际上它是创建了String的一个实例。

C#的字符串还允许在字符串中放置转义字符. C 语言程序员和C++语言程序员都很熟悉此技术, 但是对于那些具有VB 背景的人来说它却可能是一个新内容. 转义字符用来把诸如换行符和制表符这类版式字符放置在字符串内. 转义字符由一个反斜杠(\\)开始, 后边跟着单独一个表示版式的字母. 例如, \\n 说明换行, 而\\t 则表示一个制表符. 在下面这行单独字符串中用到了这两种转义字符 :

string name = “第一行文字\\n第二行文字\\t增加了缩进的文字”;

2.2、常用的String类方法

虽然对字符串可以执行许多操作, 不过有几种操作是最常用的, 它们分别是 :1. 找到子字符串. 2. 获取字符串的长度. 3. 确定字符在字符串中的位置。

下面这段程序就说明了如何执行这些操作. 这里把String 对象实例化成字符串"Hello, world!". 然后把此字符串分离成两个组成段 :第一个单词和第二个单词. 代码如下所示, 后边跟着的是对用到的String 方法的解释说明。

using System;

class Program {
    static void Main()
    {
        string string1 = "Hello, world!";
        int len = string1.Length;
        int pos = string1.IndexOf(" ");
        string firstWord, secondWord;
        firstWord = string1.Substring(0, pos);
        secondWord = string1.Substring(pos + 1, (len - 1) - (pos + 1));
        Console.WriteLine("单词1 :" + firstWord);
        Console.WriteLine("单词2 :" + secondWord);
        Console.Read();
    }
}

程序首先做的事就是用Length属性来确定对象string1 的长度. 长度简单说就是字符串中所有字符的总数量. 这里会简要解释一下为什么需要知道字符串的长度。

为了把两词的短语分离出单词, 就需要知道怎么分隔单词. 在一个符合格式的短语中, 空格可以用来分隔单词, 所以就需要找到短语中两个单词之间的空格. 这可以用IndexOf 方法做到. 此方法需要一个字符, 然后返回此字符在字符串中的位置. C#中的字符串中的第一个字符在位置0 上, 第二个字符则是在位置1 上, 其他则以此类推. 如果无法在字符串中找到某个字符, 就返回-1。

IndexOf 方法找到了分隔两个单词的空格的位置, 然后就用下一个方法Substring来真地把第一个单词从字符串中抽出来. Substring方法需要两个参数 :开始位置和要抽出字符的数量. Substring方法会把所要求的字符全部从字符串中抽出, 但是如果试图超过字符串的末尾的话, 就无法得到预期的内容。

程序把第一个单词从位置0 开始由字符串中抽离出来, 而且是抽出了pos个数量的字符. 既然pos包含了空格的位置, 那么这样做好像很多余. 但是, 由于初始字符索引是零, 所以这样做才会是正确的数量。

下一步就是把第二个单词抽离出来. 既然知道了空格的位置, 所以就知道了第二个单词是从pos+1开始的. 较困难的部分就是要确定抽离出来的字符的数量, 因为如果超出了字符串的末尾就 无法得到预期的结果了. 这里可以用一个类别公式来完成计算. 首先, 把1和找到的空格位 置相加, 然后用串长减去这个数值. 这样就可以准确地告诉方法要抽离的字符的数量了。

虽然这段程序很有趣, 但是它不是很实用. 实际需要的程序应该是可以从任意长度的符合格式短语中抽离出单词. 我们可以用几种不同的算法来实现. 这里将用到的算法包含下列这些步骤 :

1、找到字符串中第一个空格的位置。
2、抽取单词。
3、从空格后边开始到字符串的末尾构建一个新的字符串。
4、寻找新字符串中的另外一个空格。
5、如果没有其他空格, 那么抽取的单词就从当前位置到字符串的末尾。
6、否则循环返回第2 步重复操作。
下面就是根据此算法编写的代码(从字符串中抽取的每个单词都存储到名为word的集合里面) :

static void Main()
{
    string astring = "中文 不 像 英文一样 需要 加 空格";
    int pos;
    string word;
    ArrayList words = new ArrayList();
    pos = astring.IndexOf(" ");
    while(pos > 0)
    {
        word = astring.Substring(0, pos);
        words.Add(word);
        //每次拿到词之后都从原字符串中把找到的词和它后面的空格去掉了
        astring = astring.Substring(pos + 1, astring.Length - (pos + 1));
        pos = astring.IndexOf(" ");
        if (pos == -1) {
            word = astring.Substring(0, astring.Length);
            words.Add(word);
        }
        Console.WriteLine($"{word}");
    }
    Console.Read();
}

当然, 如果打算在程序中实际使用这个算法, 那么最好把它做成一个函数并且返回一个集合, 如下所示 :

static void Main()
{
    string astring = "中文 不 像 英文一样 需要 加 空格";
    ArrayList words = new ArrayList();
    words = SplitWords(astring);
    foreach (object item in words) {
        Console.WriteLine($"{item}");
    }
    Console.Read();
}

static ArrayList SplitWords(string astring)
{
    string[] ws = new string[astring.Length - 1];
    ArrayList words = new ArrayList();
    int pos;
    string word;
    pos = astring.IndexOf(" ");
    while (pos > 0) {
        word = astring.Substring(0, pos);
        words.Add(word);
        astring = astring.Substring(pos + 1, astring.Length - (pos + 1));
        pos = astring.IndexOf(" ");
        if (pos == -1) {
            word = astring.Substring(0, astring.Length);
            words.Add(word);
        }
    }
    return words;
}

实际上String类已经有一个把按照指定字符分割字符串的方法了(Split 方法), 而且还有一个方法可以取走一个数据集合并且把几部分组合成一个字符串(Join方法). 下一小节将看到这些方法.。

3、plit方法和Join 方法

把字符串分解成独立的数据段是一种非常常见的功能. 从网络应用软件到日常办公应用软件 范围内的许多程序都把数据存储在一些字符串格式类型里. 为了简化字符串的分解以及再次合并在一起的过程, String类提供了两种可用的方法 :用于分解字符串的 Split 方法, 以及用来把存储在数组中的数据制作成字符串的Join 方法。

Split 方法取得一条字符串后, 就会按照指定字符分割字符串, 并返回包含分割后字符串的数组. 在前一小节的实例中, SplitWords函数始终采用空格作为分隔符. 而在使用Split 方法时则可以使用参数指定分隔符, 分隔符就是此方法的第一个参数. 该参数必须以 char型数组的形式出 现, 而数组的第一个元素将是用作分隔符的字符。

许多应用程序是通过写出用逗号分隔的数据串的方式来输出数据的. 这被称为是逗号分隔值串, 或简称为CSVs. 某些作者则采用逗号分隔这一术语. 逗号分隔串就如同下列这样的形式 :“Mike, McMillan, 3000W. Scenic, North Little Rock, Ar, 72118”. 此串内的每一字符串数据部分都是用逗号进行分隔的. 这里可以用Split 方法把每个逻辑数据块放入到一个数组中, 如下列所示 :

string data = "Mike,McMillan,3000 W. Scenic,North Little Rock,AR,72118"; 
string[] sdata; 
char[] delimiter = new char[] {','}; 
sdata = data.Split(delimiter); 

使用Split方法得到字符串数组后, 就能以常规数组的方法来访问这些数据了 :

foreach (string word in sdata) 
Console.Write(word + " "); 

Split 方法还可以添加第二个参数, 代表了想要将原字符串分割为几部分. 例如, 如果想要把第一个串元素放置在数组的首位置而把串的其余部分放在第二个元素内, 就需要采用 下列方式调用此方法 :

//参数2表示只分割为两部分
sdata = data.Split(delimiter, 2); 

数组内的元素将是这样的 :

第0 个元素——Mike

第1 个元素——McMillan, 3000W. Scenic, North Little Rock, Ar, 72118

现在来讨论另外一种方法, 即用Join 方法从数组变为字符串. 此方法接受两个参数 :参数1代表目标数组, 参数2代表合并为字符串后, 用来分隔每个元素数据的字符。

还应该注意的是该方法通过String类直接调用, 不需要被String的实例调用。

下面这个实例采用了和前面例子相同的数据 :

static void Main()
{
    string data = "Mike,McMillan,3000 W. Scenic,North Little Rock,AR,72118";
    string[] sdata;
    char[] delimiter = new char[] { ',' };
    sdata = data.Split(delimiter);
    foreach (object item in sdata) {
        Console.WriteLine($"{item}");
    }
    //将分割后的字符串数组再以指定分隔符连接到一起
    Console.WriteLine(string.Join(",", sdata));
    Console.Read();
}

可以利用Split方法从其他数据源中获得数据放入自身程序; Join方法可以把数据以字符串的形式从自身程序发送到其他程序中。

4、字符串比较方法

在C#中有几种比较String对象的方法. 最直接的就是使用等号来比较字符串是否相等. 然而还有一些情况要比较字符串之间的其他关系, 例如, 如果希望知道字符串是大于, 小于, 还是等于另外一个字符串, 需要用到String类中的方法了。

字符串之间的互相比较就如同数的比较一样. 但是, 由于"a"是大于还是小于"H"不是直接观察并看不出来, 所以需要借助数字测量方法. 这种测量就是Unicode表. 每一个字符都有一个Unicode值, 操作系统就是用此数值把字符的二进 制表示转化成为字符的形式. 通过使用ASC 函数可以确定字符的Unicode值. ASC 实际上指的就是数的ASCII 码. ASCII 码是一种先于Unicode的早期数字编码, 而ASC 函数是在Unicode包含ASCII 之前被首先开发出来的。

为了找到字符的ASCII 值, 可以采用强制类型转换把字符简单地转换成为一个整数, 如下所示 :

int charCode; 
charCode = (int)'a'; 

上述代码会把charCode的值设置为97。

然后, 两个字符串的比较实际就是比较它们的数字编码. 字符串"a"和字符串"b"不相等, 就是因为编码 97 不同于编码 98. 事实上compareTo方法可以用来确定两个 String对象之间的精确关系. 这里将会看到采用此方法的简单工作原理。

第一个要检测的比较方法就是Equal方法. 此方法由一个String 对象调用, 并使用另外一个String对象作为参数. 接着就会逐个字符的比较两个String对象. 如果这两个String对象每一个字符都相同(以它们的数字编码为基础), 那么方法就会返回一个True值. 否则, 方法就会返回False值. 此方法的调用如下所示 :

string s1 = "foobar"; 
string s2 = "foobar"; 
if (s1.Equals(s2)) 
    Console.WriteLine("它们相等"); 
else 
    Console.WriteLine("它们不相等"); 

下一个比较字符串的方法就是CompareTo. 此方法也是取一个String作为参数, 但是它不会布尔值. 取而代之的是此方法会返回1, -1 或者0, 具体数值要由传递给的字符串和调用此方法的字符串实例之间的关系来决定 :

string s1 = "foobar"; 
string s2 = "foobar"; 
Console.WriteLine(s1.CompareTo(s2)); // returns 0 
s2 = "foofoo"; 
Console.WriteLine(s1.CompareTo(s2)); // returns -1 
s2 = "fooaar"; 
Console.WriteLine(s1.CompareTo(s2)); // returns 1 

CompareTo方法会将调用它的字符串1与指定字符串2进行比较,并返回一个整数,该整数表示字符串1在排序顺序中位于字符串2之前(-1)、之后(1)还是与其出现在同一位置(0)。

替换CompareTo方法的就是Compare方法. Compare方法通过String类直接调用. 此方法会执行和CompareTo方法相同的比较规则, Compare方法的应用如下所示:

static void Main() 
{ 
    string s1 = "foobar"; 
    string s2 = "foobar"; 
    int compVal = String.Compare(s1, s2); 
    switch (compVal) 
    { 
        case 0: Console.WriteLine(s1 + " " + s2 + " are equal"); 
            break; 
        case 1: Console.WriteLine(s1 + " is less than " + s2); 
            break; 
        case 2: Console.WriteLine(s1 + " is greater than" + s2); 
            break; 
        default: Console.WriteLine("Can't compare"); 
            break; 
    } 
} 

(关于CompareTo和Compare, 的不同之处, 可以参考这篇博客提到的第一点)
另外两种在处理字符串时会很有用的比较方法是StartsWith和EndsWith. 它们需要一个字符串参数, 并检查调用方法的字符串是否以参数字符串作为开始或结束, 如果是返回true, 否则返回false.

下面两段小程序说明了这些方法的用法. 首先, 这里将先说明EndsWith 方法:

using System; 
using System.Collections; 

class Chapter7 
{ 
    static void Main() 
    { 
        string[] nouns = new string[] {"cat", "dog", "bird","eggs", "bones"}; 
        ArrayList pluralNouns = new ArrayList(); 
        foreach (string noun in nouns) 
            if (noun.EndsWith("s")) 
                pluralNouns.Add(noun); 
        foreach (string noun in pluralNouns) 
            Console.Write(noun + " "); 
    } 
} 

这个程序先创建了一个名词数组, 且其中一些名词还是复数的形式. 接着, 程序循环遍历数组的元素, 并且查看名词是否为复数. 如果是, 就把这些名词添加到一个集合里. 然后, 程序遍历集合并且把每个复数名词显示出来。

接下来这个程序采用了相同的基本思想来确定以前缀"tri"开头的单词:

using System; 
using System.Collections; 

class Chapter7 
{ 
    static void Main() 
    { 
        string[] words = new string[]{"triangle", "diagonal", "trimester","bifocal","triglycerides"}; 
        ArrayList triWords = new ArrayList(); 
        foreach (string word in words) 
            if (word.StartsWith("tri")) 
                triWords.Add(word); 
        foreach (string word in triWords) 
            Console.Write(word + " "); 
    } 
} 

5、处理字符串的方法

字符串处理通常包括对字符串的更改. 我们需要在字符串中插入新的字符, 或从字符串中移除字符, 或是用新字符替换旧字符, 以及向字符串添加空格或者从字符 串中移除空格等等. 在 String类中针对这些操作全部有相应的方法, 因而本小节将对这些方法进行讨论。

这里将先以Insert方法开始. 此方法会把某个字符串插入到另外一个字符串的指定位置。

Insert方法会返回新的字符串. 调用此方法的格式如下所示 :

//Insert方法会把targetString插入到新字符串的position索引位置
String1 = String0.Insert(position, targetString);

下面来看一个实例:

static void Main()
{
    string s1 = "来了,?欢迎来到苏州程序大白博客!";
    string s2 = "老弟";
    int pos = s1.IndexOf(",");
    s1 = s1.Insert(pos + 1, s2);
    Console.WriteLine(s1);
    Console.Read();
}

运行结果是 :

来了, 老弟?欢迎来到苏州程序大白博客!

此程序逗号索引+1的位置插入了其他字符串。

Insert方法之后下一个最合理的方法就是Remove 方法了. 这种方法需要两个整数参数: 开始索引和要移除字符的数量. 下面的代码在插入新字符串后, 接着又把它从字符串中移除掉:

static void Main()
{
    string s1 = "来了,?欢迎来到苏州程序大白博客!";
    string s2 = "老弟";
    int pos = s1.IndexOf(",");
    s1 = s1.Insert(pos + 1, s2);
    Console.WriteLine(s1);
    s1 = s1.Remove(pos + 1, s2.Length);
    Console.WriteLine(s1);
    Console.Read();
}

为了移除新字符串, Remove 方法采用了与插入新字符串相同的位置, 而且通过获取新字符串的长度来计算要移除的长度. 这样做, 就可以随意更改要插入的新字符串, 而不需要修改代码 :

static void Main()
{
    string s1 = "来了,?苏州程序大白博客!";
    string s2 = "老大哥";
    int pos = s1.IndexOf(",");
    s1 = s1.Insert(pos + 1, s2);
    Console.WriteLine(s1);
    s1 = s1.Remove(pos + 1, s2.Length);
    Console.WriteLine(s1);
    Console.Read();
}

程序运行结果 :
在这里插入图片描述
接下来介绍的方法是Replace方法. 该方法需要两个参数: 要移除掉的字符串和用来替换掉的字符串. 此方方会返回新的字符串. 下面就是Replace方法的使用过程:

static void Main()
{
    string[] words = new string[] { "大哥", "二哥", "三哥" };
    for (int i = 0; i <= words.GetUpperBound(0); i++) {
        words[i] = words[i].Replace("哥", "弟");
        Console.WriteLine(words[i]);
    }
    Console.Read();
}

程序运行结果 :
在这里插入图片描述
由于要操作的字符串是一个数组中的元素, 所以需要通过索引来访问它们, 再对它们调用Replace方法

显示来自程序的数据时, 为了数据排列美观, 可能需要在打印区域内对数据显示的对齐格式进行调整. String类包括两种执行对齐操作的方法: PadLeft方法和PadRight方法. PadLeft方法 会对字符串进行右对齐排列, 而PadRight 方法会对字符串进行左对齐排列. 例如, 若果需要在一个10 个字符宽度区域内右对齐打印单词"Hello", 就需要写成下列形式 :


string s1 = "Hello"; 
Console.WriteLine(s1.PadLeft(10)); 
Console.WriteLine("world"); 

程序运行结果 :
在这里插入图片描述
下面是PadRight方法的例子 :

string s1 = "Hello";
string s2 = "world";
string s3 = "Goodbye";
Console.Write(s1.PadRight(10));
Console.WriteLine(s2.PadRight(10));
Console.Write(s3.PadRight(10));
Console.WriteLine(s2.PadRight(10));
Console.Read();

程序运行结果 :
在这里插入图片描述
还有一个实例说明了如何排列来自数组的数据使其更容易阅读 :

using System;

class Program {
    static void Main()
    {
        string[,] names = new string[,]
        {
            {"1504", "Mary", "Ella", "Steve", "Bob"},
            {"1133", "Elizabeth", "Alex", "David", "Joe"},
            {"2624", "Joel", "Chris", "Craig",<

以上是关于C#中的字符串, String类和StringBuilder类的主要内容,如果未能解决你的问题,请参考以下文章

C#中的正则匹配和文本处理

C#命名空间与类和方法的认识

string stringbuffer StringBuilder

StringStringBuilderStringBuffer 的区别

StringStringBuilderStringBuffer 的区别

java 初识String