官术网_书友最值得收藏!

第3章 萬(wàn)丈高樓平地起——基本操作符

操作符是任何計(jì)算機(jī)語(yǔ)言的最核心部分之一。例如,四則運(yùn)算、求余、邏輯運(yùn)算對(duì)于程序都是非常重要的。在Swift語(yǔ)言中,除了支持常規(guī)的操作符外(任何語(yǔ)言都支持的操作符),還新增加了很多操作符,以及對(duì)部分常規(guī)操作符進(jìn)行了擴(kuò)展(如求余支持浮點(diǎn)數(shù))。本章將詳細(xì)介紹 Swift 支持的最基本,也是最常用的操作符。更復(fù)雜的操作符會(huì)在后面的章節(jié)詳細(xì)討論。

本章要點(diǎn)

□ Swift語(yǔ)言支持哪些操作符

□ 賦值操作符

□ 數(shù)組操作符

□ 復(fù)合賦值操作符

□ 比較操作符

□ 三元條件操作符

□ 區(qū)間操作符

□ 邏輯操作符

3.1 操作符的種類

操作符(Operator,或稱為運(yùn)算符)是所有語(yǔ)言的必需品,Swift也不例外。通常操作符需要和操作數(shù)一同出現(xiàn)。根據(jù)操作數(shù)的個(gè)數(shù),可以分為一元、二元和三元操作符。這里的“元”就是指操作數(shù)。

□ 一元操作符:只有一個(gè)操作數(shù)。例如,符號(hào)(?)、自加 (++)、自減(??)都屬于一元操作符。一元操作符又分為前置和后置一元操作符。這里的前置和后置是指操作符相對(duì)于操作數(shù)的位置。例如,-a中的“-”就是前置操作符,而a++中的“++”就屬于后置操作符。

□ 二元操作符:這類操作符是最常用的,絕大多數(shù)操作符都屬于這類操作符。例如,最常用的加(+)、減( ?)、乘(*)、除(/)就屬于二元操作符。二元操作符是中置的,也就是說(shuō),操作符會(huì)出現(xiàn)中兩個(gè)操作數(shù)之間,例如a + b。

□ 三元操作符:這類操作符可能并不多見(jiàn)。在Swift語(yǔ)言中只有一個(gè)三元操作符,就是三元條件操作符:a?b:c。其中a、b、c是操作數(shù),夾在它們之間(“?”和“:”)的是操作符。

3.2 賦值操作符

賦值操作(a = b)表示用b的值來(lái)初始化或更新a的值,例如,下面是一些標(biāo)準(zhǔn)的賦值操作。

var a = 10

let b = a

b = 10

a = b

如果等號(hào)(=)右側(cè)是一個(gè)元組類型的值,那么等號(hào)左側(cè)也必須是一個(gè)元組形式的變量或常量。而且在賦值的過(guò)程中,右側(cè)元組值中每一個(gè)分量值會(huì)被分別賦給左側(cè)對(duì)應(yīng)的變量或常量。

var (x, y, z) = (1,2,3)

// 現(xiàn)在 x 等于 1, y 等于 2

要注意的是,在C語(yǔ)言和Objective-C中,需要Bool值的地方也可以使用整數(shù)值代替,0表示false,非0表示true。所以下面的代碼在C或Objective-C中是正確的。

int x = 20

int y = 100

if(x = y) // 可以滿足條件

{

... ...

}

對(duì)于 Swift語(yǔ)言來(lái)說(shuō),賦值語(yǔ)句是不返回值的,所以下面的代碼在 Swift語(yǔ)言中是錯(cuò)誤的。

var x = 20

var y = 100

if x = y

{

// 無(wú)法編譯通過(guò),因?yàn)閤 = y不會(huì)返回任何值

}

Swift的這個(gè)特性使你無(wú)法將等于操作符(==)錯(cuò)寫成賦值操作符(=)。盡管像Java這樣的語(yǔ)言可以在一定程度上避免這種錯(cuò)誤(因?yàn)樵贘ava中不能用整數(shù)代替Bool類型值),但如果賦值的變量正好是一個(gè)布爾類型,那么仍然可能錯(cuò)將(==)錯(cuò)寫成(=)。

3.3 數(shù)值操作符

Swift 語(yǔ)言支持標(biāo)準(zhǔn)的四則運(yùn)算操作符,其他數(shù)值操作符還包括整數(shù)求余、浮點(diǎn)數(shù)求余、自增、自減、一元負(fù)號(hào)、一元正號(hào)操作符。本節(jié)將介紹這些操作符的基本使用方法。

3.3.1 四則運(yùn)算操作符

Swift 中所有數(shù)值類型都支持基本的四則運(yùn)算。

□ 加法(+)。

□ 減法(?)。

□ 乘法(*)。

□ 除法(/)。

例如,下面是一些數(shù)值進(jìn)行基本運(yùn)算的例子。

letx= 1+ 2   // x= 3

var y= 5 -3   // y= 2

var abc= 2*3  // abc =6

var c= 10.0 /2.5 // c= 4.0

與 C 語(yǔ)言、Objective-C、Java等語(yǔ)言不同,Swift的數(shù)值默認(rèn)是不允許溢出的。例如,下面的代碼是無(wú)法編譯通過(guò)的。

let x:Byte = 1234 // 1234超出了Byte的取值范圍

var y:Byte = 12*33 // Swift編譯器在編譯時(shí)會(huì)計(jì)算12*33的值,很明顯,它們的乘積超出了Byte的范圍

如果在計(jì)算數(shù)值時(shí)使用的變量、常量或方法(函數(shù))返回的值,即使數(shù)值超出范圍,也是可以編譯通過(guò)的,但執(zhí)行時(shí)會(huì)拋出異常,也就是說(shuō)溢出會(huì)變成一個(gè)運(yùn)行時(shí)錯(cuò)誤。例如,下面的代碼在運(yùn)行時(shí)程序會(huì)中斷。

let x:Byte = 120

var y:Byte = 20 * x  // 執(zhí)行這條語(yǔ)句會(huì)拋出異常

如果需要考慮到溢出的情況,可以使用溢出操作符進(jìn)行運(yùn)算,例如,a &* b。即使 a和b的乘積超出了數(shù)值類型的取值范圍,也會(huì)輸出溢出的結(jié)果。由于Swift中的一些高級(jí)操作符涉及現(xiàn)在還沒(méi)講過(guò)的概念,所以這些高級(jí)操作符(包括溢出操作符)將放到本書的后面講解。

加法(+)運(yùn)算符不僅能用于數(shù)值的相加,也能用于字符和字符、字符和字符串以及字符串和字符串之間的連接。這3種情況下連接的結(jié)果都是字符串。

let c1:Character = "a"

let c2:Character = "b"

var s1:String = c1 + c2 // s1 = "ab"

var s2:String = c1 + s1 // s2 = "aab"

var s3:String = s1 + s2 // s3 = "abaab"

3.3.2 整數(shù)求余

整數(shù)求余(a%b)就是指計(jì)算a最多可以容納多少個(gè)b,最后多出來(lái)那部分就是余數(shù)。例如,9 % 4 = 1,這里1就是余數(shù)。也就是說(shuō),9最多容納2個(gè)4,那么剩余的那個(gè)1就是余數(shù)。

要注意的是,求余操作符(%)在其他語(yǔ)言中又可以稱為取模運(yùn)算。不過(guò)實(shí)際上,%可以對(duì)負(fù)數(shù)進(jìn)行操作,所以“求余”比“取?!笨赡芨线m些。

如果要為求余操作符給出一個(gè)計(jì)算公式的話,那么這個(gè)公式如下。

a = (b ×倍數(shù)) + 余數(shù)

這個(gè)公式也可以是。

余數(shù) = a - (b ×倍數(shù))

如果對(duì)負(fù)數(shù)使用%,那么計(jì)算結(jié)果也是負(fù)數(shù)。例如,?9 % 4 = ?1,如果將這個(gè)表達(dá)式帶入公式,結(jié)果就是。

-9 = ( 4 × -2) + -1

所以余數(shù)是?1。

注意

如果%后面的操作數(shù)(也就是b)為負(fù)數(shù),那么這個(gè)負(fù)號(hào)將被忽略。也就是說(shuō) a % b = a % (-b)。另外,%后面的操作數(shù)如果加負(fù)號(hào),要用圓括號(hào)括起來(lái)。

3.3.3 浮點(diǎn)數(shù)求余

與其他語(yǔ)言不同,Swift是可以對(duì)浮點(diǎn)數(shù)求余的。例如,8.5 % 2.5 = 1.0。浮點(diǎn)數(shù)求余也可以使用整數(shù)求余的公式。如果將這個(gè)表達(dá)式代入公式的結(jié)果是。

8.5 = (2.5 × 3) + 1.0

3.3.4 自增和自減

和C語(yǔ)言一樣,Swift也提供了使變量增1和減1的操作符。自增使用兩個(gè)加號(hào)(++),自減使用兩個(gè)減號(hào)(??)。不過(guò)和C語(yǔ)言不同的是操作數(shù)可以是整數(shù),也可以是浮點(diǎn)數(shù)。

和C語(yǔ)言一樣,Swift 也提供了方便對(duì)變量本身加1或減1的自增(++)和自減(??)的運(yùn)算符。其操作對(duì)象可以是整形和浮點(diǎn)型。

自增和自減還分為前自增、后自增;前自減、后自減。這里的前和后是指自增和自減操作符相對(duì)于操作數(shù)的位置。前自增和前自減操作符位于操作數(shù)前面,例如,++a、??b。后自增和后自減操作符位于操作數(shù)后面,例如,a++、b??。它們的區(qū)別是當(dāng)操作符位于操作數(shù)前面時(shí),先自加或自減,然后再返回變量值。當(dāng)操作符位于操作數(shù)后面時(shí),先返回變量值,然后再自加或自減。

var i = 1

var v = ++i // v = 2

var m = v++ // m = 2

var x = 2.5

x = ++x  // x = 3.5

x = x++  // x = 3.5

盡管單獨(dú)增加和減少變量值時(shí)使用++a、a++、??a和a??都可以。但推薦使用++a和??a,因?yàn)樵诜祷刈兞恐抵跋仍?或減1更符合邏輯。

3.3.5 一元負(fù)號(hào)和正號(hào)

數(shù)值的正負(fù)號(hào)可以使用前綴?(即一元負(fù)號(hào))來(lái)切換。

let three= 3

letminusThree= -three   // minusThree等于 ?3

letplusThree= -minusThree // plusThree等于 3

要注意的是一元負(fù)號(hào)(?)需要寫在操作數(shù)之前,與操作數(shù)之間沒(méi)有空格。

一元正號(hào)(+)不做任何改變地返回操作數(shù)的值。使用規(guī)則與一元負(fù)號(hào)相同。盡管一元正好做的是無(wú)用功,但當(dāng)使用一元負(fù)號(hào)表示一個(gè)負(fù)數(shù)時(shí),使用一元正號(hào)表示正數(shù)會(huì)使你的代碼更容易閱讀,當(dāng)然,對(duì)于某些審美能力很強(qiáng)的人來(lái)說(shuō),會(huì)看出代碼之美。

3.4 復(fù)合賦值操作符

復(fù)合賦值(Compound Assignment)就是指將其他操作符和賦值操作符組合在一起使用,例如+=、?=都屬于復(fù)合賦值操作?;旧蠈儆贑風(fēng)格的語(yǔ)言(Java、C#、C++等)都支持這類操作符。

我們也可以將復(fù)合賦值操作符看著是兩個(gè)操作數(shù)進(jìn)行運(yùn)算并賦值的簡(jiǎn)寫形式,例如,a += b相當(dāng)于a = a + b。

var a = 1

a += 2 //相當(dāng)于a = a + 2,所以a等于 3

注意

符合賦值運(yùn)算沒(méi)有返回值,也就是說(shuō),let b = a += 2 是錯(cuò)誤的寫法。

3.5 比較操作符

所有在標(biāo)準(zhǔn)C語(yǔ)言中的比較運(yùn)算都可以在Swift中使用。

□ 等于(a == b)。

□ 不等于(a != b)。

□ 大于(a > b)。

□ 小于(a < b)。

□ 大于等于(a >= b)。

□ 小于等于(a <= b)。

注意

在 Swift 語(yǔ)言中還支持恒等(3 個(gè)等號(hào),===)和不恒等(一個(gè)感嘆號(hào)和兩個(gè)等號(hào),!==)兩個(gè)比較操作符。這兩個(gè)操作符用來(lái)判斷兩個(gè)對(duì)象是否引用了同一個(gè)對(duì)象實(shí)例。更多關(guān)于這兩個(gè)操作符的細(xì)節(jié),將在后面介紹類和結(jié)構(gòu)體時(shí)詳細(xì)討論。

每一個(gè)比較操作符都返回一個(gè)Bool類型的值,所以,比較操作符會(huì)經(jīng)常用于if語(yǔ)句中,關(guān)于if語(yǔ)句的細(xì)節(jié)會(huì)在后面的章節(jié)中詳細(xì)討論。

下面是一些使用比較操作符的例子。

1 == 1 // true,因?yàn)?1 等于 1

2 != 1 // true,因?yàn)?2 不等于 1

2 > 1 // true, 因?yàn)?2大于 1

1 < 2 // true, 因?yàn)?1小于2

1 >= 1 // true,因?yàn)?1 大于等于 1

2 <= 1 // false,因?yàn)?2 并不小于等于 1

let name = "bill"

if name == "world" // 此處條件為false

{

println("yes")

}

else     // 此處條件為true

{

println("no")

}

3.6 三元條件操作符

Swift中只有一個(gè)三元操作符。操作符的原型如下。

邏輯表達(dá)式?為true時(shí)的答案:為false時(shí)的答案

其實(shí)三元條件操作符和前面介紹的復(fù)合賦值操作符一樣,也是為了簡(jiǎn)化表達(dá)式而存在的,所以并不是必須的,但使用該操作符卻能提升程序的開(kāi)發(fā)效率,使程序看起來(lái)更美觀。

三元條件操作符實(shí)際上是簡(jiǎn)化了下面的代碼。

if 邏輯表達(dá)式

{

為true時(shí)的答案

}

else

{

為false時(shí)的答案

}

下面是一個(gè)實(shí)際的例子,在該例子中分別演示了不使用三元邏輯操作符和使用三元邏輯操作符的情況。

var value:Int

var flag:Bool = true

// 不使用三元邏輯操作符的情況

if flag

{

value = 1

}

else

{

value = 2

}

// 使用三元邏輯操作符的情況

value = (flag ? 1 : 2)

3.7 區(qū)間操作符

區(qū)間操作符可以非常方便地確定一個(gè)區(qū)間,通常是一個(gè)數(shù)值的區(qū)間。并且可以枚舉這個(gè)區(qū)間中的每一個(gè)值。盡管區(qū)間操作符用起來(lái)很方便,但并不是所有的語(yǔ)言都支持區(qū)間操作符,對(duì)于靜態(tài)語(yǔ)言來(lái)說(shuō),Pascal 是支持區(qū)間操作符的。不過(guò)幸好 Swift 也支持區(qū)間操作符,這將會(huì)給我們編寫代碼帶來(lái)很多方便。

區(qū)間操作符分為閉區(qū)間操作符和半開(kāi)半閉操作符。閉區(qū)間操作符使用3個(gè)點(diǎn)(...)表示,該操作符包含了區(qū)間兩端的值。而半開(kāi)半閉操作符使用兩個(gè)點(diǎn)加一個(gè)小于號(hào)(..<)表示 當(dāng) Swift 語(yǔ)言剛出來(lái)時(shí)半開(kāi)半閉操作符使用兩個(gè)點(diǎn)(..)表示??赡苡刑嗳私o Apple 提意見(jiàn)。大概意思就是我的鍵盤反應(yīng)太靈敏了,手指抬起得慢點(diǎn)就會(huì)多按一個(gè)點(diǎn),你這樣很容易造成錯(cuò)誤,而且會(huì)產(chǎn)生史上最難排除的Bug。所以當(dāng)XCode 6 Beta3出來(lái)時(shí),就將“..”改成了“..<”。估計(jì)以后是不會(huì)變了。 ,該操作符左側(cè)端點(diǎn)的值會(huì)被包含,但不包含右側(cè)端點(diǎn)的值。

區(qū)間操作符在使用for-in循環(huán)枚舉數(shù)組或字典中元素時(shí)非常有用。

let names = ["Anna", "Alex", "Brian", "Jack"]

let count = names.count

// i會(huì)從0循環(huán)到count – 1

for i in 0..<count

{

println("第 \(i + 1) 個(gè)人叫 \(names[i])")

}

執(zhí)行上面的代碼,會(huì)輸出如下的結(jié)果。

第 1 個(gè)人叫 Anna

第 2 個(gè)人叫 Alex

第 3 個(gè)人叫 Brian

第 4 個(gè)人叫 Jack

當(dāng)然,我們還可以使用閉區(qū)間對(duì)數(shù)值進(jìn)行循環(huán)。

for i in 1...5

{

print("index = \(i) ")

}

執(zhí)行上面的代碼,會(huì)輸出如下的內(nèi)容。

index = 1 index = 2 index = 3 index = 4 index = 5

注意

經(jīng)測(cè)試發(fā)現(xiàn),區(qū)間操作符是可以使用浮點(diǎn)數(shù)的,例如,1...1.2,不過(guò)使用浮點(diǎn)數(shù)會(huì)使Swift程序員不好處理。讀者自己測(cè)試下就知道了,如果使用 for-in語(yǔ)句,會(huì)無(wú)限循環(huán)下去,每次都會(huì)輸出很大的數(shù)。這可能是因?yàn)镾wift最開(kāi)始確定的開(kāi)發(fā)理念是盡可能滿足更多的表達(dá)方法,估計(jì)是能用浮點(diǎn)數(shù)的都可以使用浮點(diǎn)數(shù)了(如求余)。但可能還沒(méi)考慮全(編譯器未實(shí)現(xiàn)完整),所以在對(duì)區(qū)間操作符使用浮點(diǎn)數(shù)時(shí),就會(huì)出現(xiàn)無(wú)法預(yù)料的結(jié)果,大家還是別用浮點(diǎn)數(shù)了。如果要真用浮點(diǎn)數(shù),Swift最好用步長(zhǎng)之類的東西。否則沒(méi)法循環(huán)了。

3.8 邏輯操作符

邏輯運(yùn)算的操作對(duì)象是邏輯布爾值。Swift支持基于C語(yǔ)言的3個(gè)標(biāo)準(zhǔn)邏輯運(yùn)算。

□ 邏輯非(!a)。

□ 邏輯與(a && b)。

□ 邏輯或(a || b)。

3.8.1 邏輯非

邏輯非運(yùn)算(!a)對(duì)一個(gè)布爾值取反,使得true變?yōu)閒alse,或使false變?yōu)閠rue。

邏輯非是一個(gè)前置操作符,需出現(xiàn)在操作數(shù)的前面,并且操作符和操作數(shù)之間不能加空格。讀作“非 a”或“對(duì)a取反”,現(xiàn)在來(lái)看下面的例子。

let allowed = false

if !allowed

{

println("allowed")

}

else

{

println("denied");

}

執(zhí)行這段代碼后,會(huì)輸出“allowed”。

3.8.2 邏輯與

邏輯與(a && b)表達(dá)了只有a和b的值都為true時(shí),整個(gè)表達(dá)式的值才會(huì)是true。只要任意一個(gè)值為false,整個(gè)表達(dá)式的值就為false。事實(shí)上,如果第一個(gè)值為false,那么是不去計(jì)算第二個(gè)值的,因?yàn)樗呀?jīng)不可能影響整個(gè)表達(dá)式的結(jié)果了。這被稱做“短路計(jì)算(short-circuit evaluation)”。

在下面的例子中,只有兩個(gè)Bool值都為true值的時(shí)候才會(huì)執(zhí)行if語(yǔ)句中的代碼,否則會(huì)執(zhí)行else中的代碼。

let entered = true

let passed = false

if entered && passed

{

println("Welcome!")

}

else

{

println("ACCESS DENIED")

}

在執(zhí)行上面的代碼后,會(huì)輸出“ACCESS DENIED”

3.8.3 邏輯或

邏輯或(a || b)是一個(gè)由兩個(gè)連續(xù)的“|”組成的中置運(yùn)算符。它表示了兩個(gè)邏輯表達(dá)式的其中一個(gè)為true,整個(gè)表達(dá)式就為true。

同邏輯與運(yùn)算類似,邏輯或也是“短路計(jì)算”的,當(dāng)左端的表達(dá)式為true時(shí),將不計(jì)算右邊的表達(dá)式了,因?yàn)樗豢赡芨淖冋麄€(gè)表達(dá)式的值了。

在下面的代碼中,第一個(gè)布爾值(hasKey)為 false,但第二個(gè)值(knowsPassword)為 true,所以整個(gè)表達(dá)是true,于是允許進(jìn)入:

let hasKey = false

let knowsPassword = true

if hasKey || knowsPassword

{

println("Welcome!")

}

else

{

println("ACCESS DENIED")

}

執(zhí)行這段代碼后,會(huì)輸出“Welcome!”。

3.8.4 組合邏輯

我們可以組合多個(gè)邏輯運(yùn)算來(lái)表達(dá)一個(gè)復(fù)合邏輯。

if entered && passed || hasKey || knowsPassword

{

println("Welcome!")

}

else

{

println("ACCESS DENIED")

}

執(zhí)行這段代碼后,會(huì)輸出“Welcome!”。

如果只是簡(jiǎn)單地將邏輯操作符組合在一起,那么系統(tǒng)會(huì)從左到右依次計(jì)算,例如,對(duì)于這段代碼來(lái)說(shuō),會(huì)先計(jì)算“entered && passed”,然后用計(jì)算結(jié)果與hasKey進(jìn)行邏輯或,最后再用邏輯或的結(jié)果與knowsPassword進(jìn)行邏輯或。

3.8.5 使用圓括號(hào)指定優(yōu)先級(jí)

對(duì)于一個(gè)復(fù)雜的表達(dá)式,可能需要指定先運(yùn)算那一對(duì)操作數(shù),這就要使用圓括號(hào)來(lái)確定優(yōu)先級(jí)。例如,下面的表達(dá)式就會(huì)先將passed和hasKey進(jìn)行邏輯或,然后再與entered邏輯與,最后與knowsPassword邏輯或。

if entered&&(passed || hasKey) || knowsPassword

{

println("Welcome!")

}

else

{

println("ACCESS DENIED")

}

執(zhí)行這段代碼后,會(huì)輸出“Welcome!”。

如果邏輯表達(dá)式比較復(fù)雜,建議使用圓括號(hào)指定優(yōu)先級(jí),這樣不僅不易出錯(cuò),而且也增加了程序的可讀性。

3.9 小結(jié)

盡管 Swift 語(yǔ)言支持的大多數(shù)操作符和其他語(yǔ)言類似,但對(duì)于剛?cè)腴T的程序員來(lái)說(shuō),最好仔細(xì)閱讀本章的內(nèi)容。因?yàn)?,如果?duì)這些基本的操作符不了解或不能熟練使用的話,會(huì)在以后的學(xué)習(xí)和工作中遇到很大的困難。當(dāng)然,對(duì)于已有多年工作經(jīng)驗(yàn)的讀者來(lái)說(shuō),只需要看一下Swift特有的操作符(如區(qū)間操作符)即可,其他內(nèi)容可直接跳過(guò)。

主站蜘蛛池模板: 聂荣县| 卓尼县| 玛纳斯县| 宝山区| 库车县| 柘城县| 泽普县| 大城县| 永城市| 宁晋县| 介休市| 阜南县| 石渠县| 新和县| 贡山| 海原县| 姜堰市| 宣恩县| 巴东县| 正阳县| 广昌县| 启东市| 霍州市| 定州市| 白河县| 思茅市| 邛崃市| 贺兰县| 苍梧县| 博白县| 兰考县| 伊春市| 晋宁县| 上犹县| 连南| 来宾市| 杨浦区| 石阡县| 湖南省| 洛扎县| 富阳市|