Script Perl pour compter une occurence dans une ligne avec mots

Fermé
laisso - 11 nov. 2014 à 18:27
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 17 nov. 2014 à 14:06
Bonjour,

J'ai des difficultés à exécuter ce script.

# Date 11/11/2014

#Demander à l'utilisateur de saisir autant de mots qu'il le souhaite. Il signale la fin de la saisie en entrant "@".
#Ensuite, la liste des mots qu'il a saisis est affichée dans l'ordre alphabétique avec le nombre d'occurrences de chaque mot dans la liste (un mot par ligne).


#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Term::ANSIColor qw(:constants);
use List::Util qw(min max);
use List::Util qw(sum);
my $i=0;
my @L1;


print "saisissez autant de mots que vous le désirez: " ;
my $mots= <>;
chomp $mots;
say "vous avez saisi: $mots";

while ($mots !=@) {


$L1[$i]=$mots ;
$i++ ;
print "saisissez autant de mots que vous le désirez : " ;
$mots= <> ;
chomp $mots ;
say "vous avez saisi :$mots" ;

}

say(BOLD,RED,"> Terminé !",RESET) ;

foreach $line (@fcont) {
$compte =()= $line =~ /\s/g;
$compte++;
print FOUT $compte;
print FOUT "\n"
A voir également:

2 réponses

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 12/11/2014 à 14:34
Salut laisso,

Oui, effectivement :

$ ./laisso.pl 
syntax error at ./laisso.pl line 22, near "$i"
syntax error at ./laisso.pl line 28, near "}"
Global symbol "$line" requires explicit package name at ./laisso.pl line 32.
Global symbol "@fcont" requires explicit package name at ./laisso.pl line 32.
Global symbol "$compte" requires explicit package name at ./laisso.pl line 33.
Global symbol "$line" requires explicit package name at ./laisso.pl line 33.
Global symbol "$compte" requires explicit package name at ./laisso.pl line 34.
Global symbol "$compte" requires explicit package name at ./laisso.pl line 35.
Missing right curly or square bracket at ./laisso.pl line 36, at end of line
syntax error at ./laisso.pl line 36, at EOF
./laisso.pl has too many errors.


Tu dois faire
while ($mots !="@") {
, puisque le symbole "@" est un caractère.

Tu dois déclarer avec
my
toutes les variables que tu utilises.

Il manque une accolade fermante à ta boucle foreach à la fin.

Cela dit :

- @fcont sort de nulle part, cela ne serait pas plutôt @L1 ?
- tu ne fais aucun tri alphabétique
- tu veux faire quoi exactement avec
$compte =()= $line =~ /\s/g; 
, en tout état de cause, cela cela n'affichera un décompte que pour chaque ligne du tableau

Si j'étais toi, je mettrais les mots en tant que clefs d'un hash, dont la valeur serait la valeur numérique correspondant au nombre d'occurrences. Ensuite, tu tries ton hash selon les clefs avec foreach et sort, et tu affiches les clefs et leurs valeurs.


Dal
1
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 13/11/2014 à 14:34
au temps pou rmoi,
 while ($mots !="@")
est incorrect car l'opérateur de comparaison de chaînes doit aussi être changé, c'est
while ($mots ne "@")
, qui est correct.

Autrement, avec strict et warnings, tu as tous les messages d'erreur à la compilation, et à l'exécution, qui devraient permettre de te rendre compte que :

-
print: "@L2";
est incorrect et que tu dois écrire
print "@L2";
,
-
foreach $line (@L2) {
utilise une variable $line non déclarée, donc tu dois écrire
foreach my $line (@L2) {
,
-
print FOUT $compte;
utilise un identifiant de fichier non ouvert, ni déclaré, pourquoi ne pas faire simplement
print "$compte\n";
?

voilà le code corrigé

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Term::ANSIColor qw(:constants);
use List::Util qw(min max);
use List::Util qw(sum);
my $i=0;
my @L1;
my $compte=0;
my @L2;


print "saisissez autant de mots que vous le désirez: " ;
my $mots= <> ;
chomp $mots ;
say "vous avez saisi: $mots";
while ($mots ne "@") {
    $L1[$i]=$mots ;
    $i++ ;
    print "saisissez autant de mots que vous le désirez : " ;
    $mots= <> ;
    chomp $mots ;
    say "vous avez saisi :$mots" ;
}

@L2=sort @L1;
print "@L2";

say(BOLD,RED,"> Terminé !",RESET) ;

foreach my $line (@L2) {
    $compte =()= $line =~ /\s/g;
    $compte++;
    print "$compte\n";
} 


sur un exemple de saisies, cela donne cela :

$ ./laisso_corr.pl
saisissez autant de mots que vous le désirez: un
vous avez saisi: un
saisissez autant de mots que vous le désirez : deux deux
vous avez saisi :deux deux
saisissez autant de mots que vous le désirez : trois trois trois
vous avez saisi :trois trois trois
saisissez autant de mots que vous le désirez : quatre quatre quatre quatre
vous avez saisi :quatre quatre quatre quatre
saisissez autant de mots que vous le désirez : @
vous avez saisi :@
deux deux quatre quatre quatre quatre trois trois trois un> Terminé !
2
4
3
1


c'est assez illisible, surtout si tu as beaucoup de mots différents, et tu n'affiches pas un mot par ligne avec le nombre de fois que ce mot apparaît.

pourquoi ne procèdes-tu pas comme suggéré dans mon message précédent avec un hash trié par clefs ?

Dal
0
Nous n'avons pas vue encore cet aspect du chapitre. Nous nous sommes arrêté dans le chapitre liste. Pour le reste c'est compliqué. J'en suis à mon premier cours de perl avec ce type d'exercice donc c'est difficile et besoin de quelqu'un qui m'aide à corriger mes fautes.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 13/11/2014 à 18:56
j'ai corrigé les erreurs de syntaxe, mais ton code ne fonctionne pas vraiment, à moins que des mots identiques soient saisis sur les mêmes lignes (comme dans mon exemple).

En fait :

- ton code trie alphabétiquement chaque ligne et crée un tableau avec le résultat
- l'expression
$compte =()= $line =~ /\s/g;
compte les espaces dans chaque ligne, et tu incrémentes de 1 le résultat, mais cela ne fait que compter les espaces (dans chaque ligne du tableau trié), et pas les occurrences des mots

Pour une solution avec un hash, voir mon nouveau post avec un exemple de code.


Dal
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 13/11/2014 à 19:04
Dans le monde réel, pour faire cela, on utiliserai un hash, c'est absurde de faire autrement en Perl.

et c'est aussi simple que cela :

#!/usr/bin/perl

use strict;
use warnings;

my %hash;
print "saisissez autant de lignes de mots séparés " .                                                                                                                                                              
    "par des espaces que vous le désirez (saisir " .
    "@ sur une ligne pour terminer) :\n" ;
while ((my $mots = <>) ne "@\n") {
    chomp $mots;
    foreach my $mot (split /\s+/, $mots) {
        $hash{$mot}++;
    }
}
foreach my $mot (sort keys %hash) {
    print "Mot $mot :\t$hash{$mot} fois\n";
}


ce qui donne :

$ ./laisso_corr2.pl 
saisissez autant de lignes de mots séparés par des espaces que vous le désirez (saisir @ sur une ligne pour terminer) :
il était un petit navire
il était un petit navire
qui n'avait ja ja jamais navigué
qui n'avait ja ja jamais navigué
ohé ohé
ohé ohé matelot
matelot navigue sur les flots
@
Mot flots : 1 fois
Mot il : 2 fois
Mot ja : 4 fois
Mot jamais : 2 fois
Mot les : 1 fois
Mot matelot : 2 fois
Mot n'avait : 2 fois
Mot navigue : 1 fois
Mot navigué : 2 fois
Mot navire : 2 fois
Mot ohé : 4 fois
Mot petit : 2 fois
Mot qui : 2 fois
Mot sur : 1 fois
Mot un : 2 fois
Mot était : 2 fois

Dal
1
Merci. J'ai choisi d'appliquer ce code plus apte à mon gout. Bien que mon code soit aussi fonctionnel mais moins performants et moins puissants.

Merci de votre aide.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
14 nov. 2014 à 15:45
Mais je croyais que tu disais ne pas pouvoir utiliser les hash parce qu'ils n'avaient pas été enseignés ?

N'oublie pas de me citer en tant qu'auteur de ce code, ainsi tu respecteras la licence CreativeCommons applicable : https://www.commentcamarche.net/infos/25861-informations-de-copyright/ et je te souhaite bonne chance :-)

Sinon, je te confirme de nouveau que ton code ne fonctionnait pas vraiment, en fin de compte. Essaye de lui passer les mêmes entrées que le mien, et tu verras le résultat.


Dal
0
Il y a une diapo sur le hash. Je viens juste d'en voir l'utilité. Merci en tout cas. J'en ai d'ailleurs parlé avec mon responsable de formation qui m'autorise à m'aider des forums.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
17 nov. 2014 à 14:06
ok, c'est super. Tu peux donc me citer sans crainte :-)
0