Boucles imbriquées WHILE qui ne fonctionnent pas

Résolu/Fermé
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 - 18 déc. 2019 à 17:58
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 - 21 déc. 2019 à 17:50
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

yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024 1 476
18 déc. 2019 à 18:41
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
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
18 déc. 2019 à 20:27
Salut yg_be,

Qu'est-ce que je devrais changer au programme pour que celui-ci lise le fichier B un nombre de fois égal au nombre de lignes que contient le fichier A?

Merci pour ta réponse.
0
yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024 1 476 > artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024
18 déc. 2019 à 23:07
je pense à deux solutions:
1) utiliser seek pour se repositionner en début de fichier B en ligne 27
2) déplacer le open de B en ligne 27, et le close de B en ligne 36
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7 > yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024
19 déc. 2019 à 00:36
Je vais essayer ça. Merci.
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7 > yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024
19 déc. 2019 à 03:09
J'ai essayé ta deuxième solution et ça a fonctionné. J'insérerai le code plus tard. Merci pour ton aide yb_be.
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7 > yg_be Messages postés 22724 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 25 avril 2024
19 déc. 2019 à 19:32
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";
0