跳转至

Ruby 控制流

原文: https://zetcode.com/lang/rubytutorial/flowcontrol/

在 Ruby 教程的这一部分中,我们将讨论流控制。 我们将定义几个关键字,这些关键字使我们能够控制 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,并且在控制台中得到"Driving license not permitted"

$ ./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语句是选择控制流语句。 它允许变量或表达式的值通过多路分支控制程序执行的流程。 与使用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

在我们的程序中,我们有一个域变量。 我们从命令行读取变量的值。 我们使用when语句测试变量的值。 有几种选择。 例如,如果该值等于"us",则将"United States"字符串打印到控制台。

domain = gets.chomp

我们使用gets方法从用户那里得到输入。 输入还包括换行符。 chomp方法排除换行符。

$ ./domains.rb 
Enter top level domain: hu
Hungary

我们在控制台输入了"hu"字符串,程序以"Hungary"作为响应。

Ruby whileuntil语句

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

我们启动isum变量。 i用作计数器。

while i < 10  do
   ...
end

whiledo关键字之间的表达式是第二阶段,即测试。 请注意,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迭代器是一种适用于行星数组的方法。 该行星是迭代中当前项目的占位符。 我们可以把任何想要的角色放在那里。 我们可以使用{}字符代替doend关键字。

Ruby breaknext语句

break语句可用于终止由whileforcase语句定义的块。

#!/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语句用于跳过循环的一部分,并继续循环的下一个迭代。 它可以与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

如果表达式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"
...

使用多个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 教程的这一部分中,我们正在讨论控制流结构。



回到顶部