文章目錄
在應用程式中使用最頻繁的類型是字串。字串簡稱串,是一種特殊的線 性表,其特殊性在於串中的資料元素是一個個的字元。字串在電腦的許多方面應用很廣。如在彙編和進階語言的編譯器中,來源程式和目標程式都是字串 資料。在交易處理程式中,顧客的資訊如姓名、地址等及貨物的名稱、產地和規 格等,都被作為字串來處理。另外,字串還具有自身的一些特性。因此,把字串作為一種資料結構來研究。
串的基本概念
串(String)由n(n ≥0)字元組成的有限序列。一般記為:S=”c1c2 …cn ”(n≥0) 其中,S是串名,雙引號作為串的定界符,用雙引號引起來的字元序列是串 值。ci(1≤i≤n )可以是字母、數字或其它字元,n為串的長度,當n=0時,稱為空白串(Empty String)。 串中任意個連續的字元組成的子序列稱為該串的子串(Substring)。包含子串的串相應地稱為主串。子串的第一個字元在主串中的位置叫子串的位置。
由於串中的字元都是連續儲存的,而在C#中串具有恒定不變的特性,即字 符串一經建立,就不能將其變長、變短或者改變其中任何的字元。所以,這裡不 討論串的鏈式儲存,也不用介面來表示串的操作。
串的基本操作的實現
1、求串長
求串的長度就是求串中字元的個數,可以通過求數組 data的長度來求串的長度。求串的長度的實現如下:
public int GetLength(){return data.Length;}
2、串比較
如果兩個串的長度相等並且對應位置的字元相同,則串相等,返回 0;如果串s對應位置的字元大於該串的字元或者如果串s的長度大於該串,而在該串的 長度返回內二者對應位置的字元相同,則返回-1,該串小於串s;其餘情況返回 1,該串大於串s。 串比較的演算法實現如下:
public int Compare(StringDS s){int len=((this.GetLength()<=s.GetLength())? this.GetLength():s.GetLength());int i = 0;for (i = 0; i < len; ++i){if (this[i] != s[i]){break;}}if (i <= len){if (this[i] < s[i]){return -1;}else if (this[i] > s[i]){return 1;}}else if(this.GetLength() s.GetLength()){return 0;}else if (this.GetLength() < s.GetLength()){return -1;}return 1;}
3、求子串
從主串的index位置起找長度為len的子串,若找到,返回該子串,否則,返回一個空串。 演算法實現如下:
public StringDS SubString(int index, int len){if ((index<0) || (index>this.GetLength()-1)|| (len<0) || (len>this.GetLength()-index)){Console.WriteLine("Position or Length is error!");return null;}StringDS s = new StringDS(len);for (int i = 0; i < len; ++i){s[i] = this[i + index-1];}return s;}
4、串聯接
將一個串和另外一個串聯接成一個串,其結果返回一個新串,新串的長度是兩個串的長度之和,新串的前部分是原串,長度為該串的長度,新串的後部分是串s,長度為串s的長度。 串聯接的演算法實現如下:
public StringDS Concat(StringDS s){StringDS s1 = new StringDS(this.GetLength()+ s.GetLength());for(int i = 0; i < this.GetLength(); ++i){s1.data[i] = this[i];}for(int j = 0; j < s.GetLength(); ++j){s1.data[this.GetLength() + j] = s[j];}return s1;}
5、串插入
串插入是在一個串的位置index處插入一個串s。如果位置符合條件,則該操作返回一個新串,新串的長度是該串的長度與串s的長度之和,新串的第1部分是 該串的開始字元到第index之間的字元,第2部分是串s,第3部分是該串從index 位置字元到該串的結束位置處的字元。如果位置不符合條件,則返回一個空串。 串插入的演算法如下:
public StringDS Insert(int index, StringDS s){int len = s.GetLength();int len2 = len + this.GetLength();StringDS s1 = new StringDS(len2);if (index < 0 || index > this.GetLength() - 1){Console.WriteLine("Position is error!");return null;}for (int i = 0; i < index; ++i){s1[i] = this[i];}for(int i = index; i < index + len ; ++i){s1[i] = s[i - index];}for (int i = index + len; i < len2; ++i){s1[i] = this[i - len];}return s1;}
6、串刪除
串刪除是從把串的第index位置起連續的len個字元的子串從主串中刪除掉。 如果位置和長度符合條件,則該操作返回一個新串,新串的長度是原串的長度減 去len,新串的前部分是原串的開始到第index個位置之間的字元,後部分是原串 從第index+len位置到原串結束的字元。如果位置和長度不符合條件,則返回一 個空串。 串刪除的演算法實現如下:
public StringDS Delete(int index, int len){if ((index<0) || (index>this.GetLength()-1)|| (len<0) || (len>this.GetLength()-index)){Console.WriteLine("Position or Length is error!");return null;}StringDS s = new StringDS(this.GetLength() - len);for (int i = 0; i < index; ++i){s[i] = this[i];}for (int i = index + len; i < this.GetLength(); ++i){s[i] = this[i];}return s;}
7、串定位
尋找子串s在主串中首次出現的位置。如果找到,返回子串s在主串中首次出現的位置,否則,返回-1。 串定位的演算法實現如下:
public int Index(StringDS s){if (this.GetLength() < s.GetLength()){Console.WriteLine("There is not string s!");return -1;}int i = 0;int len = this.GetLength() - s.GetLength();while (i < len){if (Compare(s) 0){break;}}if (i <= len){return i;}return -1;}
在C#中,一個String 表示一個恒定不變的字元序列集合。String 類型是封閉類型,所以,它不能被其它類繼承,而它直接繼承自 object。因此,String 是參考型別,不是實值型別,在託管堆上而不是線上程的堆棧上分配空間。String 類型還繼承了 IComparable 、ICloneable 、IConvertible 、IComparable<string> 、IEnumerable<char>、IEnumerable 和IEquatable<string>等介面。String 的恒定性指的是一個串一旦被建立,就不能將其變長、變短或者改變其中任何的字元。所以,當我們對一個串進行操作時,不能改變字串,C#也 提供了 StringBuilder 類型來支援高效地動態建立字串。
在C#中,建立串不能用new 操作符,而是使用一種稱為字串駐留的機制。這是因為 C#語言將 String 看作是基元類型。基元類型是被編譯器直接支援的類型,可以在原始碼中用文本常量(Literal)來直接表達字串。當C#編譯器對原始碼進行編譯時間,將文本常量字串存放在託管模組的中繼資料中。而當 CLR 初始 化時,CLR建立一個空的散列表,其中的鍵是字串,值為指向託管堆中字元 串對象的引用。散列表就是雜湊表。當 JIT 編譯器編譯方法時,它會在散列表中尋找每一個文本常量字串。如果找不到,就會在託管堆中構造一個新的 String 對象(指向字串),然後將該字串和指 向該字串對象的引用添加到散列表中;如果找到了,不會執行任何操作。