I wrote a code for translating a plain text message into a cipher text message using a simple substitution cipher (a=b, b=c, etc). Spaces were substituted with a "1".

I then wanted to make it so that I could type in a different message using 'gets'. This caused a problem which I solved by replacing "gets" with "gets.strip". If the gets was adding a space to the typed string, either in the beginning or end, why did it cause a problem? I had a way of dealing with spaces so is it really a " " or is it a nil space (for lack of a better word) or a character return or what? This is what I wrote:

base_alph =[" ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]  
code_alph = ["1", "z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"]  
x=0  
base_msgarray = []  
code_msgarray = []  
puts "type what you want to translate below"  
base_msg = gets.strip # without the .strip the program doesn't run  
msg_size = base_msg.length  
puts "the message is translated as:"  

loop do  #this section populates an array with all the characters from the gets  
break if x >= msg_size  
base_msgarray.push(base_msg[x])  
x += 1  
end  
# this section passes in the values of the base_msgarray to |letter| to then determine its key   
# in base_alph then that key is passed into code_alph to find the translated letter which  
# is then used to populate the code_msgarray  
base_msgarray.each do |letter|  
code_index = base_alph.index(letter)  
code_msgarray.push(code_alph[code_index])  
end  
# this section displays the values of code_msgarray in a more text-like fashion  
code_msgarray.each do |codeletter|  
print codeletter  
end  
gets # for some reason if i dont have this here the terminal window disappears before I can read anything  
有帮助吗?

解决方案

The problem is this. If you don't use strip, a new line character is appended to your input. For example

type what you want to translate below
rubyisgreat

The value of base_msg if gets.strip is used

"rubyisgreat"

The value of base_msg without strip

"rubyisgreat\n"

As such, since "\n" does not belong to your cipher array, querying its index in line

code_index = base_alph.index(letter)

produces nil. This nil is used in next line as

code_msgarray.push(code_alph[code_index])

Hence the error!

Here's a tip. Use 'p base_msg' to inspect the exact value of. One more thing. You might be using ruby but you need to learn it. This program is C written in ruby. Its not the ruby way. Use hashes instead of arrays here. And don't use loop if possible.

其他提示

From the fine manual:

gets(sep=$/) → string or nil
[...]

Returns (and assigns to $_) the next line from the list of files in ARGV (or $*), or from standard input if no files are present on the command line. Returns nil at end of file. The optional argument specifies the record separator. The separator is included with the contents of each record.

Note the final sentence: the record separator is included in the contents of each record. By default, the record separate is an EOL (generally a line-feed or carriage-return/line-feed pair) so you'll get a stray \n at the of of your string.

Your strip call will remove leading and trailing whitespace (which includes CR and LF characters) so the problem goes away. Another common approach is to use chomp to strip off the trailing $/ record separator if it is present.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top