在开始播放之前,MediaPlayer对象必须要调用prepared()进入Prepared状态。
要开始播放,必须调用start()方法。当此方法成功返回时,MediaPlayer的对象处于Started状态。
分类: Code
你可不可以
成为我的main函数
做我此生必须有
且只能有一个的入口
——————————
我愿为自己加上private
在你的class中只有
你能调用
——————————————代 码 如 诗 。
【note】the swift programming language Swift教程笔记
// ——————–Swift教程——————————————-
要么变量初始化让其可以推断出类型,要么直接指定一个类型,不可以写:
var a
这样的语句,会让系统不明白a到底是什么类型的变量
允许嵌套多行注释
可以访问不同整数类型的min和max属性来获取对应类型的最小值和最大值
let minValue = UInt8.min
let maxValue = UInt8.max
可以添加额外的0或者下划线来增加数值的可读性,并不影响字面量:
let paddedDouble = 000123.456
let oneMillion = 1_000_000
如果赋值的数值超过了变量或者常量可存储的范围,编译的时候会报错
加号两边的数的类型必须相同,如果不进行类型的转换,无法直接相加
将Double或Float转化为Int的时候,会截断到整数部分,舍弃小数部分
如果在需要使用Bool类型的地方使用了非布尔值,Swift的类型安全机制会报错
这样能够避免错误并保证这块代码的意图总是清晰的。
if i {
}
//这样的语句不被允许,会报错
元组:把多个值组合成一个复合值,元组内的值可以是任意类型,并不要求是相同类型,常用作函数的多个返回值组成一个元组返回
let http404Error = (404, “Not Found”)或者:
let http404Error = (statusCode: 404, description: “OK”)
两种提取元组中元素的方法:
1.
let (statusCode, statusMessage) = http404Error
print(“the status codes is \(statusCode), the status message is \(statusMessage)”)
注意,可以只需要其中一部分的值,不需要的值可用_代替,如:
let (statusCode, _) = http404Error
2.print(“the status code is \(http404Error.0), the statue message is \(http404Error.1)”)
//可选类型
Swift的nil和Objective-C的nil的区别:在Objective-C中,nil是一个指向不存在对象的指针。而在Swift中,nil不是指针,它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为nil,不只是对象类型。
强制解析:当你确定可选类型确实包含值后,可以再可选名字后面加!来获取值,这个!表示我知道这个可选有值,请使用它。
if convertedNumber != nil {
print(“it is \(convertedNumber!).”)
} else {
print(“~~”)
}
也可以这样写,使用可选绑定来判断可选类型是否包含值,如果包含就把值赋给一个临时变量或者变量。
if let actualNumber = Int(possibleNumber) {
print(“actualNumber is \(actualNumber)”)
}
这样转换成功的话actualNumber就能在if下面语句中用,这时候就可以不用写actualNumber的!啦~
//隐式解析可选类型
当可选类型第一次赋值后就可以确定之后一定有值的时候,隐式解析可选类型可以定义时把后面的问号改成感叹号,来声明一个隐式解析可选类型,后面使用它时候就不需要强制拆封了
let possibleString: String! = “djskfjls”
let aString: String = possiableString
// 错误处理
1. 通过枚举类型表示错误
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
2. 抛出一个错误表明有意外情况发生 使用throw关键字
throw VendingMachineError.insufficientFunds(coinsNeed: 5)
3.某个错误被抛出时,附近的某部分代码必须负责处理这个错误
swift有4种错误处理方式:
– 把函数抛出的错误传递给调用此函数的代码
– 用do-catch语句处理错误
– 将错误作为可选类型处理
– 断言此错误根本不会发生
为了表示一个函数、方法或者构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字。一个标有throws关键字的函数叫做throwing函数。
func canThrowErrors() throws -> String
一个throwing函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域
只有throwing函数可以传递错误。任何在某个非throwing函数内部抛出的错误只能在函数内部处理
-+ 把函数抛出的错误传递给调用此函数的代码
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
“Candy Bar”: Item(price: 12, count: 7),
“Chips”: Item(price: 10, count: 4),
“Pretzels”: Item(price: 7, count: 11)
]
var coinsDeposited = 0
func dispenseSnack(snack: String) {
print(“Dispensing \(snack)”)
}
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.InvalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.OutOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price – coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print(“Dispensing \(name)”)
}
}
在vend(itemNamed:)方法的实现中使用了guard语句来提前退出方法,确保在购买某个物品所需的条件中,有任一条件不满足时,能提前退出方法并抛出相应的错误。由于 throw语句会立即退出方法,所以物品只有在所有条件都满足时才会被售出。
throwing 构造器能像 throwing 函数一样传递错误.例如下面代码中的 PurchasedSnack 构造器在构造过程中调用 了throwing函数,并且通过传递到它的调用者来处理这些错误。
struct PurchasedSnack {
let name: String
init(name: String, vendingMachine: VendingMachine) throws {
try vendingMachine.vend(itemNamed: name)
self.name = name
}
}
-+ 用do-catch处理错误
var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
try buyFavoriteSnack(“Alice”, vendingMachine: vendingMachine)
} catch VendingMachineError.InvalidSelection {
print(“Invalid Selection.”)
} catch VendingMachineError.OutOfStock {
print(“Out of Stock.”)
} catch VendingMachineError.InsufficientFunds(let coinsNeeded) {
print(“Insufficient funds. Please insert an additional \(coinsNeeded) coins.”)
}
// 打印 “Insufficient funds. Please insert an additional 2 coins.”
buyFavoriteSnack(person:vendingMachine:)函数在一个try表达式中调用,因为它能抛出错误。如果错误被抛出,相应的执行会马上转移到 catch 子句中,并判断这个错误是否要被继续传递下去。如果没有错误抛出,do子句中余下的语句就会被执行。
-+ 将错误转换成可选值
可以使用try?通过将错误转换成一个可选值来处理错误。如果在评估try?表达式时一个错误被抛出,那么表达式的值就是nil 。例如,在下面的代码中,x和y有着相同的数值和等价的含义:
func someThrowingFunction() throws -> Int {
// …
}
let x = try? someThrowingFunction()
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
如果 someThrowingFunction() 抛出一个错误, x 和 y 的值是 nil 。否则 x 和 y 的值就是该函数的返回值。注 意,无论 someThrowingFunction() 的返回值类型是什么类型, x 和 y 都是这个类型的可选类型。例子中此函数返 回一个整型,所以 x 和 y 是可选整型。
-+ 禁用错误传递(保证这个错误不会发生)
有时你知道某个 throwing 函数实际上在运行时是不会抛出错误的,在这种情况下,你可以在表达式前面写 tr
y! 来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一 个运行时错误。
例如:
let photo = try! loadImage(atPath: “./Resources/John Appleseed.jpg”)
// 指定清理操作
使用defer语句在即将离开当前代码块时候执行一系列语句,该语句让你能执行一些必要的清理操作,不管是 以何种方式离开当前代码块的——无论是由于抛出错误而离开,还是由于诸如 return 或者 break 的语句。例如,你可以用 defer 语句来确保文件描述符得以关闭,以及手动分配的内存得以释放。
延迟执行的操作会按照它们被指定时的顺序的相反顺序执行——也就是说,第一条 defer 语句中的代码会在第二条 defer 语句中的代码被执行之后才执行,以此类推。
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// 处理文件。
}
// close(file) 会在这里被调用,即作用域的最后。
}
}
注意:即使没有涉及到错误处理,你也可以使用 defer 语句。
//类型转换
-+ 检查类型:用类型检查操作符( is )来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回
true ,否则返回 false 。
for item in library {
if item is Movie {
movieCount += 1
} else if item is Song {
songCount += 1
}
}
某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类
型,用类型转换操作符(as? 或 as!)。
条件形式as? 返回一个你试图向下转成的类型的
可选值。强制形式 as! 把试图向下转型和强制解包转换结果结合为一个操作。
当你不确定向下转型可以成功时,用类型转换的条件形式( as? )。条件形式的类型转换总是返回一个可选
值,并且若下转是不可能的,可选值将是 nil 。这使你能够检查向下转型是否成功。 只有你可以确定向下转型一定会成功时,才使用强制形式( as! )。当你试图向下转型为一个不正确的类型
时,强制形式的类型转换会触发一个运行时错误。
在这个示例中,数组中的每一个 item 可能是 Movie 或 Song 。事前你不知道每个 item 的真实类型,所以 这里使用条件形式的类型转换( as? )去检查循环里的每次下转:
for item in library {
if let movie = item as? Movie {
print(“Movie: ‘\(movie.name)’, dir. \(movie.director)”)
} else if let song = item as? Song {
print(“Song: ‘\(song.name)’, by \(song.artist)”)
}
}
注意:转换没有真的改变实例或它的值。根本的实例保持不变;只是简单地把它作为它被转换成的类型来使用。
Swift 为不确定类型提供了两种特殊的类型别名:
• Any 可以表示任何类型,包括函数类型。
• AnyObject 可以表示任何类类型的实例。
var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append(“hello”)
things.append((3.0, 5.0))
things.append(Movie(name: “Ghostbusters”, director: “Ivan Reitman”))
things.append({ (name: String) -> String in “Hello, \(name)” })
注意:
Any 类型可以表示所有类型的值,包括可选类型。Swift 会在你用 Any 类型来表示一个可选值的时候,给你一
个警告。如果你确实想使用 Any 类型来承载可选值,你可以使用 as 操作符显示转换为 Any ,如下所示:
let optionalNumber: Int? = 3 things.append(optionalNumber) // 警告
things.append(optionalNumber as Any) // 没有警告
//扩展
扩展就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能。
这包括在没有权限获取原始源代码的情 况下扩展类型的能力
扩展和 Objective-C 中的分类类似。(与 Objective-C 不同的是,Swift的扩展没有名字。)
使用关键字 extension 来声明扩展:
extension SomeType {
// 为 SomeType 添加的新功能写到这里
}
如果你通过扩展为一个已有类型添加新功能,那么新功能对该类型的所有已有实例都是可用的,即使它们是在这个扩展定义之前创建的。
//协议
协议的定义方式与类、结构体和枚举的定义非常相似:
protocol SomeProtocol {
// 这里是协议的定义部分
}
遵循 多个协议时,各协议之间用逗号( , )分隔:
struct SomeStructure: FirstProtocol, AnotherProtocol {
// 这里是结构体的定义部分
}
拥有父类的类在遵循协议时,应该将父类名放在协议名之前,以逗号分隔:
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
// 这里是类的定义部分
}
// 泛型
泛型代码让你能够根据自定义的需求,编写出适用于任意类型、灵活可重用的函数及类型。它能让你避免代码的
重复,用一种清晰和抽象的方式来表达代码的意图。
泛型函数可以适用于任何类型,下面的 swapTwoValues(_:_:) 函数是上面三个函数的泛型版本:
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107 swapTwoValues(&someInt, &anotherInt)
// someInt 现在 107, and anotherInt 现在 3
var someString = “hello”
var anotherString = “world”
swapTwoValues(&someString, &anotherString)
// someString 现在 “world”, and anotherString 现在 “hello”
//访问控制
Swift 为代码中的实体提供了五种不同的访问级别。这些访问级别不仅与源文件中定义的实体相关,同时也与源 文件所属的模块相关。
• open和public: 开放访问和公开访问可以访问同一模块源文件中的任何实体,在模块外也可以通过导入该模块来访问源文件 里的所有实体。通常情况下,框架中的某个接口可以被任何人使用时,你可以将其设置为开放或者公开访问。
• internal: 内部访问可以访问同一模块源文件中的任何实体,但是不能从模块外访问该模块源文件中的实体。通常情况 下,某个接口只在应用程序或框架内部使用时,你可以将其设置为内部访问。
• fileprivate: 文件私有访问限制实体只能被所定义的文件内部访问。当需要把这些细节被整个文件使用的时候,使用文件私有访问隐藏了一些特定功能的实现细节。
• private: 私有访问限制实体只能在所定义的作用域内使用。需要把这些细节被整个作用域使用的时候,使用文件私有访问隐藏了一些特定功能的实现细节。
通过修饰符 open,public,internal,filepart,private 来声明实体的访问级别:
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}
//溢出运算符
在默认情况下,当向一个整数赋予超过它容量的值时,Swift 默认会报错,而不是生成一个无效的数。这个行为 为我们在运算过大或着过小的数的时候提供了额外的安全性。
然而,也可以选择让系统在数值溢出的时候采取截断处理,而非报错。可以使用 Swift 提供的三个溢出运算符来
让系统支持整数溢出运算。这些运算符都是以 & 开头的:
• 溢出加法 &+
• 溢出减法 &-
• 溢出乘法 &*
【note】Swift初见笔记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
//: Playground - noun: a place where people can play import UIKit // -----------------------Swift初见-------------------------------------- // 简单输出 print("hello, world") // print可以自定义连接符或者自定义结束符 print(1, 2, 3, 4, separator: "-") print(1, 2, 3, 4, terminator: "") print(1, 2, 3, 4, separator: "->", terminator: "->End\n") // let声明常量,var声明变量 let myConstant = 11 var myVariable1 = 42 myVariable1 = 56 // 可以让编译器推断常量或者变量的类型,也可以自己显式指定 var myVariable2:Double = 6 // 值永远的不会被隐式转换为其他类型,必须显式转换 let string1 = "the label is" let integer1 = 94 let string2 = string1 + String(integer1) // 把值转换为字符串的另一种写法 let string3 = "the label is \(integer1)" // 数组和字典都是用[]创建 var list1 = ["apple", "banana", "orange"] list1[2] = "pear" var dic = ["class": "2班", "grade": "1年级"] dic["class"] = "3班" // 创建一个空数组或者字典 let emptyArray = [String]() let emptyDictionary = [String: Float]() // 如果数组或者字典的类型已经被推断出来,就可以用[]或者[:]清空数组或者字典 list1 = [] dic = [:] // for和if后面的条件小括号可以省略,但是语句的大括号不能省略 // Swift3中已经不支持++和--,只能 += 1和 -= 1 // if中必须是布尔表达式,不会隐性和0比较 let list2 = [1, 2, 3, 4] var cnt = 0 for tempitem in list2 { if tempitem < 3 { cnt += 1 } else { cnt -= 1 } } // 用if和let处理值缺失的情况(用可选值) // 如果变量的可选值是nil,条件会判断为false,大括号内的语句不会被执行 var optionalName: String? = nil if let name = optionalName { print("hello, \(name)") } // ?可以规避实例为nil时,调用实例方法报错的现象,因为当实例为nil时候,因为实例是可选类型,所以语句会直接忽略后面的不再执行,故而不会出现异常(也就是说?前面的值为nil时,?后面的操作会被全部忽略) // nil不可以用在不是可选值的常量或者变量中,如果一个常量或者变量可能会没有值,那就必须声明为可选值 // 如果声明了可选值但是没有初始化,它的默认值为nil,如果不是可选值,且没有初始化,可以定义,但是必须初始化后才能使用 var myValue: String? = nil // 如果我们非常确定一个可选值一定有值的话,我们可以用"!"对它进行强制拆包 var myValue2: String? = "hello, everyone!" print(myValue2!) // 另一种处理可选值的方法是通过使用??操作符来提供一个默认值,如果不加??,该变量会输出nil let nickName: String? = nil let fullName: String = "John" print("Hi, \(nickName ?? fullName)") //此时会输出"Hi, John\n" // switch和case支持任何类型的数据,还支持以下方式: let vegetable = "red pepper" switch vegetable { case "apple": print("1") case "banana", "orange": print("2") case let x where x.hasSuffix("pepper"): print("It is a \(x)") default: print("~~~") } // switch语句必须要写default语句,不需要写break语句,因为它匹配成功后就会退出switch语句,不会继续执行 // 使用for-in遍历字典,用两个变量来表示每个键值对,字典里面是一个无序的集合 let dic2 = [ "apple": [1, 2, 3], "orange": [7, 10, 11] ] for (key, values) in dic2 { for value in values { if value > 0 { //balabala... } } } // 使用while或者repeat while语句 var n = 2 while n < 100 { n = n * 2 } repeat { n = n / 2; } while n > 20 // 不包含上界用..< 包含上界用... // 如果不希望print换行就写 print("\(i) ", terminator: "") for i in 0..<4 { print("\(i) ", terminator: "") } for j in 0...4 { print(j) } // 使用func声明函数,使用->指定返回值的类型 func greet(person: String, day: String) -> String { return "Hi, \(person), today is \(day)" } // 我们在写函数的时候,如果不提供参数的标签,那么参数的标签就是参数的名字,我们可以在参数名称前面加上自己想要的文字作为函数的参数标签,如果我们不想使用参数标签的话我们可以在参数名称前面加上"_" // 下面三个语句,分别使用自定义标签、参数名称以及不使用标签 // 内部使用的时候采用参数名称(内部参数名) func myfunc1(name: String, Address adr: String) -> Void { print("My name is \(name), my address is \(adr)") } func myfunc2(name: String, adr: String) -> Void { print("My name is \(name), my address is \(adr)") } func myfunc3( _ name: String, _ adr: String) -> Void { print("My name is \(name), my address is \(adr)") } // 外部调用的时候使用的是参数标签名(外部参数名) myfunc1(name: "John", Address: "1234") myfunc2(name: "John", adr: "1234") myfunc3("John", "1234") // 二进制、八进制、十进制、十六进制 var a1 = 0b100 // 4 var a2 = 0o100 // 64 var a3 = 100 // 100 var a4 = 0x100 // 256 // 十进制指数 var a5 = 1.25e-2 // 0.0125 // 元组:可以将多个类型的值聚合起来: // 注意!元组是用小括号括起来的() ; 数组和字典是用大括号括起来的[] let tuples1 = ("John", 21, 1.78) // 如果想要分解元组可以这样: let (name, age, height) = tuples1 print("my name is \(name), my age is \(age), my height is \(height)") // 如果说只想用name可以用下划线代替想要忽略的值,只指定name变量 let (name2, _, _) = tuples1 print("my name is \(name2)!~~~") // 元组可以使用类似下标的形式访问,不过是以"tuplesName.0" "tuplesName.1" "tuplesName.2"的形式 print("my name is \(tuples1.0) and my age is \(tuples1.1)") // 也可以给元组定义标签,这样就可以直接使用标签的名字进行访问啦~~~ let tuples2 = (name: "TomCat", age:"22") print("hello, my name is \(tuples2.name) and my age is \(tuples2.age)") // 可以用元组来做到让一个函数返回多个值 func myfunc4(scores: [Int]) -> (min: Int, max: Int, sum: Int) { let min = scores[0] let max = scores[1] let sum = 0 return (min, max, sum) } // 函数可以带有可变个数的参数 func func8(arr: Int...) -> Int { var sum = 0 for number in arr { sum += number } return sum } func8() func8(arr: 1, 2, 3) // 函数可以嵌套,被嵌套的函数可以访问外侧函数的变量 func func5() -> Int { var y = 10 func add() { y += 20 } add() return y } // 函数可以作为返回值 func func6() -> ((Int) -> Int) { func func7(number: Int) -> Int { return 1 + number } return func7 } var value6 = func6() //此时value6是func6的返回值类型,func6的返回值类型是一个函数类型,它表示接收一个int类型,返回一个int类型的函数类型 print(value6(7)) // print "8\n" // 函数可以作为参数 // 如下condition就是一个函数类型的参数 func func9(arr: [Int], condition: (Int) -> Bool) -> Bool { for item in arr { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] func9(arr: numbers, condition: lessThanTen) // 闭包 // 函数实际上是一种特殊的闭包,它是一段之后能够被调取的代码 // 可以使用{}创建一个匿名闭包,使用in将参数和返回值类型声明与闭包函数体进行分离 numbers.map({ (number: Int) -> Int in let result = 3 * number return result }) // 更简洁的写法:如果一个闭包的类型已知,比如作为一个回调函数,就可以忽略参数的类型和返回值。单个语句闭包会把它语句的值当作结果返回 let value7 = numbers.map({number in 3 * number}) print(value7) // 可以通过参数的位置而不是参数名字来引用参数 // 如果一个闭包是作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面 // 当一个闭包是传给函数的唯一参数,可以完全忽略括号 let arr2 = numbers.sorted { $0 > $1 } print(arr2) // 使用class来创建一个类 // 使用一个构造函数来初始化类实例,使用init来创建一个构造器 class className1 { var value = 0 var name = "hahaha" init(value: Int) { self.value = value } func func10() -> String { return "A shape with \(value) sides" } } // 创建一个类的实例,不是new不是new不是new!!是在类名后面加括号。 // 使用点来访问实例的属性和方法 var instanceName1 = className1(value: 5) instanceName1.value = 2 var stringName2 = instanceName1.func10() // 子类在后面加上“:父类名字”就能继承自父类~创建类的时候并不需要一个标准的根类,所以可以忽略父类 // 如果要重写父类的方法,必须使用override标记(如果没有添加override就重写父类方法的话编译器会报错)。编译器也同样会检测override标记的方法是否确实在父类中 class className2: className1 { var sideLength: Double init(sideLength: Double, value: Int) { self.sideLength = sideLength super.init(value: value) name = "xixi" } override func func10() -> String { print("lalala~") return name } } // 除了储存简单的属性之外,属性可以有getter和setter class className3 { var sideLength: Double = 2 var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } } var instanceName2 = className3() print(instanceName2.perimeter) instanceName2.perimeter = 8 print(instanceName2.sideLength) // willSet和didSet 在设置一个新值之前或之后运行的代码 class className4 { var age: Int = 0 { willSet { print("we will set an new value \(newValue) to age") } didSet { print("we have changed \(oldValue) to \(age)") } } } var instanceName4 = className4() instanceName4.age = 8 instanceName4.age = 12 // 使用enum创建枚举 enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six case Jack, Queen, King func simpleDescription() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" default: return String(self.rawValue) } } } let ace = Rank.Ace let aceRawValue = ace.rawValue // 使用struct创建结构体。结构体和类相似,比如方法和构造器。结构体是传值,类是传引用 struct Card { var rank = 1 func func11() -> String { return "hello" } } // 使用protocol来声明协议 // mutating 关键字用来标记一个会修改结构体的方法 protocol ExampleProtocol { var value11: Int {get} mutating func adjust() } // 类、枚举和结构体都可以实现协议 // Extension 扩展是给已经存在的类,结构体,枚举类型和协议增加新的功能 // 扩展能够增加新功能,但是不能覆盖已有的功能 // 错误处理 // 定义错误类型: enum PrinterError: Error { case OutOfPaper case NoToner case OnFire } // 使用throw关键字来抛出一个错误、使用throws关键字来表示一个可以抛出错误的函数。 // 如果在函数中抛出一个错误,这个函数会立刻返回并且调用该函数的代码进行错误处理 func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.NoToner } return "Job sent" } // 在do-catch中进行错误处理,使用try标记抛出错误的代码 do { let printerResponse = try send(job: 1440, toPrinter: "Gutenberg") print(printerResponse) } catch PrinterError.OnFire { print("I'll just put this over here, with the rest of the fire") } catch let printerError as PrinterError { print("Printer error: \(printerError).") } catch { print(error) } // 错误处理的另一种方法:使用try? 将结果转换为可选的。如果函数抛出错误,该错误会被抛弃并且结果为nil。否则的话,结果会是一个包含函数返回值的可选值 let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler") // 使用defer代码块表示在函数返回之前,函数中最后会执行的代码 // 泛型 // 可以使用where对参数做出一些约束,比如必须是实现了某一个协议,或者说具有一个特定的父类 |
Swift 3: let sortedNumbers = numbers.sort { $0 > $1 } print(sortedNumbers) 结果显示为()
1 2 |
let sortedNumbers = numbers.sort { $0 > $1 } print(sortedNumbers) |
会发现输出结果为( )
如果改成
1 |
let sortedNumbers: [Int] = numbers.sort { $0 > $1 } |
会出现报错:’sort’ has been renamed to ‘sorted(by:)’
所以知道这段代码应该改为:
1 2 |
let sortedNumbers = numbers.sorted { $0 > $1 } print(sortedNumbers) |
这样才能正确输出结果~
LeetCode 557. Reverse Words in a String III
Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order.
Example 1:
Input: “Let’s take LeetCode contest”
Output: “s’teL ekat edoCteeL tsetnoc”
Note: In the string, each word is separated by single space and there will not be any extra space in the string.
题目大意:将一个字符串的每个单词反转~
分析:将每个单词放入栈中,当遇到空格或者最后一个字符的时候,说明当前栈内为一个完整的单词,那么就将栈内的单词按字符一个个出栈加入result字符串中,根据flag的值判断是否是第一个单词,如果不是第一个单词就要在result的后面加一个空格~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Solution { public: string reverseWords(string s) { string result = ""; stack<char> word; int flag = 0; for (int i = 0; i < s.length(); i++) { if (s[i] != ' ') word.push(s[i]); if (s[i] == ' ' || i == s.length() - 1) { if (flag == 1) result += " "; while (!word.empty()) { result += word.top(); word.pop(); flag = 1; } } } return result; } }; |
蓝桥杯 ALGO-4 算法训练 结点选择
有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?
第一行包含一个整数 n 。
接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。
接下来一共 n-1 行,每行描述树上的一条边。
1 2 3 4 5
1 2
1 3
2 4
2 5
对于20%的数据, n <= 20。
对于50%的数据, n <= 1000。
对于100%的数据, n <= 100000。
权值均为不超过1000的正整数。
分析:题目给出的数据不一定是二叉树,所以可以看作图来处理~其实就是用邻接表存储啦~v[i]数组中保存i结点的孩子节点们~dp[i][0]表示不取i结点的结果~dp[i][1]表示取i结点的结果~
用深度优先搜索+动态规划,每个点的最大权值有取当前这个点和不取当前这个点两种情况~如果取当前点,则不能取与它相邻的任何点;不取当前点,则取与它相邻点的最大值进行累加~从底向上累加到顶部~max(dp[1][0], dp[1][1])就是所求结果~
用一个变量pre保存当前结点的前一个结点~如果等于pre说明访问到了它的父亲结点,为了防止重复访问,要在v[node][i]不等于pre时候继续dfs下去~否则可能会形成无限循环的环~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <iostream> #include <vector> using namespace std; int dp[100010][2]; vector<vector<int> > v; void dfs(int node, int pre) { for (int i = 0; i < v[node].size(); i++) { int temp = v[node][i]; if (temp != pre) { dfs(temp, node); dp[node][0] += max(dp[temp][0], dp[temp][1]); dp[node][1] += dp[temp][0]; } } } int main() { int n, a, b; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &dp[i][1]); v.resize(n + 1); for (int i = 1; i <= n - 1; i++) { scanf("%d%d", &a, &b); v[a].push_back(b); v[b].push_back(a); } dfs(1, 0); cout << max(dp[1][0], dp[1][1]); return 0; } |