1
votes

ruby coercition entier et chaîne

Débutant Ruby ici.

J'essaie d'écrire une calculatrice très simple où je stocke les nombres dans des variables et vérifie si l'entrée utilisateur pour l'opérateur est incluse dans le tableau des opérateurs possibles, si c'est alors ça devrait effectuer le calcul en utilisant ces variables

Est-il possible d'obtenir le résultat de la combinaison de ces 3 variables? En ce moment, me lance l'erreur "La chaîne ne peut pas être forcée en nombre entier"

puts "enter a number!"
num1 = gets.chomp().to_i
puts "enter an operator!"
op = gets.chomp()
puts "enter another number"
num2 = gets.chomp().to_i
operators = ["+", "*", "-", "/"]
result = nil

if operators.include?(op)
  result =  num1 + "#{op}" + num2
else
  puts "enter a valid operator"
end

puts result


1 commentaires

Je ne sais pas trop ce que vous entendez par «combinaison». Quel est votre résultat attendu pour num1 = 1 , op = "+" et num2 = 2 ? La chaîne "1 + 2" ou l'entier 3 ?


3 Réponses :


1
votes

Vous pouvez utiliser public_send

if op == "+"
  num1 + num2
elsif op == "-"
  num1 - num2
elsif op == "*"
  num1 * num2
elsif op == "/"
  num1 / num2
end

https://apidock.com/ruby/Object/public_send

Mais une approche plus claire consisterait simplement à utiliser des instructions if / else.

num1.public_send(op, num2)


1 commentaires

Au lieu de if / elsif , vous pouvez utiliser un case expression pour éviter de répéter la comparaison.



0
votes

Utilisez la méthode Object # send

Votre code actuel ne fonctionne pas car vous essayez d'ajouter op , qui est actuellement une chaîne, à un entier. Ce que vous voulez faire est d'appeler la méthode en envoyant le message approprié au premier entier, avec le deuxième nombre passé comme argument à la méthode. Vous pouvez le faire avec Object # send comme suit:

print "Enter a number: "
num1 = Integer gets

loop do
  print "Enter an operator: "
  op = gets.strip
  break if %w[+ - / *].include? op
end

print "Enter another number: "
num2 = Integer gets

p num1.send(op, num2)

Outre les autres modifications et refactorisations, c'est l'utilisation de #send qui permet à cette approche de fonctionner. Il existe certainement de nombreuses autres façons de représenter ce que vous essayez de faire, mais celle-ci fonctionne certainement.


0 commentaires

2
votes

Décomposons votre exemple en quelque chose d'un peu plus simple:

if operators.include?(op)
  result = num1.public_send(op, num2)
else
  puts "enter a valid operator"
end

Lorsque vous essayez d'attribuer un résultat , voici ce qui se passe réellement:

XXX

Rapports Ruby La chaîne ne peut pas être forcée en Integer car elle tente d'ajouter la chaîne + à l'entier 1 et Ruby ne peuvent pas ajouter de chaîne à un entier. Vous pouvez en savoir plus à ce sujet sur La chaîne ne peut pas être forcée dans Fixnum (TypeError) .

Vous pouvez le reproduire avec un exemple encore plus simple:

num1.public_send(op, num2)
=> 3

Dans votre question, vous dites qu'il devrait effectuer le calcul en utilisant ces variables donc je suppose que vous vous attendez à ce que le résultat soit égal à 3 . (car il devrait calculer 1 + 2 à partir des trois variables) Ce n'est pas ce qui se passe dans votre ligne result = ... pour les raisons décrites ci-dessus.

La bonne façon de faire est d'utiliser public_send comme décrit dans ces autres questions et réponses ici sur Stack Overflow:

Ainsi la réponse est:

1 + '+'
TypeError: String can't be coerced into Integer

Et intégrée dans votre exemple:

result = 1 + '+' + 2


0 commentaires