Swift5-外行零基礎(chǔ)入門_6-字符

字符和字符串

本節(jié),我們專門來(lái)講講數(shù)據(jù)類型中的String類型及其操作。

什么是字符和字符串?

簡(jiǎn)單理解,字符就是英文字母,字符串就是多個(gè)英文字母,就是單詞,詞組,或句子。
當(dāng)然,廣義來(lái)說(shuō),所有你能用鍵盤敲出來(lái)的字符,然后用雙引號(hào)""包起來(lái),都是字符或字符串。這里面當(dāng)然也包括中文。
單獨(dú)的字符場(chǎng)景較少,后面我們?yōu)榱朔奖?,統(tǒng)稱為字符串。

操作字符串的意義?

語(yǔ)言是人類信息溝通的重要工具。
對(duì)字符的操作和加工處理是任何一門計(jì)算機(jī)語(yǔ)言的重頭戲。確實(shí),在英文世界中,對(duì)字符串處理的場(chǎng)景更多,但是我們?nèi)匀粫?huì)遇到大量的場(chǎng)景,比如郵箱,號(hào)碼,各類原始數(shù)據(jù)等,都需要進(jìn)行大量的邏輯操作。
我們?cè)谥罢f(shuō)到數(shù)據(jù)類型的時(shí)候,對(duì)各種類型做了一個(gè)總結(jié)表格,還記得嗎?
不記得也沒(méi)有關(guān)系,現(xiàn)在再看一眼:

類型 說(shuō)明 舉例 備注
整型 Int 整數(shù) 1 (32位范圍) -2147483648 到 2147483647
(64位范圍)-9223372036854775808 到 9223372036854775807
浮點(diǎn)型 Float 小數(shù)(32位) 3.14 范圍:1.2E-38 到 3.4E+38 (~6 digits)
Double 小數(shù)(64位) 范圍:2.3E-308 到 1.7E+308 (~15 digits)
布爾值 Bool 真/假 True/False 只有True,F(xiàn)alse這兩個(gè)值
字符串 String 字符 "hello"
可選類型 Optional 有/沒(méi)有

我們重新梳理一下這個(gè)表格:
首先,除去布爾值,可選類型這種特殊的類型;接著,我們把整型和浮點(diǎn)型這兩個(gè)同一稱為數(shù)字型,現(xiàn)在,再看看這個(gè)表格:

類型 說(shuō)明 舉例 備注
數(shù)字型 Int Double 整數(shù) 1,1.2
字符串 String 字符 "hello"

發(fā)現(xiàn)沒(méi)有?計(jì)算機(jī)處理的所有的數(shù)據(jù)類型,就只剩下數(shù)字和字母(文字)了。而我們上一節(jié)講過(guò)的運(yùn)算符,很大程度上是針對(duì)數(shù)字的操作。
現(xiàn)在,就只剩下字母(文字)這個(gè)對(duì)象了!

定義字符串

最簡(jiǎn)單的方式,我們用雙引號(hào)包裹一段字符,賦值給一個(gè)常量或變量,就定義好了一個(gè)字符串。
let someString = "Hello world"
var newString = "I love Swift"

不僅僅是英文字符,數(shù)字,漢字,被包裹后,也是字符串。
let numberString = "100"
let hanString = "你好"
print(type(of: hanString)) // String

如果是多行文字,需要換行,可以使用三引號(hào)包裹""" """

let multiLine = 
  """
  這里可以寫多行文字。
當(dāng)我們打印個(gè)常量時(shí),多行的樣式是保留的。
  English is also available.
  """
print(multiLine)

字符串中的特殊含義

國(guó)王獲得了點(diǎn)石成金的魔力,任何東西被他碰到都會(huì)變成金子,包括他要吃的食物,和他的女兒。
《盜夢(mèng)空間》給了我們一個(gè)方法:找一個(gè)自己的“陀螺”!

剛才我們說(shuō),用雙引號(hào)包裹起來(lái)的都是字符。那么,問(wèn)題就來(lái)了。
假如我真的就是想打印一個(gè)雙引號(hào)"而已,怎么辦?
print(""")這樣嗎?你可以在Playground中試一下,顯然是不行的。
再假如我想打印一個(gè)變量,當(dāng)變量的值改變時(shí),我的打印結(jié)果也自動(dòng)變化。

var someString = "Hello"
print("someString")  // 這樣可以嗎?
print(someString) // 或者這樣呢?

顯然,都是不行的,因?yàn)殡p號(hào)將包裹其中的一切符號(hào)都當(dāng)成了字符。這里的“陀螺”就是反斜杠\。
我們?cè)僭囋嚨谝粋€(gè)例子:print("\""),這樣就正常了,因?yàn)镾wift遇到雙引號(hào)中的\時(shí),就會(huì)特殊對(duì)待,\稱為轉(zhuǎn)義字符,它后面的字符都按照非字符處理。
打印變量的話,可以這樣:

var someString = "Hello"
print("\(someString)")  // 這樣就可以正常顯示,變量值改變,打印結(jié)果也會(huì)變

讓我們繼續(xù)看看還有哪些能轉(zhuǎn)義:
轉(zhuǎn)義字符 \0(空字符)、\\(反斜線)、\t(水平制表符)、\n(換行符)、\r(回車符)、\"(雙引號(hào))、\'(單引號(hào))、\u{Unicode代碼}。
問(wèn)題又來(lái)了,我就是想打印反斜杠\出來(lái),而且我的文字里有好多,還有\n \()什么的一大堆,都想按照原貌出現(xiàn)。好吧,一般情況下,我們給\前面加個(gè)\就可以了,如果覺(jué)得麻煩,可以直接用#來(lái)包裹"。
print(#"Line 1 \nLine 2"#)
上面這段代碼就會(huì)直接打印出Line 1 \nLine 2,中間不會(huì)換行。

訪問(wèn)字符串

定義了字符串之后,我們可以對(duì)字符串進(jìn)行查詢等訪問(wèn)操作。
對(duì)字符串的訪問(wèn)可以分為遍歷,插值,統(tǒng)計(jì),索引,子字符串,比較,檢查前后綴等。

  • 遍歷
    使用for循環(huán),可以遍歷字符串中的每一個(gè)字符。
for i in "Hello" {
    print(i)
}
  • 插值
    我們之前使用過(guò),就是使用\()將變量或常量名放在一串雙引號(hào)中。
let name = "Tom"
let greeting = "Hello \(name)!"
print(greeting)   // Hello Tom!
  • 統(tǒng)計(jì)
    就是統(tǒng)計(jì)一串字符的數(shù)量。
let newString = "Hello world"
print(newString.count) // 11
// 空格也是計(jì)數(shù)的
  • 索引
    我們可以定義一串字符里面的某個(gè)字符的位置,他們可以是第一個(gè)位置string.startIndex,最后一個(gè)位置的后一個(gè)位置string.endIndex,某個(gè)位置之前一個(gè)位置string.index(before: string.endIndex),某個(gè)位置之后的位置string.index(after: string.startIndex),偏離某個(gè)位置n位string.index(string.startIndex, offsetBy: n)。
var a = "Hello"
print(a[a.startIndex])
// H
print(a[a.index(before: a.endIndex)])
// o
print(a[a.index(after: a.startIndex)])
// e
print(a[a.index(a.startIndex, offsetBy: 3)])
// l
print(a[a.index(a.endIndex, offsetBy: -4)])
// e
  • 子字符串
    我們借用前面說(shuō)過(guò)的定位,可以截取字符串的某一段。這么做的意義在于,子字符串是原字符串在內(nèi)存空間的一部分,兩者實(shí)際上是同一塊內(nèi)存空間,這樣效率更高。
let a = "Hello"
// 定義了一個(gè)字符串
let tempIndex = a.index(a.startIndex, offsetBy: 2)
// 定義一個(gè)定位
let subA = a[a.startIndex..<tempIndex]  //還記得區(qū)間運(yùn)算符嗎?
// 通過(guò)類似數(shù)組取值的方式,得到一個(gè)新字符串,它是a字符串的一部分
print(subA)
  • 比較
    字符串怎么比較呢?其實(shí)就是比兩個(gè)字符串是不是相等。這里需要用到我們之前講過(guò)的比較運(yùn)算符,等于==,不等于!=。
let stringA = "Hello there!"
let stringB = "Hello world!"
if stringA == stringB {
    print("兩個(gè)字符串一樣!")
} else if stringA != stringB {
    print("兩個(gè)字符串不一樣!")
}

除了直接比較字符串的完整部分,還可以比較字符串的其中一部分。使用前綴hasPrefix(_:)和后綴hasSuffix(_:)。

// 定義三個(gè)字符串
let stringA = "Hello there!"
let stringB = "Hello world!"
let stringC = "This is another string."
// 定義一個(gè)變量,初始值為零,計(jì)數(shù)用。
var helloCount = 0
// 將三個(gè)字符串組合成一組。
let stringList = [stringA,stringB,stringC]
// 遍歷,并判斷是不是開(kāi)頭含“Hello”。如果有,就給計(jì)數(shù)變量加1.
for i in stringList{
    if i.hasPrefix("Hello") {
        helloCount += 1
    }
}
// 輸出結(jié)果
print("帶有‘Hello’的字符串有\(zhòng)(helloCount)個(gè)。")

加工和編輯字符串

定義,訪問(wèn)字符串變量是不夠的。我們還想對(duì)字符串進(jìn)行加工和編輯。大體上,我們可以對(duì)字符串進(jìn)行拼接,插入,和刪除這幾個(gè)編輯操作。

  • 拼接
    將兩個(gè)字符串直接拼起來(lái)??梢允褂?code>+,+=string.append()。
var stringA = "Hello"
var stringB = " world"
var stringC = "!"
let newString = stringA + stringB
print(newString)
// Hello world
stringA += stringB
print(stringA)
// Hello world
stringA.append(stringC)
print(stringA)
// Hello world!
  • 插入
    結(jié)合我們之前對(duì)字符串做的定位,可以在固定位置插入某個(gè)新字符串,insert(contentsOf:at:),如果是插入單個(gè)字符,可以省略contensOf。
// 定義一個(gè)字符串
var a = "Hello"
// 定義一個(gè)定位
let tempIndex = a.endIndex
// 對(duì)字符串a(chǎn)進(jìn)行insert操作
a.insert(contentsOf:" world", at: tempIndex)
// 打印并驗(yàn)證結(jié)果
print(a)
  • 刪除
    同樣的道理,我們也可以刪除某段字符串。使用remove(at:)刪除某個(gè)位置的那一個(gè)字符,用removeSubrange(_:)刪除某個(gè)區(qū)間的字符。
var a = "Hello!"
a.remove(at: a.index(before: a.endIndex))
print(a)
// Hello
a.removeSubrange(a.index(a.startIndex, offsetBy: 2)..<a.endIndex)
print(a)
// He

小結(jié)與預(yù)告

到這里,我們已經(jīng)講解了關(guān)鍵的數(shù)據(jù)類型:數(shù)字和文字,并使用多種符號(hào)對(duì)它們進(jìn)行各種操作。
還有一種情況,就是將多個(gè)數(shù)字或文字進(jìn)行組合,并操作這個(gè)組合。
下節(jié)見(jiàn)!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容