Bonjour à tous,
je cherchais à remplacer la série de IF…ELSE pour la fonction de calcul par un SWITCH…CASE or j’ai un souci Xcode me signale que ma variable ‘result’ n’est pas initialisée mais si je lui mets une valeur de 0 ça ne fait pas les bons calculs.
Avez vous une idée ? Sachant que ça marchait très bien avec la version IF…ELSE.
func performingCalculous() {
var result:Double
switch _typeOperation {
case "+":
result = _previousNumber + _currentNumber
case "-":
result = _previousNumber - _currentNumber
case "/":
if _currentNumber != 0 {
result = _previousNumber /_currentNumber
}
case "x":
result = _previousNumber * _currentNumber
default:
ui_diplayedNumber.text = "Erreur"
}
_previousNumber = resultat
_shouldResetCurrentNumber = true
ui_displayedNumber.text = "\(result)"
}
Il est normal qu’Xcode te signale que la variable result ne soit pas initialisée. Par contre, le fait que les résultats soient erronés quand elle est initialisée avec la valeur 0 me laisse perplexe.
J’ai écrit un programme de test reproduisant la situation, et les résultats sont parfaitement corrects !
import UIKit
class ViewController: UIViewController {
var a = 2.0
var b = 3.0
override func viewDidLoad() {
super.viewDidLoad()
calcul(operateur: "+")
calcul(operateur: "-")
calcul(operateur: "/")
calcul(operateur: "*")
}
func calcul(operateur:String) {
var result:Double = 0
switch operateur {
case "+":
result = a+b
case "-":
result = a-b
case "/":
result = a/b
case "*":
result = a*b
default:
print ("Erreur opérateur")
}
print (a, operateur, b, " = ", result)
}
Peut-être une erreur avec l’opérateur de multiplication ? J’ai remarqué que ton code effectue le test sur la chaîne « x », alors qu’on utilise plutôt « * ».
Tout d’abord, merci de ta réponse et du test. Concernant la chaine « x » ça n’a aucune incidence, on pourrait mettre « a » pour les additions, « s » pour les soustraction, « d » pour les division et « m » pour les multiplications ce ne sont que des valeurs de type String.
Sinon en déclarant ma variable var result:Double? comme une optionnel et en utilisant _previousNumber = resultat! et ui_displayedNumber.text = "\(result!)" j’ai réglé le problème du Warning de Xcode et je peux lancer le simulateur.
Et j’ai trouvé d’où venait le bug dans mes calcul ! A force de gratter j’ai fini par comprendre qu’il fallait impérativement déclarer la variable result = _currentNumber dans la partie ‹ default › du SWITCH…CASE.
Voici le code corrigé est utilisable pour ceux que ça intéresse :
func performingCalculous() {
var result:Double?
switch _typeOperation {
case "+":
result = _previousNumber + _currentNumber
case "-":
result = _previousNumber - _currentNumber
case "/":
if _currentNumber != 0 {
result = _previousNumber /_currentNumber
}
case "x":
result = _previousNumber * _currentNumber
default:
result = _currentNumber
}
_previousNumber = resultat!
_shouldResetCurrentNumber = true
ui_displayedNumber.text = "\(result!)"
}
@mbritto pourquoi faut il déclaré result = _currentNumber dans le default pour que cela fonctionne correctement ? il me semblait que le default était pour gérer tout les autres cas non défini.
Salut,
Alors normalement, une variable ne peut être vide donc, si tu switch passe par le default et qu’une valeur ne lui est pas attribuée celle-ci sera vide.
C’est pour cela que les optionnels existe pour gérer le cas, ou une variable peut-être vide.
Tu peut même faire une amélioration et mettre result = nil dans ton default et ensuite mettre une condition sur ton displayNumber.text, en affichant erreur si result = nil et sinon afficher le result.
[quote="alexandre.cane, post:5, topic:680 »]
il me semblait que le default était pour gérer tout les autres cas non défini.
[/quote]
Oui, le default est pour gérer les cas non défini. Ta première intuition était la bonne. D’ailleurs, tu peux le constater sur l’exemple que je t’ai montré. Tu devrais placer des print() un peu partout dans ton programme pour suivre l’évolution des choses.
Oui, je sais. Je débute en Swift, mais j’ai 25 ans de pratique avec d’autres langages. J’ai perdu un temps incalculable dans des erreurs comme coder « * » une information dans une chaîne de caractère et comparer sa valeur avec « x » ailleurs dans le programme.
Je n’ai pas fait le toto de Maxime sur la calculatrice, mais il me semble bien que le bouton de la multiplication est une « * ». En récupérant l’identifiant en lisant le texte du bouton, c’est un « * » que que l’on obtient, d’où la possibilité d’une erreur à la lecture d’un « x » dans la routine de calcul.
Désolé, mais non… Ce n’est pas la source de ton problème. Regarde, j’ai modifié ton programme pour visualiser le déroulement des opérations, en initialisant result à 0. Cela fonctionne très bien, sans modifier sa valeur dans le default.
En affichant la valeur des données, on peut suivre ce que fait le programme, et voir précisément où cela cloche. En regardant le low des tests, on voit bien que le default: n’est appelé qu’une fois, quand l’opérateur est « zog zog ».
J’ajoute que dire « les calculs sont mauvais » sans donner d’exemples précis n’ai pas d’une grande aide pour comprendre d’où vient le problème. Sont-ils toujours erronés, ou seulement dans certaines conditions (avec un opérateur précis par exemple). Il faut donner des exemples, avec les valeurs d’entrées et de sortie des variables.
En y réfléchissant l’utilisation d’un optionnel pour result est une idée intéressante, à cause de l’erreur de division par zéro. Il faudrais modifier le code du diviseur pour affecter nil à result si le diviseur est 0. Et afficher un texte comme « 9999999999 » (comme une vraie calculatrice) à la fin des opérations si result est nul.
Effectivement j’ai peu être un peu baclé ma description du problème. En comprenant mieux mon code s’était l’affichage de la variable var _currentNumber qui n’apparaissait pas au bon moment.
Lorsque je faisait 1 + 2, le chiffre 1 s’affichait bien mais lorsque je cliquais sur le 2 s’était 0 qui s’affichait soit le ui_diplayedNumber.text qui ne donnait pas la bonne valeur. Mais derrière les calcules finissaient par être bon et cela peu importe l’opérateur.
Je reviens pour apporter des précision.
Alors, c’est bien je que j’ai dit plus haut car, enfaite tu veut afficher ta variable result après ton switch et donc, si il passe par le default il n’y auras aucune valeur dedans.
La prochaine fois met une capture d’écran, nous comprendrons mieux.