Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 使用Caesar密码时如何保留字符大小写_Ruby_Caesar Cipher - Fatal编程技术网

Ruby 使用Caesar密码时如何保留字符大小写

Ruby 使用Caesar密码时如何保留字符大小写,ruby,caesar-cipher,Ruby,Caesar Cipher,我有一个用Ruby编写的Caesar密码脚本正在工作,但它返回的字符串是所有大写字母,而不是保留原始字符串的大小写 我可以使用大写使它看起来足够好,但我希望有一种更具体的方法来保存这些案例 以下是脚本: BASE_ORD = 'A'.ord def caesar_cipher(phrase, key) cipher = phrase.gsub(/[a-z]/i) do |c| orig_pos = c.upcase.ord - BASE_ORD new_pos = (ori

我有一个用Ruby编写的Caesar密码脚本正在工作,但它返回的字符串是所有大写字母,而不是保留原始字符串的大小写

我可以使用
大写
使它看起来足够好,但我希望有一种更具体的方法来保存这些案例

以下是脚本:

BASE_ORD = 'A'.ord

def caesar_cipher(phrase, key)
  cipher = phrase.gsub(/[a-z]/i) do |c|
    orig_pos = c.upcase.ord - BASE_ORD
    new_pos = (orig_pos + key) % 26
    (new_pos + BASE_ORD).chr
  end
  puts cipher
end

caesar_cipher("What a string!", 5) 

任何帮助或见解都将不胜感激。

如评论中所述,
tr
对于Caesar Cypher更容易使用(一旦您准备好两个字母表),并且应该更快:

class CaesarCypher
    def initialize(key, alphabet=nil)
        @from_alphabet = alphabet || (?a..?z).to_a.join
        @to_alphabet = @from_alphabet[key..-1] + @from_alphabet[0...key]
        @from_alphabet += @from_alphabet.upcase
        @to_alphabet += @to_alphabet.upcase
    end
    def encode(str)
        str.tr(@from_alphabet, @to_alphabet)
    end
    def encode!(str)
        str.tr!(@from_alphabet, @to_alphabet)
    end
    def decode(str)
        str.tr(@to_alphabet, @from_alphabet)
    end
    def decode(str)
        str.tr!(@to_alphabet, @from_alphabet)
    end
end

cc = CaesarCypher.new(1)
puts cc.encode("Caesar, huh?")
puts cc.decode("Dbftbs, ivi?")

给定现有代码,最简单的解决方案是检查字符是大写还是小写,并相应地设置
base\u ord
。由于UTF-8中的小写字母位于大写字母之后(如ASCII),因此我们可以只测试
字母>='a'
,例如:

base_ord = (letter >= 'a' ? 'a' : 'A').ord
以下是此更改的整个方法(您不再需要
BASE\u ORD
常量):

编辑 Amadan非常重视使用。下面是一个更简洁的实现:

ALPHABET = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
# Or if you want to be fancy: ALPHABET = (?a..?z).flat_map {|c| [ c, c.upcase ] }.join

def caesar_cipher(phrase, key)
  to_alphabet = ALPHABET.dup
  to_alphabet << to_alphabet.slice!(0, key * 2)
  phrase.tr(ALPHABET, to_alphabet)
end

puts caesar_cipher("What a string!", 5) # => Bmfy f xywnsl!
字母表 #或者,如果你想变得有趣:ALPHABET=(?a…?z).flat|map{| c |[c,c.upcase]}.join def caesar_密码(短语、密钥) to_alphabet=alphabet.dup 到字母Bmfy f xywnsl!
您的正则表达式不区分大小写,您可能希望捕获所有实际情况:
短语.gsub(/\w/)
@Brennan:
\w
还包括一些非字母的内容,因此
[a-zA-Z]
会更好。问题实际上是
upcase
。无论如何,使用
tr
比使用
gsub
更容易做到这一点。。。谢谢使用大于或等于的符号非常有效!不过,我必须尝试使用String#tr方法,这看起来有点简单!
ALPHABET = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
# Or if you want to be fancy: ALPHABET = (?a..?z).flat_map {|c| [ c, c.upcase ] }.join

def caesar_cipher(phrase, key)
  to_alphabet = ALPHABET.dup
  to_alphabet << to_alphabet.slice!(0, key * 2)
  phrase.tr(ALPHABET, to_alphabet)
end

puts caesar_cipher("What a string!", 5) # => Bmfy f xywnsl!