本章我们将讨论流控制,我们将定义几个关键字,这些关键字使我们能够控制 Ruby 程序的流程。
条件和循环会改变 Ruby 程序的流程。 条件语句是在特定条件下执行特定语句的关键字。 循环是多次执行的程序块。 当程序运行时,语句从源文件的顶部到底部执行。
Ruby if
语句
if
关键字用于检查表达式是否为真。 如果为 true,则执行一条语句。 该语句可以是单个语句或复合语句。 复合语句由该块包围的多个语句组成。 块是由end
关键字括起来的代码。 then
关键字是可选的。
#!/usr/bin/ruby
num = gets.to_i
if num > 0 then
puts "num variable is positive"
puts "num variable equals to #{num}"
end
我们从用户那里读取了一个号码。 如果数字大于零,那么我们将两个消息打印到控制台。 如果没有,则什么也不做。
$ ./simpleif.rb
4
num variable is positive
num variable equals to 4
满足条件,并将消息写入控制台。
我们可以使用else
关键字来创建一个简单的分支。 如果if
关键字后方括号内的表达式的值为假,则将自动执行else
关键字后方的语句。 代码块包含在end
关键字中。
#!/usr/bin/ruby
age = 17
if age > 18
puts "Driving license issued"
else
puts "Driving license not permitted"
end
我们有一个年龄变量。 布尔表达式的计算结果为 false,并且在控制台中得到“不允许驾驶执照”。
$ ./licence.rb
Driving license not permitted
我们可以使用elsif
关键字创建多个分支。 仅当不满足先前条件时,elsif
关键字才会测试其他条件。 请注意,我们可以在测试中使用多个elsif
关键字。
#!/usr/bin/ruby
print "Enter a number: "
num = gets.to_i
if num < 0
puts "#{num} is negative"
elsif num == 0
puts "#{num} is zero"
elsif num > 0
puts "#{num} is positive"
end
我们有一个数值变量,并测试它是否为负数或正数或等于零。 根据从用户读取的值,我们将其中一条消息打印到控制台。
Ruby case
语句
case
语句是选择控制流语句。 它允许变量或表达式的值通过多路分支控制程序执行的流程。 与使用if
和elsif
语句的组合相比,它以更简单的方式创建多个分支。
我们有一个变量或一个表达式。 case
关键字用于根据值列表测试变量或表达式中的值。 值列表用when
关键字显示。 如果值匹配,则执行when
之后的语句。 有一个可选的else
语句。 如果找不到其他匹配项,则执行该命令。
#!/usr/bin/ruby
print "Enter top level domain: "
domain = gets.chomp
case domain
when "us"
puts "United States"
when "de"
puts "Germany"
when "sk"
puts "Slovakia"
when "hu"
puts "Hungary"
else
puts "Unknown"
end
在我们的程序中,我们有一个域变量。 我们从命令行读取变量的值。 我们使用when
语句测试变量的值。 有几种选择。 例如,如果该值等于“ us”,则将“ United States”字符串打印到控制台。
domain = gets.chomp
我们使用gets
方法从用户那里得到输入。 输入还包括换行符。 chomp
方法排除换行符。
$ ./domains.rb
Enter top level domain: hu
Hungary
我们在控制台输入了“ hu”字符串,程序以“ Hungary”作为响应。
Ruby while
,until
语句
while
语句是一个控制流语句,它允许根据给定的布尔条件重复执行代码。 条件为真时,它将执行代码。
while
关键字在end
关键字包围的块内执行语句。 每次将表达式评估为 true 时都会执行这些语句。
#!/usr/bin/ruby
i = 0
sum = 0
while i < 10 do
i = i + 1
sum = sum + i
end
puts "The sum of 0..9 values is #{sum}"
在代码示例中,我们从一系列数字计算值的总和。
while
循环包含三个部分:初始化,测试和更新。 语句的每次执行都称为循环。
i = 0
sum = 0
我们启动i
和sum
变量。 i
用作计数器。
while i < 10 do
...
end
while
和do
关键字之间的表达式是第二阶段,即测试。 请注意,do
关键字是可选的。 执行主体中的语句,直到表达式的计算结果为 false。
i = i + 1
这是while
循环的最后一个第三阶段-更新。 我们增加计数器。 请注意,对while
循环的不正确处理可能会导致循环不断。
$ ./while.rb
The sum of 0..9 values is 55
这是示例的输出。
until
是一个控制流语句,在条件为 false 时执行代码。 当条件为真时,循环停止。
#!/usr/bin/ruby
hours_left = 12
until hours_left == 0
if hours_left == 1
puts "There is #{hours_left} hour left"
else
puts "There are #{hours_left} hours left"
end
hours_left -= 1
end
在我们的示例中,我们有一个变量hours_left
。 我们开始倒数。 在每个循环周期中,我们打印那里还有多少小时。 当变量等于零时,循环停止。
$ ./until.rb
There are 12 hours left
There are 11 hours left
There are 10 hours left
There are 9 hours left
There are 8 hours left
There are 7 hours left
There are 6 hours left
There are 5 hours left
There are 4 hours left
There are 3 hours left
There are 2 hours left
There is 1 hour left
运行示例,我们得到了这个结果。
Ruby for
语句
如果在启动循环之前知道周期数,则可以使用for
语句。 for 循环与范围结合使用。 对于范围的每个元素,将执行语句块。 语句包含在end
关键字中。 do
关键字是可选的。
#!/usr/bin/ruby
for i in 0..9 do
puts "#{i}"
end
在此示例中,我们将数字 0..9 打印到控制台。 在每个循环中,i 变量均包含一个数字范围内的值。 该值将打印到控制台。 ..
范围运算符创建一个数字列表,包括最后一个数字。
$ ./forloop.rb
0
1
2
3
4
5
6
7
8
9
This is the output of the example.
要使用 for 循环遍历元素数组,可以使用数组的length
方法。
#!/usr/bin/ruby
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
for i in 0...planets.length
puts planets[i]
end
在这个例子中,我们有一系列的行星。 我们遍历数组并打印数组的每个元素。
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
这是一系列行星。
for i in 0...planets.length
length
方法返回数组的长度。 由于数组以 0 开头,因此最后一个索引为 n-1。 ...
范围运算符创建一个数字范围,但最后一个高值除外。
puts planets[i]
我们在数组中打印具有特定索引的元素。
$ ./planets2.rb
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
运行上面的 Ruby 程序将给出此输出。
Ruby each
方法
在 Ruby 中,我们可以使用each
方法来遍历数组的各项。 它有两个参数。 一个元素和一个块。 元素放置在管道之间。 它是当前迭代项目的占位符。 块是在每次迭代中执行的代码。
#!/usr/bin/ruby
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
planets.each do |planet|
puts planet
end
在此示例中,我们使用each
迭代器遍历了一系列行星。
planets.each do |planet|
puts planet
end
each
迭代器是一种适用于行星阵列的方法。 该行星是迭代中当前项目的占位符。 我们可以把任何想要的角色放在那里。 我们可以使用{}
字符代替do
和end
关键字。
Ruby break
,next
语句
break
语句可用于终止由while
,for
或case
语句定义的块。
#!/usr/bin/ruby
while true
r = 1 + rand(30)
print "#{r} "
if r == 22
break
end
end
puts
我们定义了一个无限的while
循环。 我们使用break
语句退出此循环。 我们从 1 到 30 中选择一个随机值。我们打印该值。 如果该值等于 22,则结束无穷的 while 循环。
while true
...
end
这是一个无尽的循环。 while 循环的条件始终为 true。 摆脱这种无穷循环的唯一方法就是突破。
r = 1 + rand(30)
print "#{r} "
我们计算一个从 1 到 30 的随机数,并将其打印到控制台。
if r == 22
break
end
如果数字等于 22,我们将打破循环。 while 循环终止。
$ ./break.rb
20 14 6 26 30 12 2 10 18 29 28 11 30 26 20 22
我们可能会得到这样的东西。
next
语句用于跳过循环的一部分,并继续循环的下一个迭代。 它可以与for
和while
语句结合使用。
在下面的示例中,我们将打印一个数字列表,这些数字不能除以 2 而没有余数。
#!/usr/bin/ruby
num = 0
while num < 100
num += 1
if (num % 2 == 0)
next
end
print "#{num} "
end
puts
我们使用while
循环遍历数字 1..99。
if (num % 2 == 0)
next
end
如果表达式num % 2
返回 0,则可以将所讨论的数字除以 2。执行next
语句,并跳过循环的其余部分。 在我们的例子中,循环的最后一条语句将被跳过,并且数字不会输出到控制台。 下一个迭代开始。
$ ./next.rb
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77
79 81 83 85 87 89 91 93 95 97 99
这是程序的示例输出。
Ruby redo
语句
redo
语句重新启动循环的迭代,而无需检查循环条件。 最后一个示例将是一个更复杂的示例。 还将演示redo
语句和其他功能。
#!/usr/bin/ruby
options = ["rock", "scissors", "paper"]
while true
print <<TEXT
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT
val = gets.to_i
r = rand(3) + 1
if val == 9
puts "End"
exit
end
if ![1, 2, 3, 9].include?(val)
puts "Invalid option"
redo
end
computer = options[r-1]
human = options[val-1]
puts "I have #{computer}, you have #{human}"
if val == r
puts "Tie, next throw"
redo
end
if val == 1 and r == 2
puts "Rock blunts scissors, you win"
elsif val == 2 and r == 1
puts "Rock blunts scissors, you loose"
elsif val == 2 and r == 3
puts "Scissors cut paper, you win"
elsif val == 3 and r == 2
puts "Scissors cut paper, you loose"
elsif val == 3 and r == 1
puts "Paper covers rock, you win"
elsif val == 1 and r == 3
puts "Paper covers rock, you loose"
end
end
我们有一个简单的剪刀石头布游戏。 在此代码示例中,我们将利用redo
语句,条件,随机数,数组和用户输入。
options = ["rock", "scissors", "paper"]
在选项数组中,我们拥有游戏的所有可能性。 将消息打印到控制台时,将使用这三个词。
print <<TEXT
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT
我们使用 heredoc 语法将菜单打印到控制台。 Heredoc 以<<
开头,后跟一个字符串。 相同的字符串关闭构造。 它必须保持对齐。 这使我们可以一步打印多行。 每个游戏周期都会打印此菜单。
val = gets.to_i
r = rand(3) + 1
在这些代码行中,我们从终端读取一个值。 然后,我们从 1、2 和 3 中随机选择一个数字。请注意rand(3)
返回 0、1 和 2 中的一个数字。这就是为什么要加 1 的原因。
if val == 9
puts "End"
exit
end
如果来自用户的输入等于 9,我们将“ End”打印到终端并结束游戏。 exit
方法终止程序。
if ![1, 2, 3, 9].include?(val)
puts "Invalid option"
redo
end
如果用户选择的值与菜单中提供的值不同,我们将告知无效选项并重做周期。
computer = options[r-1]
human = options[val-1]
puts "I have #{computer}, you have #{human}"
数字将转换为字符串。 我们同时打印用户和计算机的选择。
if val == r
puts "Tie, next throw"
redo
end
如果双方有相同的选择,那就是平局。 我们开始一个新的游戏周期。 我们利用redo
关键字。
if val == 1 and r == 2
puts "Rock blunts scissors, you win"
elsif val == 2 and r == 1
puts "Rock blunts scissors, you loose"
...
使用多个if
和elsif
分支,我们比较用户和计算机的选择。 我们决定谁是赢家。
$ ./redo.rb
1 - rock
2 - scissors
3 - paper
9 - end game
3
I have paper, you have paper
Tie, next throw
1 - rock
2 - scissors
3 - paper
9 - end game
2
I have rock, you have scissors
Rock blunts scissors, you loose
1 - rock
2 - scissors
3 - paper
9 - end game
1
I have scissors, you have rock
Rock blunts scissors, you win
1 - rock
2 - scissors
3 - paper
9 - end game
9
End
这是一个示例输出。