POSTS
第九章、ruby中的流程控制
流程控制
这章的教程我们将讨论流程控制。
条件和循环改变了Ruby程序的流程。条件式是执行条件语句下面的特定语句。循环是执行多次的代码块。程序开始后,语句从源文件顶部到底部一行一行的执行。
if语句
if关键字用于检查一个表达式是否为真。如果为真则执行语句。这个语句可以是单一的语句,也可以是复合语句。复合语句是由多条语句构成的闭合代码块。代码块用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
输入一个数字,如果这个数字大于0则打印两条消息,否则什么也不做。
$ ./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 licence issued"
else
puts "Driving licence not permitted"
end
这里创建了一个age变量,布尔表达式求值为假,因此在终端上打印”Driving licence not permitted”。
$ ./licence.rb
Driving licence 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
创建一个数字变量判断它是正数、负数还是0。根据输入值的不同将打印不同的消息。
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
这个程序中我们创建了一个domain变量,它的值从命令行读取。使用when语句测试这个变量的值。这有些选项。如果值等于”us”则打印”United States”字符串。
domain = gets.chomp
我们使用gets方法获取一个输入值。使用chomp方法去掉换行符。
$ ./domains.rb
Enter top level domain: hu
Hungary
我们输入”hu”,程序返回”Hungary”。
while、until语句
while语句是一个控制流语句允许代码多次执行。当的条件为真时代码将执行。
while关键字执行使用end闭合的代码块语句。每次表达式为真时这些语句将执行。
#!/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*关键字是可选的。,内部的语句将会执行直到表达式的值为假。
i = i + 1
这是循环的第三阶段——更新。我们增加计数值。注意不当的处理会导致死循环。
$ ./while.rb
The sum of 0..9 values is 55
This is the output of the example.
当条件为假时until控制流语句将执行。当条件为真时循环停止。
#!/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。我们开始计数,每次循环打印还有几个小时。当变量值等于0时循环停止。
$ ./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
程序运行的结果。
for语句
当循环次数是已知时,我们可以使用for语句。for循环使用in接着一个范围。对这个范围的每个元素都执行代码块的语句。这些语句使用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
例子运行结果。
要遍历一个数组的元素可以使用数组的length方法。
#!/usr/bin/ruby
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
for i in 0...planets.length
puts planets[i]
end
这个例子中我们创建了一个数组planets,我们遍历这个数组打印这个数组的每个元素。
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
planets数组。
for i in 0...planets.length
length方法返回数组的长度。数组从0开始,最后一个索引是n-1。
puts planets[i]
打印数组指定的一个元素。
$ ./planets2.rb
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
程序的运行结果。
each方法
在Ruby中我们可以使用each方法遍历数组的每个元素。它接受两个参数。一个元素和一个代码块。元素放在管道之间,它保存了当前循环的数据项。代码块是每次要执行的内容。
#!/usr/bin/ruby
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"]
planets.each do |planet|
puts planet
end
这个例子我们使用each迭代器遍历planets数组。
planets.each do |planet|
puts planet
end
each迭代器是planets数组的一个方法。planet保存了此次迭代的数据项。我们可以使用任何我们想使用的字符。我们可以使用{}代替*do*和end关键字。
break、next语句
break语句用于终止while、for或者case的代码块语句。
#!/usr/bin/ruby
while true
r = 1 + rand(30)
print "#{r} "
if r == 22
break
end
end
puts
我们定义了一个无限循环,使用break语句退出这个循环。我们选择1到30的数,打印它。如果等于22则结束*while*循环。
while true
...
end
这是一个无限循环,while的条件总是为真。退出无限循环的唯一方法是使用break。
r = 1 + rand(30)
print "#{r} "
计算从1到30的随机数,并将其打印。
if r == 22
break
end
如果数等于22,结束循环。
$ ./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
如果这个数可以被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
程序的输出结果。
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
这是一个简单的Rock-paper-scissors游戏。这个例子中我们用到了redo语句、条件式、随机数、数组和输入。
options = ["rock", "scissors", "paper"]
定义了游戏可能用到的选项数组。这三个词在打印消息时会用到。
print <<TEXT
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT
使用定界符在终端上打印一个菜单。菜单在每次游戏循环时都打印。
val = gets.to_i
r = rand(3) + 1
这几行代码从终端输入一个值,然后选择一个1、2、3的随机数。
if val == 9
puts "End"
exit
end
如果输入为9,打印’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"
...
使用多个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
程序输出结果。
这部分的Ruby教程我们谈论了结构流程控制。zetcode原文地址