第 6 講:數(shù)據(jù)類型(三):字符和字符串
字符和字符串是 C# 里廣泛使用的一種專用表示“只用來呈現(xiàn)原封不動的數(shù)據(jù)”的數(shù)據(jù)類型。字符是 char
關(guān)鍵字表示的,它的 BCL 名稱是 System.Char
,表示一個單獨的字符;而字符串是表示一系列字符構(gòu)成的序列,用 string
關(guān)鍵字表示,它的 BCL 名稱是 System.String
。
下面我們來看一下基本的賦值方式和書寫格式。
Part 1 字符字面量和字符串字面量
我們先來說字符。字符就是一個單獨的原始數(shù)據(jù)。
C# 里使用單引號來表達(dá) a
是一個字符。
當(dāng)然,一個數(shù)字字符和一個數(shù)字是有區(qū)別的。比如說 '3'
和 3
雖然,如下的寫法都是可以輸出一個字符 3 的:
和 C 語言不同,C# 的字符是包含中文漢字、日語假名等等符號的。比如說:
在 C 語言里,一個字符是只占一個字節(jié)的,因此它只能表達(dá)一個很簡單的字符;漢字、日文甚至別的一些符號并不屬于標(biāo)準(zhǔn) ASCII 碼里的內(nèi)容,因此無法用一個字符來表示。但 C# 里是可以的。
這就是為什么,字符沒辦法參與計算了。
順帶一說,這里以單引號引起來的內(nèi)容稱為字符字面量(Character Literal)。
Part 2 字符串字面量
顯然,一個單獨的字符并不能表達(dá)很多的信息,因此大多數(shù)時候我們都會使用字符串(String)來表示一個字符序列,以達(dá)到描述復(fù)雜信息的功能。
字符串字面量(String Literal),當(dāng)然,有些時候也簡稱字符串或者串。
C# 貼心地為我們提供了 Console.WriteLine
方法,可以讓我們使用前面的所有類型,全部內(nèi)嵌到小括號里參與輸出,因此,這些字符串依然可以寫進(jìn)去。
空字符串
這樣的話,emptyString
就是一個空的字符串,里面沒有任何字符。當(dāng)然,空字符串你也可以寫成 String.Empty
或 string.Empty
前文稍微提到過,
string
是關(guān)鍵字,而String
是 BCL 名稱。它們的區(qū)別僅僅是“BCL 名需要引入System
Part 3 原義字符串和轉(zhuǎn)義字符
由于雙引號在編程的時候有特殊用途(表示字符串字面量的開頭和結(jié)尾),所以很明顯,我們并不能在字符串字面量里使用引號。如果偏要輸出引號的話,我們必須在左邊添加反斜杠:\"
。這個行為稱為轉(zhuǎn)義(Escape)。那么理所應(yīng)當(dāng)?shù)?,這里帶反斜杠的字符就是轉(zhuǎn)義字符(Escape Character)了。
在 C 語言里,
\"
和\'
都是轉(zhuǎn)義字符,即雙引號里不可以直接出現(xiàn)單引號;但 C# 里是允許的。
轉(zhuǎn)義字符除了上面說的雙引號以外,還有一些別的。比如說制表符。制表符占據(jù) 8 個空格的空間。如果是寫入字符串的時候,我們可以直接插入制表符:“ ”,但這樣顯得很不正常,因此 C# 里提供了一個字符寫法:\t
,這就表示一個制表符:
最后,由于反斜杠本身作為轉(zhuǎn)義字符的開始,因此我們單純要輸出一個反斜杠的時候,必須雙寫它。
我們目前就只需要接觸這幾個就可以了。后續(xù)用到新的轉(zhuǎn)義字符的時候,我們再作出說明。
但是有些時候,我們要寫一大段的文字(很有可能自帶換行)。這個時候,字符串怎么寫呢?我們采用的辦法是通過原義字符串(Verbatim String)來搞定。
為了避免字符串里出現(xiàn)的特殊字符,C# 提供了一種字符串:
如果是一個很普通的字符串,就必須雙寫反斜杠來表示一個反斜杠字符。當(dāng)我們在字符串最開頭追加原義標(biāo)記 @
后,字符串就成了原義字符串。原義字符串的內(nèi)部除了雙引號以外的其它所有字符都可以隨便用了:不管你怎么寫,原義字符都不作處理。
\"
這種寫法會失效。所以,此時用到的是雙寫:""
。我們雙寫雙引號,就表示原義字符串里的一個雙引號字符。
總結(jié)一下:
普通字符串里,
\\
表示一個反斜杠字符,\"
表示一個雙引號字符,\t
?表示制表符(還有別的,這里不作介紹);原義字符串里,
""
表示一個雙引號字符。
Part 4 字符串的長度
由于字符串是不定長的,因此它擁有長度(Length)的概念。字符串可以很長,它的長度是所有字符的總數(shù)。比如說,"こんにちは、お元気ですか。"
字符串里,有 9 個假名、2 個日語漢字和 2 個標(biāo)點符號,因此長度是 13。
當(dāng)然了,空字符串長度為 0,這個是不用多說的。
Part 5 字符串的基本操作
說起字符串,就不得不提一下字符串的基本操作。
不得不說,這些內(nèi)容有點超綱,但是既然重要我們就得先說。超綱內(nèi)容也不一定難,可能僅僅就是超前說明而已。
5-1 獲取字符串長度
我們直接使用 .Length
的語法來表示和獲取字符串的具體長度:
這樣的話,輸出和顯示的就是 s.Length
這個東西。s
是字符串,后直接跟上 .Length
則會得到字符串的長度。前文說過,字符串的長度就是所有字符總數(shù),因此這個字符串是 10 個字符,因此結(jié)果是 10,輸出的內(nèi)容也是 10。
順帶一提,
s.Length
的結(jié)果是一個數(shù)字,那么它會是什么類型的呢?對了,int
類型的。因為int
在 C# 里起到很重要的作用,因此很多地方都會使用int
,即使我們知道長度是不可能為負(fù)數(shù)的,按道理應(yīng)該用uint
,但因為為了兼容性(底層,比如說和 C 語言以及別的沒有無符號數(shù)據(jù)類型的語言進(jìn)行交互的時候),int
是最合適的一種類型。
5-2 獲取特定位置上的字符
我們采用類似 C 語言的中括號語法,可以獲取一個字符串里指定位置上的字符是什么。
[]
語法來確定和獲取 s
字符串里的字符信息。中括號的數(shù)字是 n,那么就取的是第 (n + 1) 個字符。換句話說,n 最小是 0,而不是 1。
這個例子里,s[3]
就相當(dāng)于取的是 s
這個字符串里的第四個字符('l'
),因此,c
變量得到的結(jié)果就是 'l'
,最后輸出的也是這個字符。
但請注意,你不能修改字符串的內(nèi)容。雖然 C 語言里,你可以使用索引器來接受一個字符,以達(dá)到修改的目的,但 C# 里,整個字符串一旦聲明后,就無法修改:
5-3 拼接字符串
有些時候我們可能需要拼接多個字符串,然后把這些字符串合并成一個字符串。我們需要用到的是一個叫 Concat
的方法。
這個例子應(yīng)該比較好理解。我們使用 string.Concat
方法,把所有需要拼接在一起的字符串挨個順次寫進(jìn)去,用逗號隔開;然后最后得到的結(jié)果就是整體的結(jié)果了。此時,用 result
變量接受結(jié)果。顯示出來就是 Hello, Mike!
。
5-4 查看字符串是不是包含一個字符或字符串
如果一個字符串較長,我們可能會去查找里面的字符。比如說一個電話號碼(用字符串表示后),我們需要查看是不是包含 666 這個序列。那么,我們可以這么寫:
我們在字符串字面量(或變量)的后面追加 .Contains("666")
bool
的結(jié)果,賦值給 contains666
變量。
看到了吧,這里就用上了
bool
類型。
當(dāng)然,小括號里不一定非得是序列,也可以是一個單獨的字符:
5-5 查看字符串開頭和結(jié)尾是不是固定的序列
如果我們要查看一個用字符串表達(dá)的電話號碼里是不是以 13 開頭的話,我們需要追加 .StartsWith("13")
來表示:
同理,如果要看字符串結(jié)尾是不是固定的序列,則使用 .EndsWith(序列)
表示:
這個依然也可以判斷一個單獨的字符:
5-6 比較字符串的具體序列是不是完全一樣
如果要比較字符串是不是完全一致的話,我們用的是 string.Equals
:
5-7 查看字符串里指定字符(或字符串序列)的具體位置
.IndexOf(內(nèi)容)
。
5-8 刪掉一個字符或字符串
要想把字符串里的一部分完整序列去掉,我們用的是 .Remove(位置)
。
這表示從第 3 個位置的字符開始,后面的字符我們都不要了。所以 t
變量的結(jié)果是 "He"
。
.Remove(2, 2)
表示從第 3 個字符開始刪,刪掉 2 個字符。所以最后 t
結(jié)果是 "Heo"
。
要想替換掉序列的話,我們可以用 .Replace(字符, 字符)
或 .Replace(字符串, 字符串)
。
u
變量結(jié)果自然就是 "今兒天氣好"
這樣就變成了 "明兒天氣好"
了。
要想取一部分字符,我們用 .Substring(開始位置, 取的長度)
來獲取:
t
從第 1 個字符開始取,取 4 個字符,所以 t
結(jié)果是 "Hell"
。
Part 6 不可變的字符串
我們看到前面的這些操作,我們發(fā)現(xiàn)共同點:我們發(fā)現(xiàn)怎么去操作字符串,最后原始的字符串都是沒有變動的:即使要修改字符串,變動的結(jié)果也會通過賦值給到新的變量上去,但原始的字符串并沒有變化。這是 C# 里字符串的一大特殊性質(zhì):不可變(Immutable)。
比如這個例子,我們已經(jīng)刪掉了 s
的字符,但代碼運行起來后,我們可以看到的是,s
還是 "Hello"
,而 t
才是 "He"
。
Part 7 總結(jié)
本節(jié)我們學(xué)習(xí)了字符和字符串的內(nèi)容,以及操作。再怎么說,我們都不必考慮類似 C 語言那樣字符串操作的復(fù)雜細(xì)節(jié)。所以從這個角度來說,C# 還是比較簡單的。