Boucles imbriquées WHILE qui ne fonctionnent pas [Résolu]

Signaler
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
-
artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
-
Bonjour,

Je veux écrire un programme qui cherche les mots qui se trouvent en commun dans deux fichiers texte. Les deux fichiers ne possèdent qu'un seul mot par ligne. Par exemple, avec les deux fichiers suivants :

fich_a.txt

album
an
art
attrape
avant
avion


fich_b.txt

album
anniversaire
artichaut
attirail
avant
avoir

le programme devrait générer le fichier de sortie paires.txt suivant :

album
avant

Le programme que j'ai écrit s'exécute mais il n'écrit qu'un seul mot (album) dans le fichier paires.txt. Il n'entre pas une seconde fois dans la boucle WHILE interne. C'est ce que je ne comprends pas.

Voici le code :

#  Programme trouver_les_paires.pl

#  Programme qui trouve les mots qui se trouvent à la fois dans deux fichiers (fich_a.txt,
#  fich_b.txt). Il n'y a qu'un seul mot par ligne dans chacun des fichiers.
#
#  Le programme lit le premier mot dans le fichier fich_a.txt et le compare au premier mot 
#  du second fichier. Si les mots sont les mêmes, le programme copie le mot dans le fichier #  paires.txt. Sinon, il lit le second mot du fichier fich_b.txt et fait la comparaison et #  ainsi de suite.
#
#  Une fois que la lecture du fichier fich_b.txt est complétée pour le premier mot du 
#  fichier fich_a.txt, le programme lit le second mot du fichier fich_a.txt puis recommence
#  la lecture du second fichier. Il recommence jusqu'à ce que tous les mots du premier 
#  fichiers aient été lus.

#!/usr/bin/perl

use strict;
use warnings;

open(FICHIER_A, "fich_a.txt") or die "Le fichier ne s'ouvre pas: $!";
open(FICHIER_B, "fich_b.txt") or die "Le fichier ne s'ouvre pas: $!";
open(FICHIER_PAIRE, ">paires.txt") or die "Le fichier ne s'ouvre pas: $!";
my $x1;

while(<FICHIER_A>)
{
$x1 = "$_";

while(<FICHIER_B>)
{
my $x2 = "$_";
print "$x1";       # Uniquement pour visualiser ce que fait le programme.
print "$x2\n";     # Uniquement pour visualiser ce que fait le programme.
if ($x1=~$x2)
{print FICHIER_PAIRE "$x2"}
}

print "$x1";       # Uniquement pour visualiser ce que fait le programme.
}

close FICHIER_A;
close FICHIER_B;
close FICHIER_PAIRE;


Merci

Configuration: Windows / Chrome 79.0.3945.79

1 réponse

Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020
500
bonjour,
quand le programme arrive pour la seconde fois au début de la boucle interne, il a déjà lu tout le fichier B, donc il me semble normal qu'il se comporte comme tu observes.
artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
6 > yg_be
Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020

J'ai essayé ta deuxième solution et ça a fonctionné. J'insérerai le code plus tard. Merci pour ton aide yb_be.
artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
6 > yg_be
Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020

Bonjour,

Le programme est fonctionnel mais il n'est pas optimal. En effet, lorsque le programme trouve deux mots identiques, il continue la lecture du fichier B. Idéalement, il devrait sortir de la boucle interne car chaque mot ne se retrouve qu'une fois dans chaque fichier. Il devient donc inutile de continuer la lecture du fichier B lorsqu'un mot a été trouvé. Je vais tenter d'insérer une commande comme BREAK si ça existe dans Perl.

Voici le code :

#!/usr/bin/perl

use strict;
use warnings;

my $fich_a="fich_a.txt";
my $fich_b="fich_b.txt";

open(FICHIER_A, $fich_a) or die "Le fichier ne s'ouvre pas: $!";
open(FICHIER_PAIRE, ">paires.txt") or die "Le fichier ne s'ouvre pas: $!";

my $x1;
my $cptr=0;

while(<FICHIER_A>)
{
$x1 = "$_";
open(FICHIER_B, $fich_b) or die "Le fichier ne s'ouvre pas: $!";

while(<FICHIER_B>)
{
my $x2 = "$_";
if ($x1=~$x2)
{print FICHIER_PAIRE "$x2";
$cptr++;}
}
close FICHIER_B;
}

close FICHIER_A;
close FICHIER_PAIRE;
print "\nIl y a $cptr mots en commun dans les deux fichiers.\n\n";
yg_be
Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020
500 > artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019

je pense que tu peux faire cela avec l'instruction LAST.
artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
6 > yg_be
Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020

Salut,

La fonction LAST a réglé le problème.

Je me suis rendu compte qu'il y avait un autre problème. Lorsque le programme est rendu à un quelconque mot du fichier A, il recommence la lecture du fichier B et le lit à partir du début. Ça ne devrait pas être le cas.

Par exemple, si j'ai les deux fichiers suivants:

Fichier A ******* Fichier B

avion ******* an
bateau ****** date
pont ******** ferme
quille ******* raisin
tableau ****** sapin

et que le programme saisit le mot pont, il lit le fichier B à partir du début alors qu'il devrait le lire à partir du mot raisin.

Le programme est fonctionnel mais est loin d'être parfait.

Merci yg_be
artagon7
Messages postés
283
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
21 décembre 2019
6 > yg_be
Messages postés
9425
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
28 janvier 2020

Je vais essayer de travailler avec la fonction seek que tu as mentionnée précédemment et tell.