在本文中,我们将给您介绍关于Swift-控制流的详细内容,并且为您解答swift控制流语句的相关问题,此外,我们还将为您提供关于05-Swift控制流、20190815OnJava8第五章控制流、控制
在本文中,我们将给您介绍关于Swift-控制流的详细内容,并且为您解答swift控制流语句的相关问题,此外,我们还将为您提供关于05-Swift 控制流、20190815 On Java8 第五章 控制流、
Swift-控制流(swift控制流语句)
05-Swift 控制流
01-for in循环
for index in 1...5 {
println("\(index) × 5 = \(index * 5)")
}
var 底数 = 2
var 幂数 = 10
var 结果 = 1
// for in的循环变量可以省略
for _ in 1...幂数 {
结果 *= 底数
}
// 数组的遍历
var 所有学科 = ["语文", "数学", "英语", "物理", "化学"]
for 学科 in 所有学科 {
println(学科)
}
// 字典的遍历
var 所有学科的分数 = ["语文" : 100, "数学" : 110, "英语" : 105, "物理" : 95, "化学" : 90]
for 学科的分数 in 所有学科的分数 {
println(学科的分数)
}
// 字符串的遍历
for 单个字符 in "(*^__^*)" {
println(单个字符)
}
02-for循环
for var index = 1 ; index < 4 ; ++index {
println("\(index) × 3 = \(index * 3)")
}
03-while循环
let 棋盘的格子数 = 25
var 棋盘 = [Int](count: 棋盘的格子数 + 1, repeatedValue: 0)
var 当前格子 = 0
var 色子 = 0
// 云梯
棋盘[3] = 8
棋盘[6] = 11
棋盘[9] = 9
棋盘[10] = 2
// 蛇
棋盘[14] = -10
棋盘[19] = -11
棋盘[22] = -2
棋盘[24] = -8
while (当前格子 < 棋盘的格子数) {
// 模拟随机数
if (++色子 == 7) {
色子 = 1
}
当前格子 += 色子
println("当前格子是\(当前格子)")
// 避免数组越界
if (当前格子 < 棋盘.count) {
var 前进步数 = 棋盘[当前格子]
if (前进步数 > 0) {
println("恭喜你,遇到云梯,前进\(前进步数)步")
} else if (前进步数 < 0) {
println("真倒霉,遇到蛇头,倒进\(-前进步数)步")
}
当前格子 += 前进步数
}
}
println("当前格子是\(当前格子)")
04-do while循环
let 棋盘的格子数 = 25
var 棋盘 = [Int](count: 棋盘的格子数 + 1, repeatedValue: 0)
var 当前格子 = 0
var 色子 = 0
// 云梯
棋盘[3] = 8
棋盘[6] = 11
棋盘[9] = 9
棋盘[10] = 2
// 蛇
棋盘[14] = -10
棋盘[19] = -11
棋盘[22] = -2
棋盘[24] = -8
do {
// 模拟随机数
if (++色子 == 7) {
色子 = 1
}
var 步数 = 棋盘[当前格子]
if (步数 > 0) {
println("遇到云梯,前进\(步数)步")
}
if (步数 < 0) {
println("遇到蛇头,倒进\(步数)步")
}
当前格子 += 步数 + 色子
println("当前格子是\(当前格子)")
} while (当前格子 < 棋盘的格子数)
05-条件语句if
var 分数 = 90
if (分数 > 90) {
println("优秀")
} else if (分数 < 60) {
println("不及格")
} else {
println("良好")
}
06-条件语句switch
var someCharacter :Character = "a"
// switch的条件分支不允许为空
switch someCharacter {
case "a", "e", "i", "o", "u" :
println("\(someCharacter) is avowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z" :
println("\(someCharacter) is consonant")
default :
println("\(someCharacter) is not a vowel")
}
07-条件语句switch的区间匹配
var 分数 = 95
var 评价 : String
switch 分数 {
case 0...59 :
评价 = "不及格"
case 60...79 :
评价 = "及格"
case 80...90 :
评价 = "良好"
case 91...100 :
评价 = "优秀"
default :
评价 = "缺考"
}
08-条件语句switch的元组匹配
var 坐标 = (1, 0)
switch 坐标 {
case (0, 0) : "在原点上"
case (_, 0) : "在X轴上"
case (0, _) : "在Y抽上"
case (-2...2, -2...2) : "在指定的范围内"
default : "不在指定的范围内"
}
09-条件语句switch的值绑定
var 坐标 = (6, 6)
switch 坐标 {
case (var x, 0) : "坐标在X抽上,值是\(x)"
case (0, var y) : "坐标在Y抽上,值是\(y)"
case (var x, var y) : "在X抽上值是\(x),在Y抽上值是\(y)"
}
10-条件语句switch的值绑定where筛选
var 坐标 = (1, -4)
switch 坐标 {
case var (x, y) where (x == y) : "(\(x), \(y))的横坐标和纵坐标相等"
case var (x, y) where (x > 0 && y > 0) : "(\(x), \(y))在第一象限"
case var (x, y) : "坐标(\(x), \(y))"
}
11-控制转移语句continue
var 网址列表 = ["qq.com", "google.hk", "baidu.com", "facebook.com"]
for 网址 in 网址列表 {
switch 网址 {
case var url where (网址.hasPrefix("facebook") || 网址.hasSuffix("hk")) : continue
default : println("即将打开\(网址)")
}
}
12-控制转移语句break
var 网址列表 = [
"developer.apple.com",
"google.com",
"baidu.com",
"qq.com",
"wikipedia.org",
"sf.net",
"github.com",
"jamesonquave.com",
]
for 网址 in 网址列表 {
if (网址.hasSuffix("qq.com")) {
break
}
println(网址)
}
var url = "baidu.com"
var 网址分类 : String?
switch url {
case "developer.apple.com", "wikipedia.org" : 网址分类 = "知识库网站"
case "github.com", "sf.net" : 网址分类 = "源代码网站"
case "jamesonquave.com", "wikipedia.org" : 网址分类 = "技术博客网站"
case "google.com", "baidu.com" : 网址分类 = "资料搜索网站"
default : break
}
if var 类型 = 网址分类 {
println("\(url)是\(类型)")
} else {
println("未分类")
}
13-控制转移语句fallthrough
var 数字 = 3
switch 数字 {
case 1, 3, 5, 7, 9 :
print("\(数字)是1到10之间的奇数")
fallthrough
default :
println(",同时也是一个整数")
}
14-标签语句
let 棋盘的格子数 = 25
var 棋盘 = [Int](count: 棋盘的格子数 + 1, repeatedValue: 0)
var 当前格子 = 0
var 色子 = 0
// 云梯
棋盘[3] = 8
棋盘[6] = 11
棋盘[9] = 9
棋盘[10] = 2
// 蛇
棋盘[14] = -10
棋盘[19] = -11
棋盘[22] = -2
棋盘[24] = -8
// 标签语句
gameloop : while (当前格子 != 棋盘的格子数) {
// 模拟随机数
if (++色子 == 7) {
色子 = 1
}
switch 当前格子 + 色子 {
case 棋盘的格子数 : break gameloop
case var 当前格子数 where (当前格子数 > 棋盘的格子数) : continue gameloop
default :
var 步数 = 棋盘[当前格子]
if (步数 > 0) {
println("遇到云梯,前进\(步数)步")
}
if (步数 < 0) {
println("遇到蛇头,后进\(步数)步")
}
当前格子 += 步数 + 色子
println("当前格子是\(当前格子)")
}
}
20190815 On Java8 第五章 控制流
第五章 控制流
迭代语句
逗号操作符
在 Java 中逗号运算符(这里并非指我们平常用于分隔定义和方法参数的逗号分隔符)仅有一种用法:在 for 循环的初始化和步进控制中定义多个变量。我们可以使用逗号分隔多个语句,并按顺序计算这些语句。注意:要求定义的变量类型相同。
for-in 语法
Java 5 引入了更为简洁的 “增强版 for 循环” 语法来操纵数组和集合。大部分文档也称其为 for-each
语法,但因为了不与 Java 8 新添的 forEach()
产生混淆,因此我称之为 for-in
循环。
for-in 循环适用于任何可迭代(iterable)的 对象。
两种无限循环的形式: for(;;)
与 while(true)
无异,使用哪种完全取决于你的编程品味。
臭名昭著的 goto
随着 Edsger Dijkstra 发表著名的 “Goto 有害” 论(Goto considered harmful)以后,goto 便从此失宠。
Java 中并不支持 goto。然而,在 break 和 continue 这两个关键字的身上,我们仍能看出一些 goto 的影子。它们并不属于一次跳转,而是中断循环语句的一种方法。之所以把它们纳入 goto 问题中一起讨论,是由于它们使用了相同的机制:标签。
对 Java 来说,唯一用到标签的地方是在循环语句之前。进一步说,它实际需要紧靠在循环语句的前方 —— 在标签和循环之间置入任何语句都是不明智的。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环或者一个开关。这是由于 break 和 continue 关键字通常只中断当前循环,但若搭配标签一起使用,它们就会中断并跳转到标签所在的地方开始执行。
在 Java 里需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中 break 或 continue。
在 Dijkstra 的 “Goto 有害” 论文中,他最反对的就是标签,而非 goto。他观察到 BUG 的数量似乎随着程序中标签的数量而增加。标签和 goto 使得程序难以分析。但是,Java 标签不会造成这方面的问题,因为它们的应用场景受到限制,无法用于以临时方式传输控制。由此也引出了一个有趣的情形:对语言能力的限制,反而使它这项特性更加有价值。
switch
每个 case 均以一个 break 结尾。这样可使执行流程跳转至 switch 主体的末尾。这是构建 switch 语句的一种传统方式,但 break 是可选的。若省略 break, 会继续执行后面的 case 语句的代码,直到遇到一个 break 为止。通常我们不想出现这种情况,但对有经验的程序员来说,也许能够善加利用。注意最后的 default 语句没有 break,因为执行流程已到了 break 的跳转目的地。当然,如果考虑到编程风格方面的原因,完全可以在 default 语句的末尾放置一个 break,尽管它并没有任何实际的作用。
switch 字符串
Java 7 增加了在字符串上 switch 的用法。
控制流
本篇博客仅作为笔记,如有侵权,请联系,立即删除(网上找博客学习,然后手记笔记,因纸质笔记不便保存,所以保存到网络笔记)
控制流:C++提供了几种常见的控制流,来满足我们复杂多变的程序设计顺序。
(1)while语句
基本语法:
1 while(condition)
2 statement
while反复的执行statement中的代码,知道condition中的条件判定为false为止。
例:输入一些数,求和
1 #include<iostream>
2
3 using namespace std;
4
5 int main(){
6 int sum = 0;
7 int x = 0;
8
9 while(cin >> x){
10 sum += x;
11 }
12
13 cout << "所求数和为:" << sum << std;
14 system("pause");
15 return 0;
16 }
在Windows系统下,结束输入的组合键是 Ctrl + Z,然后回车。 Linux系统下是 Ctrl + D。 Max OS系统下是 Ctrl + D;
注意:while语句还有一种do while的形式,这种形式下,要注意执行语句至少执行一次。
(2)for语句
基本语法:
1 for(init-statement;condition;expression)
2 statement
每个for语句都包含两个部分:循环头和循环体。循环头控制循环体的执行次数,它由三个部分组成:一个初始化语句(init-statement),一个循环条件(condition)以及一个表达式(expression)。
例:求整数1到99的和。
1 #include<iostream>
2
3 using namespace std;
4
5 int main(){
6 int sum = 0;
7 int x = 0;
8
9 for(int i = 0; i < 100; i++){
10 sum += i;
11 }
12
13 cout << "整数1到99的和为:" << sum << endl;
14
15 system("pause");
16 return 0;
17 }
注意:for语句的初始化语句、循环条件、表达式都是可以省略的。例如for( ; ; ){},相当于while(true){}。所以,for语句使用不当,会造成死循环。
基本语法(范围for语句):
1 for(declaration : expression)
2 statement
declaration定义了一个变量,序列中的每个元素都是能转换成该变量的类型。
expression必须是一个序列。例如可以使数组、vector或者string等对象。
例:
1 #include<iostream>
2 #include<vector>
3
4 using namespace std;
5
6 int main(){
7 vector<int> v = {9,8,7,6,5,4,3,2,1,0};
8
9 for(auto& val : v){
10 val = val * val;
11 }
12
13 for(vector<int>::iterator iter = v.begin(); iter != v.end(); ++iter){
14 cout << *iter << " " << endl;
15 }
16
17 system("pause");
18 return 0;
19 }
(3)if语句
if语句也就是条件语句。其形式为:
1 if(condition)
2 statement
3
4
5 if(condition)
6 statement1
7 else
8 statement2
if语句还支持嵌套,所以我们在使用的时候应该十分注意悬进问题。
例;
1 #include<iostream>
2
3 using namespace std;
4
5 int main(){
6 int currentVal = 0,val = 0;
7
8 if(cin >> currentVal){
9 int count = 1;
10 while(cin >> val){
11 if(val == currentVal){
12 ++count;
13 }
14 else{
15 cout << currentVal << "出现了" << count << "次" << endl;
16 currentVal = val;
17 count =1;
18 }
19 }
20 cout << currentVal << "出现了" << count << "次" << endl;
21 }
22
23 system("pause");
24 return 0;
25 }
(4)switch语句
switch语句提供了一条便利的途径使我们在若干个固定选项中作出选择。其语法为:
1 switch(switch_on)
2 case x1:
3 statement1
4 break;
5 case x2:
6 statement2
7 break;
8 ...
9 default:
10 statementn;
11 break;
注意:不要漏写break,如果漏写break语句会从判定成功的case语句处顺序执行下去。
(5)跳转语句
break;continue;goto;return
break语句负责终止离它最近的while,do while,for或者switch语句,并从这些语句之后的第一条语句开始执行。
continue语句终止离它最近的循环中当前迭代并立即开始下一次迭代。
goto语句的作用是无条件跳转到同一函数的另一条语句,尽量不要再程序中使用该语句,难以修改和难以理解,但是该语句在多层中使用会很有意思(没有使用过)。
return语句终止当前正在执行的函数并将控制权返回给调用该函数的地方
?年学 go 2:控制流
上一篇我们了解了golang 的变量、函数和基本类型,这一篇将介绍一下控制流
现在我们看一个复杂点的例子:
fibonacci(递归版)
package main
import "fmt"
func main() {
result := 0
for i := 0; i <= 10; i++ {
result = fibonacci(i)
fmt.Printf("fibonacci(%d) is: %d\n", i, result)
}
}
func fibonacci(n int) (res int) {
if n <= 1 {
res = 1
} else {
res = fibonacci(n-1) + fibonacci(n-2)
}
return
}
// outputs
fibonacci(0) is: 1
fibonacci(1) is: 1
fibonacci(2) is: 2
fibonacci(3) is: 3
fibonacci(4) is: 5
fibonacci(5) is: 8
fibonacci(6) is: 13
fibonacci(7) is: 21
fibonacci(8) is: 34
fibonacci(9) is: 55
fibonacci(10) is: 89
- for i := 0; i <= 10; i++ {} 第7行是一个循环结构 这里for 循环是一个控制流
控制流
For
Go 只有一种循环接口-- for 循环
For 支持三种循环方式,包括类 while 语法
1 基本for循环 支持初始化语句
s := "abc"
for i, n := 0, len(s); i < n; i++ {
// i, n 为定义的变量 只在for 循环内作用
println(s[i])
}
基本的 for 循环包含三个由分号分开的组成部分:
- 初始化语句:在第一次循环执行前被执行
- 循环条件表达式:每轮迭代开始前被求值
- 后置语句:每轮迭代后被执行
2 替代 while (n > 0) {}
C 的 while 在 Go 中叫做 for
n := len(s)
// 循环初始化语句和后置语句都是可选的。
for n > 0 { // 等同于 for (; n > 0;) {}
println(s[n])
n--
}
3 死循环
for { // while true
println(s)
}
IF…ELSE
就像 for 循环一样,Go 的 if 语句也不要求用 ( ) 将条件括起来,同时, { } 还是必须有的
- 条件表达式必须是布尔类型,可省略条件表达式括号
- 支持初始化语句,可定义代码块局部变量
- 代码块左大括号必须在条件表达式尾部
x := 0
// if x > 10 // Error: missing condition in if statement(左大括号必须在条件表达式尾部)
// {
// }
if x > 10{
...
}else{
...
}
if n := "abc"; x > 0 { // 初始化语句(在这里是定义变量)
println(n[2])
} else if x < 0 {
println(n[1])
} else {
println(n[0]) // 局部变量 n 有效范围是 整个 if/else 块
}
if 语句定义的变量作用域仅在if范围之内(包含else语句)
不支持三元操作符 "a > b ? a : b"
以上是上段代码出现的两个控制流,剩下的控制流还有
- Switch
- Range
- Goto, Break, Continue, defer
Switch
switch 语句用于选择执行,语法如下:
switch optionalStatement; optionalExpression{
case expressionList1: block1
...
case expressionListN: blockN
default: blockD
}
先看一个例子:
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os { // 将 os 与 case 条件匹配
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
case "plan9", "openbsd": // 多个条件命中其一即可(OR)
fmt.Println("plan9 | openbsd")
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
}
- 如果有可选语句声明, 分号是必要的, 无论后边的可选表达式语句是否出现(如果可选语句没有出现默认为true)
- 每一个case 语句必须要有一个表达式列表,多个用分号隔开
- switch 语句自上而下执行,当匹配成功后执行case分支的代码块,执行结束后退出switch
switch i {
case 0: // 空分支,只有当 i == 0 时才会进入分支 相当于 "case 0: break;"
case 1:
f() // 当 i == 0 时函数不会被调用
}
- 如果想要在执行完每个分支的代码后还继续执行后续的分支代码,可以使用fallthrough 关键字达到目的
package main
import "fmt"
func switch1(n int) {
switch { // 这里用的是没有条件的switch 语句会直接执行
case n == 0:
fmt.Println(0)
fallthrough // fallthrough 需放在 case 块结尾,可用 break 阻止
case n == 1: // 如果匹配到0 这里会继续执行
fmt.Println(1)
case n == 2: // fallthrough 不会对这里有作用
fmt.Println(2)
default:
fmt.Println("default")
}
}
func main() {
switch1(0)
}
# output
0
1
- 用 default 可以指定当其他所有分支都不匹配的时候的行为
switch i {
case 0:
case 1:
f()
default:
g() // 当i不等于0 或 1 时调用
}
Range
Range 类似迭代器的操作,返回(索引,值)或(健,值)
它可以迭代任何一个集合(包括字符串、数组、数组指针、切片、字典、通道)
基本语法如下:
coll := 3string["a", "b", "c"]
for ix, val := range coll {
...
}
// 允许返回单值
for ix := range coll {
println(ix, coll[ix])
}
// 也可以使用 _ 忽略
for _, val := range coll {
println(val)
}
// 也可以只迭代,不返回。可用来执行清空 channel 等操作
for range coll {
...
}
val 始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值(译者注:如果 val 为指针,则会产生指针的拷贝,依旧可以修改集合中的原值
一个字符串是 Unicode 编码的字符(或称之为 rune)集合,因此您也可以用它迭代字符串
下面是每种数据类型使用range时 ix和val 的值
date type | ix | value | 值类型 |
---|---|---|---|
string | index | s[index] | unicode, rune |
array/slice | index | s[index] | |
map | key | m[index] | |
channel | element |
range 会复制目标数据。字符串、切片基本结构是个很小的结构体,而字典、通道本身是指针封装,复制成本很小,无需专门优化。如果是数组,可改成数组指针或者切片类型。
Break continue
break 和 continue 都可在多级嵌套循环中跳出
break 可用于 for、switch、select语句,终止整个语句块执行continue 仅能 于 for 循环,终止后续操作,立即进入下一轮循环。
goto
goto 语句可以配合标签(label)形式的标识符使用,即某一行第一个以冒号:
结尾的单词,标签区分大小写。
package main
func main() {
i:=0
HERE:
print(i)
i++
if i==5 {
return
}
goto HERE
}
# output 01234
使用标签和 goto 语句是不被鼓励的:它们会很快导致非常糟糕的程序设计,而且总有更加可读的替代方案来实现相同的需求。
for、switch 或 select 语句都可以配合标签(label)形式的标识符使用
package main
import "fmt"
func main() {
LABEL1:
for i := 0; i <= 5; i++ {
for j := 0; j <= 5; j++ {
if j == 4 {
continue LABEL1
}
fmt.Printf("i is: %d, and j is: %d\n", i, j)
}
}
}
continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置
defer
defer 语句会延迟函数的执行直到上层函数返回
延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
// output
hello
world
defer 栈
延迟的函数调用被压入一个栈中。当函数返回时, 会按照后进先出的顺序调用被延迟的函数调用。
defer 常用来定义简单的方法
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
// 可以想一下会输出什么
// 代码执行 https://tour.go-zh.org/flowcontrol/13
关键字 defer 允许我们进行一些函数执行完成后的收尾工作,例如:
- 关闭文件流:
// open a file defer file.Close()
- 解锁一个加锁的资源
mu.Lock() defer mu.Unlock()
- 打印最终报告
printHeader() defer printFooter()
- 关闭数据库链接
// open a database connection defer disconnectFromDB()
合理使用 defer 语句能够使得代码更加简洁。
下面的代码展示了在调试时使用 defer 语句的手法
package main
import (
"io"
"log"
)
func func1(s string) (n int, err error) {
defer func() {
log.Printf("func1(%q) = %d, %v", s, n, err)
}()
return 7, io.EOF
}
func main() {
func1("Go")
}
// 输出
Output: 2016/04/25 10:46:11 func1("Go") = 7, EOF
更多defer 的用法(https://blog.go-zh.org/defer-panic-and-recover)
参考链接
Go 指南
The way to go -- 控制结构
Effective Go
到这里简单的控制流用法讲解就结束了
下节将会是golang 数据结构部分, 会用到的代码为
fibonacci(内存版)
package main
import (
"fmt"
"time"
)
const LIM = 41
var fibs [LIM]uint64
func main() {
var result uint64 = 0
start := time.Now()
for i := 0; i < LIM; i++ {
result = fibonacci(i)
fmt.Printf("fibonacci(%d) is: %d\n", i, result)
}
end := time.Now()
delta := end.Sub(start)
fmt.Printf("longCalculation took this amount of time: %s\n", delta)
}
func fibonacci(n int) (res uint64) {
// memoization: check if fibonacci(n) is already known in array:
if fibs[n] != 0 {
res = fibs[n]
return
}
if n <= 1 {
res = 1
} else {
res = fibonacci(n-1) + fibonacci(n-2)
}
fibs[n] = res
return
}
最后,感谢女朋友支持和包容,比❤️
想了解以下内容可以在公号输入相应关键字获取历史文章: 公号&小程序
| 设计模式
| 并发&协程
今天关于Swift-控制流和swift控制流语句的介绍到此结束,谢谢您的阅读,有关05-Swift 控制流、20190815 On Java8 第五章 控制流、
本文标签: