控制流, 就是程序中的控制语句, 如 if, switch, for, while 等.但是在 Swift 和 C++中控制流有一些不同.
控制流 | Swift | C++ |
---|---|---|
条件 | if, switch | if, switch |
循环 | for-in ,while,repeat-while | for, 范围 for, while, do-while |
Swift 中条件表达式和循环变量的括号可以省略, 但是大括号必须要写:
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
C++中圆括号是必须要写的, 大括号反而可以省略. 但要注意的是, 大括号括起来的众多语句, 整体表示一条复合语句
, 一个块
; 省略了大括号, 相应的语句体只有一条语句起作用:
#include <iostream>
using namespace std;
int main() {
const int individualScores[5] = {75, 43, 103, 87, 12,};
auto teamScore = 0;
for (auto score : individualScores) {
if (score > 50) {
teamScore += 3;
}else {
teamScore += 1;
}
}
cout << teamScore << endl;
if (teamScore > 10) // 省略了大括号
cout << "teamScore 大于10" << endl; // 此时这里只能写一条语句
else // 省略了大括号
cout << "teamScore 不大于10" << endl; // 此时这里只能写一条语句
return 0;
}
if 语句
Swift 中 if
语句的条件必须是一个布尔表达式. 像if score {....}
编译器会提示出错.
而不像在** C++中 ** score
可以是表达式或变量, 会隐式的转换成布尔类型, 当然前提是这个表达式变量必须能够支持这种转换.
Swift中可以一起使用if
和 let
来处理值缺失的情况. 一个可选值是一个具体的值或者nil
来表示值缺失.在类型后面加一个问号来标记这个变量的值是可选的.
var optionalString: String? = "Hello"
print(optionalString == nil)
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
// 如果变量的可选值是 nil, 条件会判断为 false, 大括号中的代码会被跳过.
// 如果不是 nil, 会将值赋给 let 后面的常量, 这样在代码块中就可以使用这个值了.
if let name = optionalName { // 这里使用 var 也是可以的
greeting = "Hello, \(name)"
}
练习: 把
optionalName
改成nil
,greeting
会是什么?添加一个else
语句,当optionalName
是nil
时给greeting
赋一个不同的值。
另一种处理可选值的方法是通过使用??
来提供一个默认值.如果可选值缺失的话, 可以使用默认值来代替.
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
注意 C++14中添加了可选值
C++中 if
,switch
,while
和for
语句的控制结构内可以定义变量. 定义在控制结构中的变量只在相应的语句的内部可见,一旦语句结束,变量也就超出其作用范围了:
#include <iostream>
using namespace std;
int main() {
if (auto var = 0) // 变量 var 仅在该 `if-else` 语句内部可见
cout << var << endl;
return 0;
}
练习: 在上面的小例子中, 添加一个
else
分支,在大括号中打印var
的值,...else {...}
.
switch 语句
Swift 中switch
支持任意类型的数据以及各种比较操作 —— 不仅仅是整型数以及测试相等。
let vegetable = "red pepper"
switch vegetable { // 关于 switch 你可以探索更多, 比如调换 case 语句的位置.
case "celery":
print("Add some raisins and make ants on a log.") // 运行 switch 中匹配的子句之后, 程序会退出 switch, 并不会继续向下运行, 所以不需要在每个子句结尾写 break.
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"): // 注意此处的 let 中是如何使用的,它将匹配的等式的值赋给常量 x; 此处的 let当然也可以使用 var 代替
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
练习: 删除
default 语句
,看看会有什么错误?
C++中的 switch
语句则不同. switch
括号中的表达式将转换为整型,然后与每个case 标签
的值进行匹配. 从这点上看, C++的 switch
语句功能没有 Swift 的多, 还存在更多的限制 :
#include <iostream>
using namespace std;
int main() {
auto ch = 'a';
switch (ch) {
case 'a':
cout << "ch 为字符 a" << endl;
break;
case 'b':
cout << "ch 为字符 b" << endl;
break;
case 10:
cout << "ch 的值为10" << endl;
break;
default:
cout << "所有的 case 标签都没有被匹配" << endl;
break;
}
return 0;
}
switch
语句会首先对ch
求值, 注意括号中的表达式可以是一个初始化的变量声明. 表达式的值转换成整数类型,然后与每个 case
标签的值比较.
如果表达式和某个 case
标签的值匹配成功,程序从该标签之后的第一条语句开始执行, 知道到达了 switch
的结尾或者是遇到一个 break 语句为止.
break
语句的作用是中断当前的控制流, 通常情况下, switch
常常与 break
一起使用.
case
关键字和它对应的值一起被称为case 标签
. case
标签必须是整形表达式
练习: 尝试删除上面例子中的每个
break
, 会发生什么?
for语句的变式
Swift 中你可以使用for-in
来遍历字典. 此时需要两个变量来表示字典的键值对. 字典是一个无序集合,所以他们的键值对以任意顺序迭代结束.
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
print(largest)
练习: 练习: 添加另一个变量来记录最大数字的种类(
kind
),同时仍然记录这个最大数字的值。
C++中你可以使用范围 for
来遍历序列,当然使用传统的for
语句也可以达到同样的效果:
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, vector<int>> interestingNumbers = {
{"Prime", {2, 3, 5, 7, 11, 13}},
{"Fibonacci", {1, 1, 2, 3, 5, 8}},
{"Square", {1, 4, 9, 16, 25}},
};
// 范围 for 语句遍历序列
for (const auto map_value : interestingNumbers) { // map_value 将是一个 pair 类型的值
cout << map_value.first << ": "; // pair 包含两个数据成员 first 和 second, 使用点语法 . 可以得到它们
for (const auto item : map_value.second)
cout << item << " ,";
cout << endl;
}
// 传统 for语句遍历序列
// interestingNumbers.begin()将得到 map 的开头—— 它是一个迭代器(即指针), interestingNumbers.end()则得到 map 的结尾
for (auto map_value = interestingNumbers.begin(); map_value != interestingNumbers.end(); ++map_value ) {
cout << (*map_value).first << ": "; // 解引用这个迭代器将得到 pair 类型的值
for (auto item = map_value->second.begin(); item != map_value->second.end(); ++item) // 而interestingNumbers 中关键字对应的值是一个 vector, 同样也可以得到它的开头和结尾
cout << *item << " ,"; // 解引用 vector 的迭代器将得到其中的值
cout << endl;
}
return 0;
}
map
是一个有序的不重复的关联数组, 当对map
进行遍历的时候, map_value
将是一个pair
类型的值, pair
包含两个数据成员first
和second
, 使用点语法.
可以得到它们. 其中first
表示 map
中关键字,second
表示map
中关键字所关联的值.
上面例子中, map_value
的second
是一个vector
, 它也是一个序列,可以再次使用范围 for
遍历其中的元素.
而interestingNumbers.begin()
表示调用interestingNumbers
中的begin
成员函数, 它将返回关联数组interestingNumbers
的开头 —— 它是一个迭代器(即指针)
, 关联数组interestingNumbers
的结尾则由end
成员函数表示.
解引用map
的迭代器
得到的是pair
类型的值,所以想要得到里面的键值对,只需要使用点语法即可. 而map_value->second
则等同于(*map_value).second
.
vector
、map
或者其他容器都拥有 begin
、end
成员函数. 不过解引用vector
的迭代器*item
将得到其中的值.
联系: 怎样修改代码才能将打印的结果变为这样:
{
{ Fibonacci, { 1 ,1 ,2 ,3 ,5 ,8 ,} },
{ Prime, { 2 ,3 ,5 ,7 ,11 ,13 , } },
{ Square, { 1 ,4 ,9 ,16 ,25 , } },
}
提示:请手动控制 cout 的输出格式
while、do-while 语句的变式
Swift中可以使用while, repeat-while
来重复运行一段代码知道不满足条件为止. 循环的条件也可以在结尾, 这样可以保证能够至少循环一次.
var n = 2
while n < 100 {
n = n * 2
}
print(n)
var m = 2
repeat {
m = m * 2
} while m < 100
print(m)
你也可以在循环中使用..<
来表示一个范围.
var total = 0
for i in 0..<4 {
total += i
}
print(total)
使用..<
创建的范围包含下界,但不包含上界, 使用...
将包含上界也包含下界 —— 类似数学中的区间[0, 4)
, [0, 4]
.
C++中则可以使用while, do-while
做到同样的目的, 但没有什么快捷的方式创建一个范围. 需要注意的是, 由于 C++中的大括号可以省略, 只能使用一条单独的语句作为循环体; do-while
语句需要在最后写一个分号;
表示语句结束:
#include <iostream>
using namespace std;
int main() {
auto n = 2;
while (n < 100) {
n = n * 2;
} // C++中一对大括号 { } 本身就表示一个复合语句, 一个块. 因此就不必在后面加上分号, 当然加上分号也不影响.
cout << n << endl;
auto m = 2;
do
m = m * 2; // 此处只能用一条单独的语句作为循环体
while (m < 100); // C++中分号 ; 才表示一个语句, 所以此处需要加上分号
cout << m << endl;
}
练习: 分别粘贴下面的代码在 Swift 中运行, 将会得到什么错误提示?
var index: Int
for index = 0; index < 3; ++index {
print("index is \(index)")
}
var index = 0
do {
index += 2
} while index < 100
网友评论