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

Signaler
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
-
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
-
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
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021
850
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.
1
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 65492 internautes nous ont dit merci ce mois-ci

Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
7 >
Messages postés
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021

J'ai essayé ta deuxième solution et ça a fonctionné. J'insérerai le code plus tard. Merci pour ton aide yb_be.
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
7 >
Messages postés
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021

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";
Messages postés
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021
850 >
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021

je pense que tu peux faire cela avec l'instruction LAST.
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
7 >
Messages postés
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021

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
Messages postés
373
Date d'inscription
dimanche 6 novembre 2005
Statut
Membre
Dernière intervention
31 mars 2021
7 >
Messages postés
15560
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
11 mai 2021

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