这是我将用户输入的字符串转换为凯撒密码的代码。
puts "text?"
text = gets.chomp
puts "key?"
key = gets.chomp.to_i
plainTex = Array.new
ciphTex = Array.new
j = 0
text.each_byte do |i|
plainTex[j] = i
j += 1
end
j = 0
plainTex.each_entry do |i|
if ( i == 32 )
ciphTex[j] = plainTex[j]
j += 1
end
if( plainTex[j] > 64) and (plainTex[j] < 91 )
if( (plainTex[j] + key) > 91)
ciphTex[j] = (plainTex[j] + key ) - 90
j += 1
else
ciphTex[j] = plainTex[j] + key
j += 1
end
end
if( plainTex[j] > 94) and (plainTex[j] < 123)
if( (plainTex [j] + key) > 122)
ciphTex [j] = (plainTex[j] + key) - 122
j += 1
else
ciphTex[j] = plainTex[j] + key
j += 1
end
end
end
ciphTex.each_entry do |i|
puts i
end
现在,我出现错误:nil:NilClass(NoMethodError)的未定义方法">'
在网上搜索后,我得出结论,plainTex可能为零,正如错误消息所说(事实并非如此,因为plainTex是预先提供数据的)。
附带说明:当输入字符串 全部为小写且没有空格时,程序运行良好那么,我做错了什么?
问题说明
当您使用超出界限的索引访问数组时,不会得到任何错误,但结果是nil
。
irb --simple-prompt
>> a = [1]
=> [1]
>> a[0]
=> 1
>> a[1]
=> nil
>> a[200]
=> nil
调试代码
一点看跌期权声明揭示了问题:
text.each_byte do |i|
plainTex[j] = i
j += 1
end
j = 0
puts "Length: #{plainTex.length}"
plainTex.each_entry do |i|
if ( i == 32 )
ciphTex[j] = plainTex[j]
j += 1
end
puts "j: #{j}"
这是输出
text?
Testing Test
key?
32
Length: 12
j: 0
j: 2
j: 3
j: 4
j: 5
j: 6
j: 7
j: 8
j: 10
j: 11
j: 12
test.rb:30:in `block in <main>': undefined method `>' for nil:NilClass (NoMethodError)
from test.rb:23:in `each'
from test.rb:23:in `each_entry'
from test.rb:23:in `<main>
在本例中,数组的最后一个索引是11,您访问了索引12。您得到了结果nil
,然后尝试在nil上调用方法>
。
专业调试
您可以安装gempry-byebug
,并使用短别名s
、n
作为步骤进入、下一步等。
https://github.com/deivid-rodriguez/pry-byebug
发现Bug
使用pry-byebug
可以立即清楚地了解错误是什么,尽管我并不真正理解你的代码,因为这些数字对我来说毫无意义
对于第一个字母,它在第二个条件if( plainTex[j] > 64) and (plainTex[j] < 91 )
中递增j
。然后随着j
的递增,它移动到if( plainTex[j] > 94) and (plainTex[j] < 123)
,在那里它再次递增。
您应该对所有这些使用elsif
或使用next
代码清理
Ruby惯例是使用snake大小写来命名变量,我会更改这段代码:
if( plainTex[j] > 64) and (plainTex[j] < 91 )
if( (plainTex[j] + key) > 91)
ciphTex[j] = (plainTex[j] + key ) - 90
j += 1
else
ciphTex[j] = plainTex[j] + key
j += 1
end
end
到此:
if plain_text[j].between?(65, 90)
ciph_text[j] = plain_text[j] + key
ciph_text[j] -= 90 if ciph_text[j] > 91
j += 1
end
似乎您在每个条件下都重复j+=1,所以为什么不将其删除到if/else块之外,并将其作为循环end
之前的最后一行呢?
我也是一个人,我不想记住";A";是65;Z";是90。为什么不在代码中这样说呢?
if plain_text[j].between?("A".ord, "Z".ord)
我从来没有在ruby中弄乱过ASCII,但我相信你可以进一步改进这一点,可能用10行或更少的代码在一个简单的循环中完成整个密码。
Ruby非常擅长处理数组,所以请使用它。我会这样做:
plain_text = text.codepoints
cyph_text = plain_text.map do |code|
if code == ' '.ord
' '.ord
elsif
# return cypher code
end
end
看看地图功能是如何工作的。