[翻译]Ruby教程9——控制流

控制流

这章的教程我们将讨论控制流。


条件和循环改变了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语句是一个程序控制流语句。它允许一个变量或者表达式的值控制程序的执行流程。相比ifelsif它创建多分支更简单。


我们创建一个变量或者表达式。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

初始化变量isumi用于计数。


while i < 10  do

end

whiledo之间的表达式是第二阶段,测试。注意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保存了此次迭代的数据项。我们可以使用任何我们想使用的字符。我们可以使用{}代替doend关键字。


break、next语句


break语句用于终止whilefor或者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语句用于跳过此次循环,继续下次循环。它可与forwhile联合使用。


接下来的例子我们打印不能被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”


使用多个ifelsif分支,比较用户和计算机的选择以决定谁是赢家。


$ ./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教程我们谈论了结构控制流。




原文地址: http://zetcode.com/lang/rubytutorial/flowcontrol/

翻译:龙昌 admin@longchangjin.cn

完整教程:https://github.com/wusuopu/Ruby-tutorial