Exercice — partie théorique puis partie pratique (séries de préparation à l'épreuve pratique)
On se propose d'écrire un programme intitulé Cryptage qui crypte un message, une chaîne ch formée uniquement de lettres majuscules et d'espaces, de 1 à 50 caractères. Chaque lettre est remplacée par celle qui la suit de p positions dans l'alphabet, avec 1 ≤ p ≤ 25 ; la lettre qui suit "Z" est "A", et le caractère espace ne subit aucune modification. On rappelle que Ord("A") = 65 et Ord("Z") = 90.
Exemple : pour ch = "BAC PRATIQUE" et p = 3, le message crypté est "EDF SUDWLTXH".
Pour la partie pratique, on a réalisé sous QtDesigner l'interface ci-dessous, enregistrée sous le nom cryptage.ui ; le nom de chaque objet est indiqué à sa droite.
- Partie 1 — théorique. Écrire l'algorithme d'une fonction Valide(ch) qui retourne Vrai si
chcontient entre 1 et 50 caractères, tous des lettres majuscules ou des espaces, et Faux sinon. Dresser le tableau de déclaration des objets locaux. - Écrire l'algorithme d'une fonction Crypter(ch, p) qui retourne le message crypté, et dresser le tableau de déclaration de ses objets locaux.
- Donner le résultat de l'appel
Crypter("XYZ BAC", 4), en détaillant le calcul pour la lettre"X". - Partie 2 — pratique. Pour chacun des objets
txtMsg,txtP,btnCrypteretlblRes, donner sa classe (QLineEdit, QPushButton ou QLabel) et l'instruction Python qui permet de lire son contenu, d'y écrire, ou de le relier à un module. - Écrire en Python les fonctions
valide(ch)etcrypter(ch, p)correspondant aux algorithmes de la partie 1. - Écrire le module
traiter()exécuté lors d'un clic sur le bouton Crypter : il lit le message et la valeur dep, puis affiche danslblResle message crypté si la saisie est correcte, et le message"Saisie invalide"sinon. - Compléter le programme principal en exploitant l'annexe ci-dessous, puis donner le texte affiché dans
lblRespour les saisies suivantes :"XYZ BAC"et"4";"Bac 2026"et"3";"ZOO"et"30".
Annexe
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QApplication
………………………………
app = QApplication([])
windows = loadUi("nom_fichier.ui")
windows.show()
windows.nom_bouton.clicked.connect(nom_module)
app.exec_()Voir la correction commentéeAprès avoir posé votre démarche
1. Idée : un parcours qui s'arrête au premier caractère interdit ; la longueur est testée avant tout accès à ch[i].
Fonction Valide (ch : Chaîne) : Booléen
DEBUT
ok ← (Long(ch) ≥ 1) ET (Long(ch) ≤ 50)
i ← 0
Tant que ok ET (i < Long(ch)) Faire
ok ← (ch[i] ∈ ["A".."Z"]) OU (ch[i] = " ")
i ← i + 1
Fin Tant que
Retourner ok
FINTDOL de Valide : ok — booléen — résultat du contrôle ; i — entier — indice du caractère examiné.
2. Idée : travailler sur le rang de la lettre, 0 pour "A" et 25 pour "Z" ; ajouter p puis prendre le reste modulo 26 fait passer de "Z" à "A" sans aucun test.
Fonction Crypter (ch : Chaîne ; p : Entier) : Chaîne
DEBUT
res ← ""
Pour i de 0 à Long(ch) - 1 Faire
Si ch[i] = " " Alors
res ← res + " "
Sinon
res ← res + Chr((Ord(ch[i]) - 65 + p) Mod 26 + 65)
FinSi
Fin Pour
Retourner res
FINTDOL de Crypter : res — chaîne — message crypté en construction ; i — entier — indice du caractère traité.
3. Pour "X" : Ord("X") - 65 = 23, (23 + 4) Mod 26 = 1, et Chr(1 + 65) = "B". De même "Y" donne "C", "Z" donne "D", puis "B", "A", "C" donnent "F", "E", "G" ; l'espace est conservé. Le résultat est "BCD FEG".
4.
| Objet | Classe | Instruction Python |
|---|---|---|
txtMsg | QLineEdit | windows.txtMsg.text() lit le message |
txtP | QLineEdit | windows.txtP.text() lit p, sous forme de chaîne |
btnCrypter | QPushButton | windows.btnCrypter.clicked.connect(traiter) relie le clic au module |
lblRes | QLabel | windows.lblRes.setText(…) écrit le résultat |
5. Idée : traduire ligne à ligne — Long devient len, Ord et Chr deviennent ord et chr, Mod devient %, la boucle Pour devient for … in range(…).
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QApplication
def valide(ch):
ok = 1 <= len(ch) <= 50
i = 0
while ok and i < len(ch):
ok = ("A" <= ch[i] <= "Z") or ch[i] == " "
i = i + 1
return ok
def crypter(ch, p):
res = ""
for i in range(len(ch)):
if ch[i] == " ":
res = res + " "
else:
res = res + chr((ord(ch[i]) - 65 + p) % 26 + 65)
return res6. Idée : dans une interface, on ne redemande pas la saisie dans une boucle ; on contrôle une fois, au clic, et on affiche un message d'erreur. text() rend toujours une chaîne : on teste isdigit() avant d'appeler int().
def traiter():
ch = windows.txtMsg.text()
sp = windows.txtP.text()
if valide(ch) and sp.isdigit() and 1 <= int(sp) <= 25:
windows.lblRes.setText(crypter(ch, int(sp)))
else:
windows.lblRes.setText("Saisie invalide")Grâce à l'évaluation de gauche à droite de and, int(sp) n'est jamais calculé lorsque sp contient autre chose que des chiffres.
7.
app = QApplication([])
windows = loadUi("cryptage.ui")
windows.show()
windows.btnCrypter.clicked.connect(traiter)
app.exec_()"XYZ BAC" et "4" : l'étiquette affiche BCD FEG (question 3). "Bac 2026" et "3" : Saisie invalide, car le message contient des minuscules et des chiffres. "ZOO" et "30" : Saisie invalide, car p = 30 dépasse 25.