IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

plusieurs arguments dans une fonction dont un hash


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 14
    Points : 17
    Points
    17
    Par défaut plusieurs arguments dans une fonction dont un hash
    Bonjour, Bonjour

    J'ai un soucis au niveau des arguments d'une fonction dans mon programme. Les arguments sont un fichier, entrée en ligne de commande et une table de hashage, qui est déjà pré-remplie (2ème fonction).
    Sur le terminal il m'est affiché :
    "Reference found where even-sized list expected at ./programme.pl line 16."
    Soit il m'est indiqué que le $file2 dans ma 2e fonction n'est pas trouvé


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ### MAIN ###
     
    use Data:: Dumper qw(Dumper);
     
    $file1 = ARGV[0];
    $file2 = ARGV[1];
     
    my %hash;
     
    %hash = hash_remplissage($file1);
    enriched_hash(\%hash, $file2);
     
    print Dumper \%hash;
    print "___________\n";
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    ### FUNCTIONS ###
     
     
    sub hash_remplissage {
     
    	<div style="margin-left:40px">my ($file1) = @_;
     
    	my %hash;
     
    	open FICHIER1, $file1;
     
    	while(<FICHIER1>) {
    		<div style="margin-left:40px">... remplissage du hash vide ...</div>	}
     
    	close FICHIER1;
     
    	return \%hash;</div>}
     
     
     
     
     
    sub enriched_hash {
     
    	<div style="margin-left:40px">my (%hash) = shift();
    	my ($file2) = shift(@_);
     
    	open (FICHIER2, $file2) or die "Can't open '$file2': $!";
     
    	while(<FICHIER2>) {
    		<div style="margin-left:40px">... ajout éléments dans hash ...</div>	}
     
    	close FICHIER2;</div>}
     
    ### END ###
    Comment fait-on pour utiliser plusieurs arguments dont un fichier et un hash ? Le hash pose le plus de problème. Sûrement dû aux références et aux pointeurs. Mais je n'arrive pas bien à cerner où cela beugue

    Merci par avance à celui ou celle qui m'aidera à comprendre et résoudre mon problème

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Intervertis l'ordre de tes paramètres et ça devrait marcher.

    Au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    enriched_hash(%hash, $file2);
    essaie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    enriched_hash( $file2, %hash,);
    Il faut bien sûr modifier aussi dans la fonction, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    sub enriched_hash {
        my ($file2, %hash) = @_;
        # ...
    }
    La raison est que si tu alimentes un hachage ou un tableau à partir de @_, le hachage ou le tableau essaie d'avaler toute la liste des arguments reçus. En mettant la variable $file2 en premier, tu récupère d'abord ce paramètre, puis la liste de ce qui reste.

    NB: il y avait aussi une incohérence entre ton passage d'un hash ref dans le code appelant et l'utilisation directe d'un hachage dans la fonction appelée. Si tu veux passer un hash ref:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    enriched_hash(\%hash, $file2);
    Alors il faut récupérer un hash ref (un scalaire dans la fonction appelée), et soit utiliser ce hash ref, soit l'utiliser pour alimenter un hash local :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    sub enriched_hash {
        my ($hash_ref, $file2) = @_;
        my %hash = %$hash_ref;
        # ...
    }
    Mais dans ce cas, il faut que la fonction renvoie le hash à l'appelant (ce que ton code ne fait pas).

    Tu peux aussi modifier directement le contenu du hash de la fonction principale en utilisant le hash ref, mais il faudrait que tu montres ton code pour que je t'indique ce qu'il y aurait à changer.

  3. #3
    Membre à l'essai
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 14
    Points : 17
    Points
    17
    Par défaut
    Merci pour tes éléments de réponse mais j'ai encore des erreurs qui s'affichent :

    Name "main::hash_ref" used only once: possible typo at ./enriched_hash_interpro.pl line 50.
    Reference found where even-sized list expected at ./enriched_hash_interpro.pl line 49.
    Use of uninitialized value $hash_ref in hash dereference at ./enriched_hash_interpro.pl line 50.
    Reference found where even-sized list expected at ./enriched_hash_interpro.pl line 17.
    Reference found where even-sized list expected at ./enriched_hash_interpro.pl line 24.
    $VAR1 = {
    'HASH(0x1ab8ff8)' => undef
    };

    Voici de nouveau mon code mais avec les modifications apportées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    ### MAIN ###
     
    use Data:: Dumper qw(Dumper);
     
    $file1 = ARGV[0];
    $file2 = ARGV[1];
     
    my %hash;
     
    %hash = hash_remplissage($file1, \%hash);
    %hash = enriched_hash($file2, \%hash);
     
    print Dumper \%hash;
    print "___________\n";
     
     
    ### FUNCTIONS ###
     
     
    sub hash_remplissage {
     
    my ($file1,%hash_ref) = @_;
     
    my%hash_function1 =%$hash_ref;
     
    open FICHIER1, $file1;
     
    while(<FICHIER1>) {
        ... remplissage du hash vide ...
    }
     
    close FICHIER1;
     
    return \%hash;
    }
     
     
     
     
     
    sub enriched_hash {
     
    my ($file2, %hash) = @_;
    my %hash_function2 =%$hash_ref;
     
    open (FICHIER2, $file2) or die "Can't open '$file2': $!";
     
    while(<FICHIER2>) {
    ... ajout éléments dans hash ...
    }
     
    close FICHIER2;
    }
     
    ### END ###
    Les lignes 50, 49, 17 et 24 correspondent respectivement à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my %hash_function1 = %$hash_ref;
     
    my ($file1,%hash_ref) = @_;
     
    %hash = hash_remplissage($file1, \%hash);
     
    %hash = enriched_hash($file2, \%hash);

    Autre question : Mais si on veut juste alimenter le hash sans forcément retourner un hash, comment peut-on faire ?
    C'est à dire que je cré mon hash dans mon main et je l'enrichie juste à partir d'une fonction.

    Merci par avance pour tes réponses

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Pas le temps tout de suite de tout regarder, mais si tu passes une référence à un hash:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    %hash = hash_remplissage($file1, \%hash);
    alors, dans la fonction, tu dois récupérer non pas un hash mais un hash ref, c'est à dire un scalaire. Il faut donc dans la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    my ($file1,$hash_ref) = @_;
    my %hash_function1 = %$hash_ref;
    Même chose avec l'autre fonction.

    Ensuite, cette fonction renvoie
    alors que tu as nommé ton hash %hash_function1.

  5. #5
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Je crois qu'il y a une certaine confusion dans ton esprit.

    Si tu passes une hash ref à une fonction, tu reçois dans la fonction une hash ref, c'est-à-dire un scalaire, et non un hachage. Tu as (au moins) deux manières d'accéder à son contenu ou de l'enrichir:
    • tu travailles avec des références pour modifier directement le hachage créé dans le code principal;
    • tu copies localement le contenu du hachage et l'enrichis, mais tu dois alors renvoyer cette copie à l'appelant (et celui-ci doit bien sûr la récupérer).



    Première solution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    use strict;
    use warnings;
    use Data::Dumper;
     
    my %hash;
     
    hash_remplissage(\%hash);
    print Dumper \%hash;
    enrich_hash(\%hash);
    print Dumper \%hash;
     
     
    sub hash_remplissage {
        my $hash_ref = shift;
        for my $val (1..5) {
            $hash_ref->{ "Valeur_1_$val" } = $val; # utilisation de références pour modifier directement le contenu de %hash
        }
    }
     
    sub enrich_hash {
        my $hash_ref = shift;
        for my $val (6..10) {
            $hash_ref->{ "Valeur_2_$val" } = $val; # utilisation de références pour modifier directement le contenu de %hash
        }
    }
    Ceci imprime:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    $VAR1 = {
              'Valeur_1_1' => 1,
              'Valeur_1_4' => 4,
              'Valeur_1_5' => 5,
              'Valeur_1_2' => 2,
              'Valeur_1_3' => 3
            };
    $VAR1 = {
              'Valeur_1_1' => 1,
              'Valeur_2_10' => 10,
              'Valeur_1_4' => 4,
              'Valeur_2_9' => 9,
              'Valeur_2_6' => 6,
              'Valeur_1_5' => 5,
              'Valeur_1_2' => 2,
              'Valeur_1_3' => 3,
              'Valeur_2_8' => 8,
              'Valeur_2_7' => 7
            };

    Seconde solution:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    use strict;
    use warnings;
    use Data::Dumper;
     
    my %hash;
     
    %hash = hash_remplissage(\%hash);
    print Dumper \%hash;
    %hash = enrich_hash(\%hash);
    print Dumper \%hash;
     
     
    sub hash_remplissage {
        my $hash_ref = shift;
        my %local_hash_copy = %$hash_ref;
        for my $val (1..5) {
        	$local_hash_copy{ "Valeur_1_$val" } = $val;
        }
        return %local_hash_copy;
    }
     
    sub enrich_hash {
        my $hash_ref = shift;
        my %other_local_hash_copy = %$hash_ref;
        for my $val (6..10) {
            $other_local_hash_copy{ "Valeur_2_$val" } = $val;
        }
        return %other_local_hash_copy;
    }
    Ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    $VAR1 = {
              'Valeur_1_1' => 1,
              'Valeur_1_4' => 4,
              'Valeur_1_2' => 2,
              'Valeur_1_5' => 5,
              'Valeur_1_3' => 3
            };
    $VAR1 = {
              'Valeur_1_1' => 1,
              'Valeur_1_4' => 4,
              'Valeur_2_10' => 10,
              'Valeur_2_6' => 6,
              'Valeur_2_9' => 9,
              'Valeur_1_2' => 2,
              'Valeur_1_5' => 5,
              'Valeur_1_3' => 3,
              'Valeur_2_8' => 8,
              'Valeur_2_7' => 7
            };
    La première solution est a priori un peu meilleure et un peu plus rapide car elle évite des copies multiples des données, mais tu peux très bien choisir la seconde si elle te paraît plus claire.

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 498 771
    Points
    498 771
    Par défaut
    Bonjour,

    Cette lecture sur les références te sera d'une très grande utilité.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passer plusieurs arguments dans une fonction
    Par philippef dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 03/02/2016, 13h04
  2. passage d'argument dans une fonction
    Par wadcyr8_197 dans le forum C++
    Réponses: 5
    Dernier message: 20/07/2007, 09h41
  3. Généricité des Input Arguments dans une fonction
    Par RaphTIM dans le forum MATLAB
    Réponses: 5
    Dernier message: 06/06/2007, 16h28
  4. Passer un tableau PHP en argument dans une fonction javascript ?
    Par The Molo dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 18/05/2007, 12h31
  5. Erreur d'argument dans une fonction
    Par rouliane dans le forum MATLAB
    Réponses: 6
    Dernier message: 12/12/2006, 11h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo