Chaînes de caractère

publicité
TP 6 Chaı̂nes de caractères
TP 6
24
Chaı̂nes de caractères
Créez un nouveau répertoire de travail Z:\Prog\TP6 pour les scripts de ce TP.
6.1
Résumé du cours
6.1.1
Chaı̂ne et indiçage
Les chaı̂nes de caractères sont des objets Python, qui (comme les tableaux) peuvent être manipulées en tant que
variables
indicées
:
chaque
caractère
de
la
chaine
est
accessible
par
la
notation
chaine[indice] où l’indice est un entier allant de 0 jusqu’à len(chaine)-1. le nombre de caractère de la chaı̂ne
est fournit par la fonction intégrée len. Ainsi :
— maChaine[0] est le premier caractère de maChaine ;
— maChaine[1] est le deuxième caractère de maChaine ;
— ...
— maChaine[len(maChaine)-1] est le dernier caractère de maChaine.
Les indices peuvent être des nombres négatifs (commençant à 1), pour compter les caractères à partir de la
fin (de droite à gauche).
6.1.2
Slicing
Python permet aussi de récupérer une sous-chaı̂ne par la technique dite de slicing : les caractères de la souschaı̂ne sont indicés dans un intervalle de la forme : [indiceDebut:indideFin]. Par exemple :
1
2
3
4
5
6
7
8
9
>>> maChaine = u " L ’ h i p p o p o t o m o n s t r o s e s q u ip é daliophobie est la peur des mots trop long . "
>>> maChaine [:2]
" L ’"
>>> maChaine [0:2]
" L ’"
>>> maChaine [2:37]
" h ip p o p ot o m o n s t r o s e s q u i p é daliophobie "
>>> maChaine [39:]
" est la peur des mots trop long . "
6.1.3
Caractères spéciaux (non imprimables)
Une chaı̂ne peut comporter des caractères spéciaux, des caractères non imprimables. Par exemple :
— le retour chariot est ’\n’
— la tabulation est ’\t’
— le backslash est ’\\’ .
L’apostrophe peut être échappée par \’ si elle doit apparaitre dans une chaı̂ne délimitée par des apostrophes. Il
en est de même pour les guillemets. Une chaı̂ne peut être déclarée sur plusieurs lignes. Elle est délimitée alors
par des triples guillemets (""").
6.1.4
Des objets non mutables
Les chaı̂nes ne sont pas mutables c’est-à-dire qu’une partie de chaı̂ne ne peut pas être modifiée indépendamment.
Ainsi la mise en majuscule du premier caractère de maChaine = ’une phrase’ n’est pas possible par maChaine[0]
= "U" mais par maChaine = "U"+ maChaine[1:].
6.1.5
Fonctions et méthodes pour les chaines
— Cf. http://docs.python.org/library/string.html#module-string et plus particulièrement les sections 7.1.1 et 7.1.6, traitant de la bibliothèque string définissant des constantes utiles
— Cf. http://docs.python.org/library/stdtypes.html#string-methods traitant de la classe str et de
ses méthodes
TP 6 Chaı̂nes de caractères
6.2
25
Manipulations basiques des index et du slicing
Dans l’interpréteur Python, déclarez la variable maChaine contenant "Définitivement, j’aime Python!" (ou
tout autre texte de votre choix). Trouvez et testez les expressions qui affichent : 1 le premier caractère de la chaine,
2 le dernier (2 possibilités), 3 les trois premiers caractères de la chaine, 4 les trois derniers (2 possibilités), 5 les
caractères entre le troisième et l’avant-dernier.
Que se passe-t-il lorsque l’un des indices de découpage (slicing ) d’une chaine est erroné ? On testera notamment le
cas où le second indice est plus petit que le premier, et le cas où le second indice est plus grand que la taille de la
chaine.
Programme affichageSimple.py : Dans le script nommé affichageSimple.py, écrivez (comme en TD)
un programme qui demande la saisie d’une chaı̂ne puis affiche chaque caractère de celle-ci sur une nouvelle ligne.
Programme recherche.py : Dans un script Python nommé recherche.py, on souhaite programmer une
fonction de recherche équivalente à la méthode find de la classe str.
A : Écrivez une fonction trouve(chaine, caractere) ayant deux paramètres chaine et caractere qui cherche
si le caractere est présent dans la chaine, et si oui, renvoie l’indice de la première occurrence du caractère
trouvé dans la chaı̂ne. Si le caractère n’est pas trouvé, la fonction renverra 1. La fonction écrite ne devra
(bien entendu) pas utiliser la méthode find ni la méthode index.
Par exemple, trouve("Bonnie et Clyde", "e") devra renvoyer 5, tandis que l’instruction : trouve("Bonnie
et Clyde", "a") devra renvoyer 1.
Testez votre fonction dans le programme principal avec les exemples ci-dessus et comparez les résultats avec
ceux de la méthode find de la classe str.
B : Améliorez la fonction trouve(chaine, caractere) précédente en implémentant une nouvelle fonction
trouveV2(chaine, caractere, indiceDebut) ayant un troisième paramètre : l’indice à partir duquel la recherche doit s’e↵ectuer dans la chaı̂ne. Comme précédemment, trouveV2(chaine, caractere, indiceDebut)
renvoie l’indice de la première occurrence de caractere dans chaine, mais en commençant cette fois la
recherche dans la chaine à partir du caractère d’indice indiceDebut.
Ainsi, l’instruction : trouveV2("Tarzan et Jane", "a", 2) devra renvoyer : 4 (et non 1, l’indice du premier
’a’ ! qui est inférieur à l’indice du début de la recherche). De même, trouveV2("Tarzan et Jane", "a", 7)
devra renvoyer : 11.
Testez cette fonction en comparant son résultat à celui de la méthode find (utilisée avec deux paramètres).
On pourra chercher une solution utilisant trouve et un slicing.
C : Améliorez la fonction trouveV2(chaine, caractere, indiceDebut) précédente en implémentant la fonction
trouveV3(chaine, caractere, indiceDebut, indiceFin) ayant un quatrième paramètre : l’indice à la fin
duquel la recherche doit s’e↵ectuer. Ainsi, l’instruction : trouveV3("Cyrano et Roxane", "o", 6, 10) devra
renvoyer -1 . On pourra aussi chercher une solution utilisant trouve ou trouveV2 et un slicing.
Testez cette fonction en comparant son résultat à celui de la méthode find (utilisée avec trois paramètres).
6.3
Un peu de cryptographie sur les chaı̂nes
La cryptographie (voir http://fr.wikipedia.org/wiki/Cryptographie) est l’art de rendre illisible un message pour qui ne détient pas un secret (ou clé) permettant de déchi↵rer ce message. Diverses techniques ont
traversé l’Histoire, les plus anciennes et simples étant celles qui traitent de caractères, dans un alphabet minimum
ne comportant que des lettres majuscules et sans ponctuation.
Une bibliothèque Python, nommée crypto, est disponible sur le site du TP pour faciliter ce traitement. Cette
bibliothèque est contenue dans le fichier crypto.pyc qui doit être copié dans votre répertoire de travail. Vos
scripts Python utilisant la bibliothèque doivent comporter la directive d’import import crypto en début de
script. Cette bibliothèque comporte les fonctions :
3 crypto.formatChaine(chaine) : renvoie la chaine passée en paramètre sans d’autres caractères que des
lettres en majuscules sans accents, cédilles etc.
TP 6 Chaı̂nes de caractères
26
3 crypto.suppDiacritique(chaine) : renvoie la chaine passée en paramètre sans les diacritiques françaises
(c’est-à-dire les accents, les cédilles, etc.)
Programme rot13.py : Le chi↵rement ROT13 s’obtient en décalant chaque caractère de la chaı̂ne initiale
de 13 rangs dans l’ordre alphabétique (voir http://fr.wikipedia.org/wiki/ROT13). L’avantage de cette méthode
de chi↵rement est que le décryptage est identique au cryptage dans le cas d’un alphabet de 26 lettres.
Dans un script Python nommé rot13.py, écrivez une fonction ROT13(chaine) qui e↵ectue le cryptage ROT13 d’une
chaı̂ne de caractère passée en paramètre. La fonction renvoie la chaı̂ne cryptée.
Vous pourrez utiliser :
— la fonction crypto.formatChaine( chaine )
— la constante string.uppercase (chaı̂ne des majuscules)
— la méthode chaine.find( sousChaine ) appliquée aux chaı̂nes (voir http://docs.python.org/2.7/library/
stdtypes.html#string-methods).
Vérifiez le bon fonctionnement de la fonction ROT13 dans le programme principal en affichant un texte à crypter, le
texte crypté par ROT13 puis décrypté.
Programme cesar.py : Le chi↵re de César (voir http://fr.wikipedia.org/wiki/Chi↵rement par décalage)
est une généralisation de la technique ROT13 : chaque caractère du message chi↵ré correspond au caractère du
message en clair décalé d’un nombre entier quelconque modulo 26. Ce nombre est la clé secrète permettant de
déchi↵rer le message.
Dans un script Python nommé cesar.py :
1. Écrivez une fonction cesar(chaine, cle) qui réalise le chi↵rement de la chaine passée en paramètre suivant la
technique du chi↵re de César utilisant l’entier cle passé en paramètre. La fonction renverra la chaı̂ne cryptée.
2. Écrivez ensuite la fonction rasec(chaineCryptee, cle) qui décrypte la chaineCryptee passée en paramètre
avec la cle fournie. En réfléchissant un peu cette fonction ne contient qu’une ligne...
3. Écrivez enfin un programme qui demande à l’utilisateur de saisir une chaine puis un entier positif (la saisie
conforme de ce nombre étant à vérifier). Le programme transformera ensuite la chaine pour ne garder que
des majuscules (en utilisant la fonction formatChaine(chaine)) puis appelle la fonction cesar(chaine, cle)
pour crypter la chaine suivant le chi↵re de César avec pour clé l’entier saisi. Le programme affichera la chaine
cryptée sur la console. Enfin, il utilisera la fonction rasec(chaineCryptee, cle) pour décrypter la chaine et
affichera le résultat décrypté sur la console pour vérifier le bon fonctionnement de cesar.
Programme cryptanalyse.py : La cryptanalyse est l’art de décoder un message crypté sans posséder
la clé de chi↵rement. On souhaite ici e↵ectuer la cryptanalyse d’un message codé par le chi↵re de César (voir
http://fr.wikipedia.org/wiki/Chi↵rement par décalage#Analyse fréquentielle) : la lettre ”E” étant de loin la plus
utilisée statistiquement dans le vocabulaire français ou anglais, il y a de fortes chances pour que la lettre la plus
fréquente dans le message chi↵ré corresponde à la lettre ”E”. La clé pourra donc être déduite du décalage entre
l’index du caractère le plus fréquent dans le texte crypté et l’index de ”E”. On parle de cryptanalyse par analyse
fréquentielle.
Cette approche revient à évaluer le nombre d’occurrence de chacune des lettres de l’alphabet dans le message et
à mémoriser le plus grand e↵ectif ainsi que la lettre la plus fréquente qui lui correspond. La clé du chi↵rement est
l’index de la lettre décalé de l’index de ”E”.
Dans un script Python nommé cryptanalyse.py, écrivez une fonction cryptanalyse( chaineCryptee ) qui e↵ectue
la cryptanalyse de la chaineCryptee passée en argument et renvoie la valeur de la clé permettant de déchi↵rer
correctement le message.
Vous pourrez utiliser la méthode chaine.count( sub ) qui renvoie le nombre total d’occurrence de sub dans chaine
et la méthode chaine.index( val ) qui renvoie l’index du premier élément de la liste qui contient la valeur val.
Réutilisez les fonctions cesar (et rasec) dans le programme principal pour tester la fonction cryptanalyse.
Pour que la cryptanalyse fonctionne bien il faut un long texte comme :
— le PEP20 (affiché dans l’interpréteur de commande par >>>import this)
— ou la traduction française proposée par Cécile TREVIAN et Bob CORDEAU :
TP 6 Chaı̂nes de caractères
27
Préfère :
la beauté à la laideur,
l’explicite à l’implicite,
le simple au complexe
et le complexe au compliqué,
le déroulé à l’imbriqué,
l’aéré au compact.
Prends en compte la lisibilité.
Les cas particuliers ne le sont jamais assez pour violer les règles.
Mais, à la pureté, privilégie l’aspect pratique.
Ne passe pas les erreurs sous silence,
... ou b^
aillonne-les explicitement.
Face à l’ambigüité, à deviner ne te laisse pas aller.
Sache qu’il ne devrait avoir qu’une et une seule façon de procéder,
m^
eme si, de prime abord, elle n’est pas évidente, à moins d’^
etre Néerlandais.
Mieux vaut maintenant que jamais.
Cependant jamais est souvent mieux qu’immédiatement.
Si l’implémentation s’explique difficilement, c’est une mauvaise idée.
Si l’implémentation s’explique aisément, c’est peut-^
etre une bonne idée.
Les espaces de nommage ! Sacrée bonne idée ! Faisons plus de trucs comme ça.
Ces textes sont disponibles sur le site du TP.
Programme vigenere.py : (Pour les étudiants bien avancés)
Lisez http://fr.wikipedia.org/wiki/Chi↵rement de Vigenère.
Dans un script Python nommé vigenere.py, réutilisez la fonction cesar et écrivez une fonction
vigenere( message, cle ) qui renvoie une chaı̂ne cryptée par le chi↵re de Vigenère. Le paramètre message contient
une chaı̂ne à crypter et le paramètre cle est une chaı̂ne contenant le secret de cryptage. Pensez à utiliser l’opérateur
modulo : % .
Vérifiez le fonctionnement de vigenere dans le programme principal avec l’exemple de Wikipédia puis écrivez la
fonction erenegiv( message, cle ) qui réalise le décryptage d’un message chi↵ré.
Téléchargement