多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# Ruby 控制流 > 原文: [https://zetcode.com/lang/rubytutorial/flowcontrol/](https://zetcode.com/lang/rubytutorial/flowcontrol/) 在 Ruby 教程的这一部分中,我们将讨论流控制。 我们将定义几个关键字,这些关键字使我们能够控制 Ruby 程序的流程。 条件和循环会改变 Ruby 程序的流程。 条件语句是在特定条件下执行特定语句的关键字。 循环是多次执行的程序块。 当程序运行时,语句从源文件的顶部到底部逐一执行。 ## Ruby `if`语句 `if`关键字用于检查表达式是否为真。 如果为`true`,则执行一条语句。 该语句可以是单个语句或复合语句。 复合语句由该块包围的多个语句组成。 块是由`end`关键字括起来的代码。 `then`关键字是可选的。 ```ruby #!/usr/bin/ruby num = gets.to_i if num > 0 then puts "num variable is positive" puts "num variable equals to #{num}" end ``` 我们从用户那里读取了一个号码。 如果数字大于零,那么我们将两个消息打印到控制台。 如果没有,则什么也不做。 ```ruby $ ./simpleif.rb 4 num variable is positive num variable equals to 4 ``` 满足条件,并将消息写入控制台。 我们可以使用`else`关键字来创建一个简单的分支。 如果`if`关键字后方括号内的表达式的值为假,则将自动执行`else`关键字后方的语句。 代码块包含在`end`关键字中。 ```ruby #!/usr/bin/ruby age = 17 if age > 18 puts "Driving license issued" else puts "Driving license not permitted" end ``` 我们有一个年龄变量。 布尔表达式的计算结果为`false`,并且在控制台中得到`"Driving license not permitted"`。 ```ruby $ ./licence.rb Driving license not permitted ``` 我们可以使用`elsif`关键字创建多个分支。 仅当不满足先前条件时,`elsif`关键字才会测试其他条件。 请注意,我们可以在测试中使用多个`elsif`关键字。 ```ruby #!/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`语句。 如果找不到其他匹配项,则执行该命令。 ```ruby #!/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"`字符串打印到控制台。 ```ruby domain = gets.chomp ``` 我们使用`gets`方法从用户那里得到输入。 输入还包括换行符。 `chomp`方法排除换行符。 ```ruby $ ./domains.rb Enter top level domain: hu Hungary ``` 我们在控制台输入了`"hu"`字符串,程序以`"Hungary"`作为响应。 ## Ruby `while`,`until`语句 `while`语句是一个控制流语句,它允许根据给定的布尔条件重复执行代码。 条件为真时,它将执行代码。 `while`关键字在`end`关键字包围的块内执行语句。 每次将表达式求值为`true`时都会执行这些语句。 ```ruby #!/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`循环包含三个部分:初始化,测试和更新。 语句的每次执行都称为循环。 ```ruby i = 0 sum = 0 ``` 我们启动`i`和`sum`变量。 `i`用作计数器。 ```ruby while i < 10 do ... end ``` `while`和`do`关键字之间的表达式是第二阶段,即测试。 请注意,`do`关键字是可选的。 执行主体中的语句,直到表达式的计算结果为`false`。 ```ruby i = i + 1 ``` 这是`while`循环的最后一个第三阶段-更新。 我们增加计数器。 请注意,对`while`循环的不正确处理可能会导致循环不断。 ```ruby $ ./while.rb The sum of 0..9 values is 55 ``` 这是示例的输出。 `until`是一个控制流语句,在条件为`false`时执行代码。 当条件为真时,循环停止。 ```ruby #!/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`。 我们开始倒数。 在每个循环周期中,我们打印那里还有多少小时。 当变量等于零时,循环停止。 ```ruby $ ./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`关键字是可选的。 ```ruby #!/usr/bin/ruby for i in 0..9 do puts "#{i}" end ``` 在此示例中,我们将数字`0..9`打印到控制台。 在每个循环中,`i`变量均包含一个数字范围内的值。 该值将打印到控制台。 `..`范围运算符创建一个数字列表,包括最后一个数字。 ```ruby $ ./forloop.rb 0 1 2 3 4 5 6 7 8 9 ``` This is the output of the example. 要使用`for`循环遍历元素数组,可以使用数组的`length`方法。 ```ruby #!/usr/bin/ruby planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] for i in 0...planets.length puts planets[i] end ``` 在这个例子中,我们有一系列的行星。 我们遍历数组并打印数组的每个元素。 ```ruby planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] ``` 这是一系列行星。 ```ruby for i in 0...planets.length ``` `length`方法返回数组的长度。 由于数组以 0 开头,因此最后一个索引为`n-1`。 `...`范围运算符创建一个数字范围,但最后一个高值除外。 ```ruby puts planets[i] ``` 我们在数组中打印具有特定索引的元素。 ```ruby $ ./planets2.rb Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune ``` 运行上面的 Ruby 程序将给出此输出。 ## Ruby `each`方法 在 Ruby 中,我们可以使用`each`方法来遍历数组的各项。 它有两个参数。 一个元素和一个块。 元素放置在管道之间。 它是当前迭代项目的占位符。 块是在每次迭代中执行的代码。 ```ruby #!/usr/bin/ruby planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] planets.each do |planet| puts planet end ``` 在此示例中,我们使用`each`迭代器遍历了一系列行星。 ```ruby planets.each do |planet| puts planet end ``` `each`迭代器是一种适用于行星数组的方法。 该行星是迭代中当前项目的占位符。 我们可以把任何想要的角色放在那里。 我们可以使用`{}`字符代替`do`和`end`关键字。 ## Ruby `break`,`next`语句 `break`语句可用于终止由`while`,`for`或`case`语句定义的块。 ```ruby #!/usr/bin/ruby while true r = 1 + rand(30) print "#{r} " if r == 22 break end end puts ``` 我们定义了一个无限的`while`循环。 我们使用`break`语句退出此循环。 我们从 1 到 30 中选择一个随机值。我们打印该值。 如果该值等于 22,则结束无穷的`while`循环。 ```ruby while true ... end ``` 这是一个无尽的循环。 while 循环的条件始终为 true。 摆脱这种无穷循环的唯一方法就是突破。 ```ruby r = 1 + rand(30) print "#{r} " ``` 我们计算一个从 1 到 30 的随机数,并将其打印到控制台。 ```ruby if r == 22 break end ``` 如果数字等于 22,我们将打破循环。 while 循环终止。 ```ruby $ ./break.rb 20 14 6 26 30 12 2 10 18 29 28 11 30 26 20 22 ``` 我们可能会得到这样的东西。 `next`语句用于跳过循环的一部分,并继续循环的下一个迭代。 它可以与`for`和`while`语句结合使用。 在下面的示例中,我们将打印一个数字列表,这些数字不能除以 2 而没有余数。 ```ruby #!/usr/bin/ruby num = 0 while num < 100 num += 1 if (num % 2 == 0) next end print "#{num} " end puts ``` 我们使用`while`循环遍历数字`1..99`。 ```ruby if (num % 2 == 0) next end ``` 如果表达式`num % 2`返回 0,则可以将所讨论的数字除以 2。执行`next`语句,并跳过循环的其余部分。 在我们的例子中,循环的最后一条语句将被跳过,并且数字不会输出到控制台。 下一个迭代开始。 ```ruby $ ./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`语句和其他功能。 ```ruby #!/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`语句,条件,随机数,数组和用户输入。 ```ruby options = ["rock", "scissors", "paper"] ``` 在选项数组中,我们拥有游戏的所有可能性。 将消息打印到控制台时,将使用这三个词。 ```ruby print <<TEXT 1 - rock 2 - scissors 3 - paper 9 - end game TEXT ``` 我们使用 heredoc 语法将菜单打印到控制台。 Heredoc 以`<<`开头,后跟一个字符串。 相同的字符串关闭构造。 它必须保持对齐。 这使我们可以一步打印多行。 每个游戏周期都会打印此菜单。 ```ruby val = gets.to_i r = rand(3) + 1 ``` 在这些代码行中,我们从终端读取一个值。 然后,我们从 1、2 和 3 中随机选择一个数字。请注意`rand(3)`返回 0、1 和 2 中的一个数字。这就是为什么要加 1 的原因。 ```ruby if val == 9 puts "End" exit end ``` 如果来自用户的输入等于 9,我们将`"End"`打印到终端并结束游戏。 `exit`方法终止程序。 ```ruby if ![1, 2, 3, 9].include?(val) puts "Invalid option" redo end ``` 如果用户选择的值与菜单中提供的值不同,我们将告知无效选项并重做周期。 ```ruby computer = options[r-1] human = options[val-1] puts "I have #{computer}, you have #{human}" ``` 数字将转换为字符串。 我们同时打印用户和计算机的选择。 ```ruby if val == r puts "Tie, next throw" redo end ``` 如果双方有相同的选择,那就是平局。 我们开始一个新的游戏周期。 我们利用`redo`关键字。 ```ruby 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`分支,我们比较用户和计算机的选择。 我们决定谁是赢家。 ```ruby $ ./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 教程的这一部分中,我们正在讨论控制流结构。