T.P. 7 : manipulation de textes
1 L’algorithme de recherche dans une chaˆıne de caract`eres
On a dit en cours (chap. 7) que si on consid`ere les lignes de codes suivantes :
devise="le lutin bleu est votre ami et il est important d’avoir des amis imaginaires"
print(devise.rfind("ami"))
La m´ethode rfind sur la chaˆıne devise donne l’indice du d´ebut de la premi`ere occurrence d’une
sous-chaˆıne, en partant de la droite r.
On veut ici ´ecrire un algorithme qui fasse la mˆeme chose mais pour changer un peu, en
partant de la gauche. Le droite ou gauche n’est pas important : le but est de comprendre comment
on fait !
Cahier des charges :fabriquer une fonction recherche qui prend deux arguments partie et
tout qui sont deux chaˆınes de caract`eres et qui va d´eterminer si la chaˆıne partie apparaˆıt dans
tout et si oui `a quel indice se trouve le d´ebut de la premi`ere occurrence de partie dans tout. La
fonction retournera cet indice dans ce cas et la valeur None sinon qui est une valeur sp´eciale de
Python sinon.
2 Cryptographie : compl´ement au D.S. 2
Niveau :finir le 2) du D.S. 2 puis faire le 3
Niveau :`a l’aide du corrig´e du D.S. 2. faire le 3, pour le codage du C´esar.
Ce 3) n´ecessite un peu de documentation suppl´ementaire (internet).
1
Plan plus d´etaill´e pour le T.P. 7. paragraphe 2
2 Codage de C´esar appliqu´e `a un fichier texte
Choisir un petit texte, enregistr´e dans un fichier texte : texte_a_coder.txt
2.1 Comment lire ce texte pour obtenir une chaˆıne de caract`eres en
python ?
Cf. cours chap. 7.
2.2 Choix de l’intervalle en utf8
Si on essaie de taper un texte en fran¸cais, et si on fait un peu attention, on peut se limiter
aux caract`eres dont les num´eros utf8 sont entre 10 et 255. Par exemple 10 correspond au retour
`a la ligne et 32 au caract`ere d’espace. Attention toutefois, par exemple, u d´ebut j’avais tap´e un
premier texte avec trois points de suspension, qui ont ´et´e remplac´es par un caract`ere sp´ecial pour
les trois points, qui lui a un code uft8 `a quatre chiffres ! Donc ´ecrire une petite fonction qui v´erifie
o`u vivent les codes utf8 de votre texte, pour ˆetre sˆur que votre encodage soit correct.
On peut donc adapter la fonction represente du D.S. en cr´eant une liste de nombres entre 0
et 245, ou bien faire un autre choix plus intelligent... `a vous de voir le vˆotre !
2.3 Analyse en fr´equence : le caract`ere espace devient tr`es majoritaire
Ecrivez un test de fr´equence pour ces caract`eres et vous verrez !
2.4 Quelles variantes possibles du codage de C´esar pour r´esister `a l’ana-
lyse en fr´equence ?
a) Coder l’espace avec plusieurs num´eros diff´erents et de mˆeme pour le ’e’. Le texte ainsi fabriqu´e
devrait r´esister `a la fonction decodeCesar. Bien sˆur le nombre de chiffres de code devient
plus grand que le nombre de caract`eres de notre jeu de caract`eres.
Programmez un encodage de ce type.
b) Commencer par supprimer tous les espaces. Programmez une fonction Python qui prend en
entr´ee un fichier texte et fabrique un nouveau fichier qui contient le mˆeme texte sauf qu’on a
supprim´e tous les espaces.
Cette op´eration semble irr´eversible. En fait, `a l’aide d’un dictionnaire de mots, il serait
possible de refabriquer `a peu pr`es les espaces, mais c’est une autre histoire qu’Aliaume nous
racontera `a l’occasion !
c) Changer de principe de codage : ne plus agir sur les codes des caract`eres mais sur les s´equences
de chiffres plus longues dans le texte binaire obtenu en mettant les num´eros binaires de
caract`eres `a la suite. Comment faire ceci en Python ?
Rien qu’avec ces petites variantes, ce n’est plus si simple de d´ecoder non ?
2
C.R. du T.P. 7
1 Algorithme de recherche dans une chaˆıne de caract`eres
def recherche(partie,tout):
"""renvoie, si elle existe, la position de la premi`ere occurence
de partie dans tout et renvoie None sinon"""
for i in range(1+len(tout)-len(partie)): # le compteur i va parcourir
# tous les indices entre 0 et len(tout)-len(partie) (inclusivement)
# qui sont ceux susceptibles d’^etre au d´ebut d’une occurrence
# de partie dans tout
j=0 # `a partir de la position j on teste lettre par lettre
while j<len(partie) and partie[j]==tout[i+j]:
j+=1
# remarque le caract`ere paresseux du "and" est crucial
# si la condition j<len(partie) n’est pas v´erifi´ee, il ne va pas
# regarder l’autre condition, ce qui ´evitera un "index out of range"
if j==len(partie):
return i
return None
# L’int´er^et du None est d’^etre bien interpr´et´e par un autre programme
# qui utiliserait celui-ci
## Test
partie="bleu"
tout="le lutin bleu regarde le ciel bleu"
recherche(partie,tout)
##
Remarque On peut, en Python, faire mieux que tester l’´egalit´e lettre par lettre : on peut tester
directement l’´egalit´e des sous-listes avec les commandes d’extractions dans une liste (slicing) ce qui
enl`evera le while.
2 Codage de C´esar appliqu´e `a un fichier texte
Choix d’un petit texte, enregistr´e dans un fichier texte : texte-a-coder.txt dans le mˆeme
r´epertoire que mon script de T.P. 7.
Bon voici un petit texte que j’aimerais coder avec le codage de C´esar. J’ai mis
quand m^eme quelques accents qui font la richesse de notre belle langue `a pr´eserver,
voyons o`u cela va nous mener ? C¸a va bien bien marcher !
2.1 Comment lire ce texte en Python : cf. chap. 7
from os import chdir
chdir("/Users/romain/Documents/MPSI/Informatique/TP7-algo-recherche-texte")
Fichier=open("texte-a-coder.txt","r",encoding="utf8")# ouverture en lecture seule
contenu=Fichier.read()# cr´ee une cha^ıne de caract`eres contenant
On dispose maintenant de la chaˆıne de caract`eres contenu en m´emoire.
3
2.2 Choix de l’intervalle en utf8
Si on essaie de taper un texte en fran¸cais, et si on fait un peu attention, on peut se limiter aux
caract`eres dont les num´eros utf8 sont entre 10 et 255. Par exemple 10 correspond au retour `a la
ligne et 32 au caract`ere d’espace. C’est le cas dans le petit texte que j’ai tap´e ci-dessus. Attention
toutefois, j’avais tap´e trois points au d´ebut, qui ont ´et´e remplac´e par le caract`ere ... qui lui a un
code uft8 `a quatre chiffres !
On peut donc adapter la fonction represente du D.S. en cr´eant une liste de nombres entre 0
et 245.
def represente(texte):
"""prend en argument une cha^ıne de car. et renvoie une liste
contenant les numero utf8 des car. successifs moins 10"""
l=[]
for i in range(len(texte)):
l.append(ord(texte[i])-10)
return l
Cependant l’analyse en fr´equence va changer par rapport `a ce qui ´etait dit dans le probl`eme.
2.3 Analyse en fr´equence : le caract`ere espace devient tr`es majoritaire
Avec le mˆeme code que dans le D.S.
def frequence(tc):
freq=[0]*255
for lettre in tc: # on parcourt les valeurs de tc
freq[lettre]+=1
on obtient bien sˆur que le caract`ere num´ero 22 r´ealise le max. des fr´equences. Donc le d´ecodage de
C´esar devra en tenir compte.
2.4 Quelles variantes possibles du codage de C´esar pour r´esister `a l’ana-
lyse en fr´equence ?
a) Coder l’espace avec plusieurs num´eros diff´erents et de mˆeme pour le ’e’. Le texte ainsi fabriqu´e
devrait r´esister `a la fonction decodeCesar.
b) Comment supprimer tous les espaces :
(M1) Si on lit bien le help(str) :on y trouve une m´ethode replace :
replace(...)
| S.replace(old, new[, count]) -> str
|
| Return a copy of S with all occurrences of substring
| old replaced by new. If the optional argument count is
| given, only the first count occurrences are replaced.
|
Avec cette m´ethode, la programmation de la fonction est imm´ediate :
def supprimer_espaces (texte):
""" Supprime tous les espaces d’un texte """
return texte.replace (" ", "")
(M2) plus artisanal, mais aussi plus instructif sans utiliser la m´ethode replace
c) Comment transformer un texte en binaire :
(M1) avec l’argument suppl´ementaire "rb" pour read binary de la fonction open :
Imaginons que j’ai un fichier phrase.txt form´e d’une seule phrase : Une seule phrase,
accentu´ee `a l’envie quand m^eme. Voyons ce que fait le script suivant :
4
Fichierbin=open("phrase.txt","rb")# ouverture en lecture seule, en binaire
contenu_binaire=Fichierbin.read()
print(contenu_binaire)
>>>
b"Une seule phrase, accentu\xc3\xa9e \xc3\xa0 l’envie quand m\xc3\xaame.\n"
Cela peut paraˆıtre un peu d´ecevant, cela n’a pas l’air d’une chaˆıne binaire, mais c’est seule-
ment un choix d’affichage de Python. Ce qui est important, c’est le bqui est devant, qui dit
que c’est une chaˆıne binaire, cf. cours du chap. 7. §5.4, autrement dit un objet de la classe
bytes. La convention de repr´esentation de Python est la suivante :
les octets de valeurs num´eriques comprises entre 32 et 127 (ascii de base) sont repr´esent´es
par le caract`ere correspondant du code ASCII,
certains octets de valeur num´erique inf´erieure `a 32 sont aussi repr´esent´es de mani`ere conver-
tionnelle comme le caract`ere de fin de ligne (ASCII 10, convention Python,\n).
les autres octets sont repr´esenes par leur valeur hexad´ecimale, pr´ec´ed´ee de \x.
Ce qui compte : `a partir d’une chaine de type bytes on peut extraire un par un le
codage binaire de chaque ´el´ement de la chaˆıne.
Comment faire ? Si cest une chaˆıne de type bytes,c[i] va renvoyer le num´ero de i. Donc
`a l’aide d’une boucle
l=[]
for oct in contenu_binaire:
l.append(oct)
print(l)
>>> (executing cell "parcours de la ch..." (line 102 of "script-TP7.py"))
[85, 110, 101, 32, 115, 101, 117, 108, 101, 32, 112, 104, 114, 97, 115, 101, 44, 32, 97, 99, 99, 101, 110, 116, 117, 195, 169, 101, 32, 195, 160, 32, 108, 39, 101, 110, 118, 105, 101, 32, 113, 117, 97, 110, 100, 32, 109, 195, 170, 109, 101, 46, 10]
Cependant, pour l’objectif du c) on voudrait que ces nombres soient ´ecrit en binaire sur huit
bits : mais cela, on sait le faire !
def huitbit(n):
"""prend un entier n entre 0 et 255 et l’´ecrit sous la forme d’une chaine de caract`ere en binaire avec exactement huit bits"""
binaire=bin(oct)[2:]# renvoie une cha^ıne de caract`eres contenant
# l’´ecriture binaire mais elle n’est peut-^etre pas assez longue
formate_en_huit=binaire.zfill(8)
return formate_en_huit
##
# programme principal
seq=""
for oct in contenu_binaire:
seq+=huitbit(oct)
print(seq)
On dispose enfin d’une chaˆıne de caract`eres form´ee de 0 et de 1 o`u chaque octet (huit
caract`eres) est le num´ero utf des caract`eres de notre chaˆıne initiale
(M2)Avec la m´ethode encode sur les chaˆıne de caract`eres (cf. cours chap. 7).
C’est en gros la mˆeme chose qu’`a la (M1) sauf qu’on ouvre le fichier texte pour fabriquer
une chaˆıne str puis on encode la chaˆıne en chaˆıne bytes.
(M3) Avec la commande ord qu’on connaˆıt. Une autre commande utile dont je n’ai pas
parl´e est la commande format, distincte de la m´ethode format.
>>> format(32,’08b’)
’00100000’
On obtient alors imm´ediatement :
5
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !