Algo. et prog. 2 en
Logo de Python
Arnaud COUTURIER - Python 3.10

✏️ TP 2 - Calculatrice niv.3 ✔️

Question 1

On veut rendre notre programme plus sophistiqué, en permettant à l'utilisateur d'entrer directement une expression simple du type: nombre1 opération nombre2. Exemples:
10.3 + 4
5 - 8
74 * 2.08
100.81 / 41

Mais pour y arriver, on doit réviser quelques notions, donc faisons-le sur des choses plus simples avant tout. Commençons par la manipulation de tableaux / listes (ces deux termes sont synonymes). Il vous faudra vous souvenir du cours du 1er semestre sur les listes.

  1. Déclarez un tableau qui contient deux éléments: 5 et 10, et stockez-le dans une variable. Affichez-le en entier, en une seule action.
  2. Puis ajoutez-y le int 15, en utilisant deux façons de faire différentes.
  3. Sans utiliser de boucle, affichez les 3 éléments du tableau individuellement (un par un) dans la console, c'est à dire chacun sur une ligne à l'affichage.
  4. Faites de même, mais avec une boucle for.
  5. Faites de même avec une boucle while.
  6. Créez un second tableau qui contient les deux chaînes "Coucou" et "Bonjour", et stockez-le dans une variable.
  7. A l'aide d'une boucle for, ajoutez un par un chaque élément du second tableau à la fin du premier tableau.
  8. Faites de même, mais en une seule action.

					# 1
					tableau = [5, 10]
					print(tableau)

					# 2
					tableau.append(15) #<= meilleure option
					tableau.extend([15])
					tableau = tableau + [15] #<= 3ème méthode possible

					# 3
					print(tableau[0])
					print(tableau[1])
					print(tableau[2])

					# 4
					for element in tableau:
						print(element)

					# 5
					i = 0
					while i < len(tableau):
						print(tableau[i])
						i += 1

					# 6
					tableau2 = ["Coucou", "Bonjour"]

					# 7
					for element in tableau2:
						tableau.append(element)

					# 8
					tableau.extend(tableau2)
				

Remarques:

  • Question 2: ajouter un élément dans un tableau ne signifie pas ré-écrire le tableau littéralement et y ajouter l'élément, comme ceci: tableau = [5, 10, 15]. Certes 15 est ajouté dans le tableau, mais vous déclarez ainsi un second tableau avec tous les éléments précédents, simplement pour pouvoir y ajouter un nouvel élément. Comment ferez-vous si le tableau contient un milliard d'éléments? Comment ferez-vous si vous ne connaissez pas les éléments à l'avance car ils auront été remplis par plusieurs utilisateurs, ou les valeurs proviendraient de sources de données extérieures (données d'un inventaire de magasin avec des milliers de produits par exemple).
  • Question 2: la méthode append() est la meilleure approche pour ajouter un seul élément à la fin d'une liste. La méthode extend() est mieux adaptée pour concaténer deux listes, c'est à dire les mettre bout-à-bout. Ici même si on ne veut ajouter qu'un seul élément, il doit tout de même être mis dans une liste (la liste [15]) pour extend(). Les méthodes append() et extend() modifient bien la liste sur laquelle on les appelle, elles ne retournent aucun résultat. Enfin l'option tableau = tableau + [15] est la moins bonne car Python évalue l'expression (l'opérateur +), qui résulte en une nouvelle liste qui consiste en une copie de la première concaténée de la seconde. Les deux listes originales sont ensuite automatiquement supprimées si plus aucune variable ne pointe vers elles. La copie et la suppression de listes qui contiennent beaucoup d'éléments (centaines de milliers ou plus) va donner du travail inutile à la machine, et l'utilisateur risque de devoir attendre sans comprendre pourquoi.

Question 2

Poursuivons nos révisions, sur les chaînes cette fois.

  1. Déclarez une variable qui pointe sur la chaine "Bonjour".
  2. A l'aide d'une boucle for, affichez chaque lettre de la chaîne sur une ligne chacune.
  3. Faites de même avec une boucle while.

On va explorer la méthode split() des chaînes. Une méthode est une fonction, mais qu'on appelle sur un objet. La méthode split() permet de découper une chaîne en plusieurs sous-chaînes, en précisant en paramètre un caractère séparateur. Attention une chaîne ne peut être modifiée, on obtient le résultat sous forme de nouvelles chaines, mais l'originale n'est jamais modifiée.

Par exemple "Bon jour".split(" ") retourne la liste ["Bon", "jour"], car le séparateur étant le caractère espace, on obtient deux sous-chaînes. Elles sont retournées dans le bon ordre "Bon" d'abord et "jour" en second.

  1. Essayez la méthode split sur la chaine "plusieurs;champs;séparés;par;point-virgule", avec pour séparateur le caractère point-virgule.
  2. Essayez avec le caractère espace comme séparateur, et voyez ce que ça donne.

					# 1
					chaine = "Bonjour"

					# 2
					for c in chaine:
						print(c)

					# 3
					i = 0
					while i < len(chaine):
						print(chaine[i])
						i += 1

					# 4
					résultat_de_split = "plusieurs;champs;séparés;par;point-virgule".split(";")
					print(résultat_de_split)
					# ↑ affiche: ['plusieurs', 'champs', 'séparés', 'par', 'point-virgule']

					résultat_de_split = "plusieurs;champs;séparés;par;point-virgule".split(" ")
					print(résultat_de_split)
					# ↑ affiche: ['plusieurs;champs;séparés;par;point-virgule']
				

Remarques:

  • Le résultat de split() est toujours une liste, même si celle-ci ne contient qu'un seul élément dans le cas où la chaîne n'aurait pas pu être coupée en plusieurs morceaux, si le caractère séparateur spécifié en paramètre de split() n'existe pas dans la chaîne.

Question 3

Reprenons notre programmation d'une calculatrice, on veut rendre notre programme plus sophistiqué, en permettant à l'utilisateur d'entrer directement une expression simple du type: nombre1 opération nombre2. Exemples:
10.3 + 4
5 - 8
74 * 2.08
100.81 / 41.

L'utilisateur doit entrer exactement un caractère espace entre les nombres et l'opération, on ne considère pas les cas où l'utilisateur rentre des espaces en trop. On ne considère pas non plus pour le moment les cas où l'utilisateur fait des erreurs dans son expression simple, comme par exemple ne rentre pas une opération supportée, ne rentre pas un nombre, etc...

A la fin affichez simplement sur une nouvelle ligne le signe "=" suivi du résultat. Inutile de ré-afficher l'expression du calcul, puisque l'utilisateur l'aura déjà entrée en entier. Par exemple:
Entrez une expression simple: 5 + 6
= 11


					expression = input("Entrez une expression simple: ")
					éléments = expression.split(" ")
					nb1 = float(éléments[0])
					op = éléments[1]
					nb2 = float(éléments[2])

					if op == "+":
						print("=", nb1 + nb2)
					elif op == "-":
						print("=", nb1 - nb2)
					elif op == "/":
						print("=", nb1 / nb2)
					else:
						print("=", nb1 * nb2)
				

Question 4

A partir de la solution précédente, considérer les cas où l'utilisateur fait des erreurs dans les nombres. Redemander d'entrer l'expression entiere tant que l'un des deux nombres n'en est pas un.


					nb_est_correct = False
					while not nb_est_correct:
						try:
							expression = input("Entrez une expression simple: ")
							éléments = expression.split(" ")
							nb1 = float(éléments[0])
							op = éléments[1]
							nb2 = float(éléments[2])
							nb_est_correct = True
						except:
							print("Vous avez entré un mauvais nombre.")

					if op == "+":
						print("=", nb1 + nb2)
					elif op == "-":
						print("=", nb1 - nb2)
					elif op == "/":
						print("=", nb1 / nb2)
					else:
						print("=", nb1 * nb2)
				

Remarques:

  • Pourquoi dans le bloc except on peut écrire print("Vous avez entré un mauvais nombre.")? Comment peut-on être sûr que le bloc except sera exécuté quand l'utilisateur aura entré un mauvais nombre?

    Parce que dans le bloc try correspondant (donc celui juste au dessus), seules les fonctions float() peuvent provoquer des erreurs à l'exécution quand leur paramètre ne représente pas un nombre, et donc le except sert uniquement à gérer ces cas d'erreurs.

Question 5

A partir de la solution précédente, considérer les cas où l'utilisateur n'entre pas une opération supportée (+, -, *, /). Redemander d'entrer l'expression entiere tant que l'opération entrée est incorrecte.


					nb_est_correct = False
					while not nb_est_correct:
						try:
							expression = input("Entrez une expression simple: ")
							éléments = expression.split(" ")
							nb1 = float(éléments[0])
							op = éléments[1]
							if op not in ["+", "-", "/", "*"]:
								print("Opération non reconnue: ", op)
								continue
							nb2 = float(éléments[2])
							nb_est_correct = True
						except:
							print("Vous avez entré un mauvais nombre.")

					if op == "+":
						print("=", nb1 + nb2)
					elif op == "-":
						print("=", nb1 - nb2)
					elif op == "/":
						print("=", nb1 / nb2)
					else:
						print("=", nb1 * nb2)
				

Remarques:

  • Vous devez vous souvenir de ce que fait continue: cette instruction ne peut se mettre que dans une boucle (donc while ou for), et dès qu'elle est exécutée, la boucle est immédiatement relancée pour la prochaine itération. Le reste des instructions de la boucle qui auraient dû être exécutées sont ignorées.

Question 6

A partir de la solution précédente, considérer les cas où l'utilisateur ajoute des espaces en trop (mais il / elle doit toujours entrer au moins un espace entre opérandes et opérateurs). Vous ne devez pas afficher un message d'erreur, mais ignorer les espaces en trop, et faire le bon calcul malgré tout. Prendre aussi en compte les espaces en trop au début et à la fin de l'expression de l'utilisateur. Mais on considère toujours que l'utilisateur rentre le bon nombre d'éléments, qui est 3, et dans le bon ordre (nb1, opération, nb2).

Exemples d'expressions avec des espaces en trop, mais quand même considérées correctes par notre calculatrice:
"   5.0   + 1  "
" 8 /  9.1   "


					nb_est_correct = False
					while not nb_est_correct:
						try:
							expression = input("Entrez une expression simple: ")
							éléments = expression.split(" ")
							éléments_corrects = []
							# on enlève les espaces en trop avant tout
							for el in éléments:
								if el != "":
									éléments_corrects.append(el)
							nb1 = float(éléments_corrects[0])
							op = éléments_corrects[1]
							if op not in ["+", "-", "/", "*"]:
								print("Opération non reconnue: ", op)
								continue
							nb2 = float(éléments_corrects[2])
							nb_est_correct = True
						except:
							print("Vous avez entré un mauvais nombre.")

					if op == "+":
						print("=", nb1 + nb2)
					elif op == "-":
						print("=", nb1 - nb2)
					elif op == "/":
						print("=", nb1 / nb2)
					else:
						print("=", nb1 * nb2)
				

Remarques:

  • l'approche de la solution c'est éliminer les caractères espaces en trop, pour cela on crée une seconde liste éléments_corrects qui contiendra 3 éléments: juste les deux nombres et l'opérateur entre les deux. Puis on analyse la liste des éléments retournés par la méthode split() exécutée sur l'expression entrée par l'utilisateur.

    Dans la boucle for el in éléments on ignore les chaînes vides, elles sont créées par split() car étant donné qu'on a spécifié le caractère espace comme séparateur, split() considère qu'entre deux espaces il y a une chaîne vide, dans la chaîne de l'expression de l'utilisateur..