美文网首页Ruby入门程序员
8(1)我送你玫瑰,你给我幸福

8(1)我送你玫瑰,你给我幸福

作者: 彩虹门票 | 来源:发表于2018-03-14 09:55 被阅读4次

    你们可能已经注意到有些方法当你在调用它们时会返回来一些东西。举例来说:gets会返回一个字符串(就是你所键入的内容),在5+3+方法(实际是5.+(3))会返回来8.数字间的运算方法返回的也会是数字,字符串间运算方法返回的也会是字符串。

    要分辨清楚方法被调用后的返回值和程序输出到屏幕上的信息这两者间的区别是很重要的。比如方法puts 5+3中,5+3返回值是数字8,而不是字符串8。

    puts的返回值会是什么?之前我们一直没考虑到过,那么现在让我们来思考一下:

    This puts returned:
    
    

    第一个puts看似没返回任何值,但只是在某种程度上它没有返回值,它实际上返回的是nil;尽管我们没测试第二个puts,它返回的也是puts,实际上puts总会返回nil。所有的方法必须会有一个返回值,即使返回值是nil

    稍微休息一会儿,写一个小程序来测试一下sayMoo会返回什么?

    是不是有些惊喜?实际上它是这样工作的:方法中的返回值只会简单返回方法中最后一行。在sayMoo的例子中就意味着它会返回的是puts 'mooooooo…'*numberOfMoos,也就是说返回值是nil(因为puts返回值是nil)。如果我们想让所有的方法得到的返回值是字符串yellow submarine,只需要在后面把我们想要的字符串加上就可以:


    输出为:
    mooooooo...mooooooo...
    yellow submarine
    

    那么现在我们就可以再回头看一下上一章中心理学调查的问题,但这次我们会写一个方法来帮我们问问题。在这个程序中会把想问的问题当成一个参数,如果回答是“yes”则返回true,回答是“no”则返回false(虽然我们大多数情况下是忽视答案的,但在方法中设置返回值还是很有必要的,同时我们在反馈尿床问题时也能用得上)。我会简略开头的欢迎部分和最后的收尾部分,方便大家阅读:

    def ask question
      goodAnswer = false
      while (not goodAnswer)
        puts question
        reply = gets.chomp.downcase
    
        if (reply == 'yes' or reply == 'no')
          goodAnswer = true
          if reply == 'yes'
            answer = true
          else
            answer = false
          end
        else
          puts 'Please answer "yes" or "no".'
        end
      end
    
      answer  # This is what we return (true or false).
    end
    
    puts 'Hello, and thank you for...'
    puts
    
    ask 'Do you like eating tacos?'      # We ignore this return value.
    ask 'Do you like eating burritos?'
    wetsBed = ask 'Do you wet the bed?'  # We save this return value.
    ask 'Do you like eating chimichangas?'
    ask 'Do you like eating sopapillas?'
    ask 'Do you like eating tamales?'
    puts 'Just a few more questions...'
    ask 'Do you like drinking horchata?'
    ask 'Do you like eating flautas?'
    
    puts
    puts 'DEBRIEFING:'
    puts 'Thank you for...'
    puts
    puts wetsBed
    

    输出

    程序运行得不错吧?现在我们可以更加方便得增加想问的问题了,同时我们的程序还更加短小精悍了!这的确是一个大的进步--让程序尽可能得短小精悍是每一个“懒”程序员的梦想。

    摩拳擦掌

    这里有个非常合适的英文数字转换的例子:输入一个数字(比如22)会输出相应的英文(这里指输出"twenty-two")。目前的话我们仅仅在0-100范围内的整数中测试。
    (注意:这个例子中用另一种技巧return来返回方法值,并且会介绍分支中一种新的转折elsif。阅读代码中的前后文会清楚得理解它们的使用方法)

      # We only want numbers from 0-100.
      if number < 0
        return 'Please enter a number zero or greater.'
      end
      if number > 100
        return 'Please enter a number 100 or lesser.'
      end
    
      numString = ''  # This is the string we will return.
    
      # "left" is how much of the number we still have left to write out.
      # "write" is the part we are writing out right now.
      # write and left... get it?  :)
      left  = number
      write = left/100          # How many hundreds left to write out?
      left  = left - write*100  # Subtract off those hundreds.
    
      if write > 0
        return 'one hundred'
      end
    
      write = left/10          # How many tens left to write out?
      left  = left - write*10  # Subtract off those tens.
    
      if write > 0
        if write == 1  # Uh-oh...
          # Since we can't write "tenty-two" instead of "twelve",
          # we have to make a special exception for these.
          if    left == 0
            numString = numString + 'ten'
          elsif left == 1
            numString = numString + 'eleven'
          elsif left == 2
            numString = numString + 'twelve'
          elsif left == 3
            numString = numString + 'thirteen'
          elsif left == 4
            numString = numString + 'fourteen'
          elsif left == 5
            numString = numString + 'fifteen'
          elsif left == 6
            numString = numString + 'sixteen'
          elsif left == 7
            numString = numString + 'seventeen'
          elsif left == 8
            numString = numString + 'eighteen'
          elsif left == 9
            numString = numString + 'nineteen'
          end
          # Since we took care of the digit in the ones place already,
          # we have nothing left to write.
          left = 0
        elsif write == 2
          numString = numString + 'twenty'
        elsif write == 3
          numString = numString + 'thirty'
        elsif write == 4
          numString = numString + 'forty'
        elsif write == 5
          numString = numString + 'fifty'
        elsif write == 6
          numString = numString + 'sixty'
        elsif write == 7
          numString = numString + 'seventy'
        elsif write == 8
          numString = numString + 'eighty'
        elsif write == 9
          numString = numString + 'ninety'
        end
    
        if left > 0
          numString = numString + '-'
        end
      end
    
      write = left  # How many ones left to write out?
      left  = 0     # Subtract off those ones.
    
      if write > 0
        if    write == 1
          numString = numString + 'one'
        elsif write == 2
          numString = numString + 'two'
        elsif write == 3
          numString = numString + 'three'
        elsif write == 4
          numString = numString + 'four'
        elsif write == 5
          numString = numString + 'five'
        elsif write == 6
          numString = numString + 'six'
        elsif write == 7
          numString = numString + 'seven'
        elsif write == 8
          numString = numString + 'eight'
        elsif write == 9
          numString = numString + 'nine'
        end
      end
    
      if numString == ''
        # The only way "numString" could be empty is if
        # "number" is 0.
        return 'zero'
      end
    
      # If we got this far, then we had a number somewhere
      # in between 0 and 100, so we need to return "numString".
      numString
    end
    
    puts englishNumber(  0)
    puts englishNumber(  9)
    puts englishNumber( 10)
    puts englishNumber( 11)
    puts englishNumber( 17)
    puts englishNumber( 32)
    puts englishNumber( 88)
    puts englishNumber( 99)
    puts englishNumber(100)
    

    输出为:

    zero
    nine
    ten
    eleven
    seventeen
    thirty-two
    eighty-eight
    ninety-nine
    one hundred
    

    程序先考虑100,后10-19,然后20、30、40~~90,再然后考虑中间数据,最终考虑数字0 --译者注
    上面程序中有几点令人不太满意的:首先有太多重复部分,其次是没法解决100以上的大数,最后是程序里有太多特殊情况和返回值。其实我们可以用阵列方法来精简一下程序:

    def englishNumber number
      if number < 0  # No negative numbers.
        return 'Please enter a number that isn\'t negative.'
      end
      if number == 0
        return 'zero'
      end
    
      # No more special cases! No more returns!
    
      numString = ''  # This is the string we will return.
    
      onesPlace = ['one',     'two',       'three',    'four',     'five',
                   'six',     'seven',     'eight',    'nine']
      tensPlace = ['ten',     'twenty',    'thirty',   'forty',    'fifty',
                   'sixty',   'seventy',   'eighty',   'ninety']
      teenagers = ['eleven',  'twelve',    'thirteen', 'fourteen', 'fifteen',
                   'sixteen', 'seventeen', 'eighteen', 'nineteen']
    
      # "left" is how much of the number we still have left to write out.
      # "write" is the part we are writing out right now.
      # write and left... get it?  :)
      left  = number
      write = left/100          # How many hundreds left to write out?
      left  = left - write*100  # Subtract off those hundreds.
    
      if write > 0
        # Now here's a really sly trick:
        hundreds  = englishNumber write
        numString = numString + hundreds + ' hundred'
        # That's called "recursion". So what did I just do?
        # I told this method to call itself, but with "write" instead of
        # "number". Remember that "write" is (at the moment) the number of
        # hundreds we have to write out. After we add "hundreds" to
        # "numString", we add the string ' hundred' after it.
        # So, for example, if we originally called englishNumber with
        # 1999 (so "number" = 1999), then at this point "write" would
        # be 19, and "left" would be 99. The laziest thing to do at this
        # point is to have englishNumber write out the 'nineteen' for us,
        # then we write out ' hundred', and then the rest of
        # englishNumber writes out 'ninety-nine'.
    
        if left > 0
          # So we don't write 'two hundredfifty-one'...
          numString = numString + ' '
        end
      end
    
      write = left/10          # How many tens left to write out?
      left  = left - write*10  # Subtract off those tens.
    
      if write > 0
        if ((write == 1) and (left > 0))
          # Since we can't write "tenty-two" instead of "twelve",
          # we have to make a special exception for these.
          numString = numString + teenagers[left-1]
          # The "-1" is because teenagers[3] is 'fourteen', not 'thirteen'.
    
          # Since we took care of the digit in the ones place already,
          # we have nothing left to write.
          left = 0
        else
          numString = numString + tensPlace[write-1]
          # The "-1" is because tensPlace[3] is 'forty', not 'thirty'.
        end
    
        if left > 0
          # So we don't write 'sixtyfour'...
          numString = numString + '-'
        end
      end
    
      write = left  # How many ones left to write out?
      left  = 0     # Subtract off those ones.
    
      if write > 0
        numString = numString + onesPlace[write-1]
        # The "-1" is because onesPlace[3] is 'four', not 'three'.
      end
    
      # Now we just return "numString"...
      numString
    end
    
    puts englishNumber(  0)
    puts englishNumber(  9)
    puts englishNumber( 10)
    puts englishNumber( 11)
    puts englishNumber( 17)
    puts englishNumber( 32)
    puts englishNumber( 88)
    puts englishNumber( 99)
    puts englishNumber(100)
    puts englishNumber(101)
    puts englishNumber(234)
    puts englishNumber(3211)
    puts englishNumber(999999)
    puts englishNumber(1000000000000)
    

    程序在输出大于等于100的数据时使用了递归,调用自身方法 ----译者注
    输出为:

    zero
    nine
    ten
    eleven
    seventeen
    thirty-two
    eighty-eight
    ninety-nine
    one hundred
    one hundred one
    two hundred thirty-four
    thirty-two hundred eleven
    ninety-nine hundred ninety-nine hundred ninety-nine
    one hundred hundred hundred hundred hundred hundred
    

    嗯,程序显得好多了,代码相当紧凑,所以我在里面写了许多注释。程序可以用于更大的数……尽管不像我们希望的那样。例如我认为最后的数的输出是'one trrllion'更合适,或是'one million million'(当然三种都对),你现在就可以试着改一下……

    牛刀小试

    • 扩展一下上面的englishNumber程序:扩大到千位数字,使程序可以返回'one thousand'、'ten thousand'来替代'ten thousand'、'one hundred hundred'。
    • 再扩展上面的程序:扩大到百万数字,使程序可以返回'one million'来替代'one thousand thousand',也可以试着增加到亿万和万亿。你最多能增加多少?
    • 能不能将数字连接起来?与上面englishNumber程序类似,只是在数字中间加入‘and’,返回的是'nineteen hundred and seventy and two',或者是婚礼请柬上那样的数字。我本想多举几个例子,但我自己也不是太懂得这些。你可能需要联系婚礼人员来帮一下忙。
    • "Ninety-nine bottles of beer..."现在你可以用上englishNumber和你之前的程序,重写一下输出这首歌的歌词的正确方法。惩罚一下你的电脑:让它从9999开始(虽然不要选一个太大的数字,因为让电脑在屏幕上输出如此多的内容需要挺多时间的)。输出十万个瓶子需要一点时间,如果你选择输出一百万个瓶子,你同时也是在惩罚你自己哦!

    恭喜你!到现在为止,你就成为一个真正的程序员了!你已经学到了从头构建一个大程序的所有知识。如果你有想编写某个程序的想法,你就可以自己去写了,统统把它们解决掉吧!

    当然从头构建所有的程序确实有点缓慢。有必要花费时间写别人已经写过的代码吗?你考虑过让程序发一封邮件吗?有没有想过让程序把网上的东西保存并下载到你的电脑上?或者是生成一个代码能够自动测试的网页教程?Ruby有多种多样的对象来帮助我们更加快速得写程序。

    相关文章

      网友评论

        本文标题:8(1)我送你玫瑰,你给我幸福

        本文链接:https://www.haomeiwen.com/subject/klhbixtx.html