в `> ': сравнение Fixnum с nil не удалось (ArgumentError) Преобразователь римских цифр в Ruby - PullRequest
0 голосов
/ 25 февраля 2012

Я новичок в Ruby и пытаюсь написать программу, которая конвертирует римские цифры в числа.

Это то, что я сделал до сих пор:

roman_numbers = {"M" => 1000, "D" => 500, "C" => 100, "L" => 50, "X" => 10, "V" => 5, "I" => 1}
number_by_user = "MCMXCIX"
singlenum = number_by_user.split(//).reverse!

l = singlenum.length
result =0


result = roman_numbers[singlenum[0]]
puts result
for i in 0..l-1
  if roman_numbers.key?(singlenum[i])
    **if (roman_numbers[singlenum[i]] > roman_numbers[singlenum[i+1]])** #gives error
      result = result - roman_numbers[singlenum[i+1]]
    elsif (roman_numbers[singlenum[i]]== roman_numbers[singlenum[i+1]] || **roman_numbers[singlenum[i]] < roman_numbers[singlenum[i+1]])** #gives error
      result = result + roman_numbers[singlenum[i+1]]
    end
    puts roman_numbers[singlenum[i]]
  else
    puts "One of the values are not roman"
    break
  end  
end
puts "The number is: " , result

но выдает следующую ошибку (см. Строку с комментарием):

:in `>': comparison of Fixnum with nil failed (ArgumentError)

Ответы [ 2 ]

5 голосов
/ 25 февраля 2012

У вас ошибка "по одному". Массивы 0 проиндексированы. Ваш singlenum.length в этом случае равен 7, но в цикле for вы поднимаетесь до 6, затем пытаетесь сослаться на singlenum[7] для сравнения с singlenum[6]. singlenum[7] равно nil, поэтому он не понимает оператор <. </p>

4 голосов
/ 25 февраля 2012

Марк хорошо объяснил, где была ошибка в вашем коде.Однако такая ошибка никогда не должна была возникать в первую очередь, поскольку в Ruby все коллекции уже знают, как перебирать себя: вам не нужно это делать, поэтому вы даже никогда не сможете сделать такую ​​ошибку!

Вот пример того, как можно реализовать тот же алгоритм в более идиоматическом Ruby:

numerals = {
  'M' => 1000,
  'D' =>  500,
  'C' =>  100,
  'L' =>   50,
  'X' =>   10,
  'V' =>    5,
  'I' =>    1
}

num = 'MCMXCIX'

(num.chars.map(&numerals.method(:[])) << 0).each_cons(2).inject(0) {|a, (n1, n2)|
  if n1 < n2 then a - n1 else a + n1 end
}

Видите?Нет петель.Нет индексов.Вы не можете сделать ошибку «один за другим», даже если вы пытались !

Бонус: на самом деле , приведенный выше фрагмент содержит частькода, чтобы предотвратить ошибочную ошибку, хотя и на гораздо более высоком семантическом уровне.Вы можете найти это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...