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 :

[Résolu]Pb. remplir un tableau de hash avec un tableau


Sujet :

Langage Perl

  1. #1
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut [Résolu]Pb. remplir un tableau de hash avec un tableau
    Bonjour, débutant en Perl et trifouillant un simple programme répertoire, je voudrais que chaque entrée puisse avoir plusieurs n° de téléphone.
    La forme du tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    @repertoire [
                 {
                   prenom => prénom
                   nom    => nom
                   tels   => [tel1,tels2 …]
                 }
                ]
    Pour remplir ce @repertoire j'utilise le fichier repertoire, de la forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Éric#Dumont#1111111111#2222222222#
    Marcelle#Amelac#3333333333#
    Syvain#Boyer#4444444444#5555555555#6666666666#
    Colette#Masson#7777777777#
    Voici le code que j'ai écris :

    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
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use diagnostics;
    use Smart::Comments;
    use Data::Dumper;
    use feature ":5.24";
     
    my $repertoire = "repertoire";  # fichier
    my @repertoire ;                # le repertoire (array de hash)
    my ($nom, $prenom, $tel);       # variables temporaires
    my @tels;                       # liste de n° de téléphone
     
    sub ouvrir_repertoire {
        if (-e $repertoire) {
            open my $REP, "<", "$repertoire" or die "Impossible de lire $repertoire : $!";
     
            while (<$REP>) {
                chomp;
                say;
                ($nom, $prenom, @tels) = split(/#/);
                ### nom: $nom
                ### prenom: $prenom
                ### tel: @tels
                push (@repertoire,{ 'prenom' => $prenom,
                                    'nom'    => $nom,
                                    'tels'    => \@tels
                                  });
            }
            ### @repertoire
            close $REP;
        } else {
            # ajouter_entree(); # si le fichier n'existe pas creer repertoire
        }
        return;
    }
     
    ouvrir_repertoire;
    J'utilise Smart::Comments, sorte de Data:umper en plus simple, pour visualiser le contenu de mes variables et voici ce que j'obtiens :

    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
     
    ### nom: 'Éric'
    ### prenom: 'Dumont'
    ### tel: [
    ###        '1111111111',
    ###        '2222222222'
    ###      ]
     
    ### nom: 'Marcelle'
    ### prenom: 'Amelac'
    ### tel: [
    ###        '3333333333'
    ###      ]
     
    ### nom: 'Syvain'
    ### prenom: 'Boyer'
    ### tel: [
    ###        '4444444444',
    ###        '5555555555',
    ###        '6666666666'
    ###      ]
     
    ### nom: 'Colette'
    ### prenom: 'Masson'
    ### tel: [
    ###        '7777777777'
    ###      ]
     
    ### @repertoire: [
    ###                {
    ###                  nom => 'Éric',
    ###                  prenom => 'Dumont',
    ###                  tels => [
    ###                            '7777777777'
    ###                          ]
    ###                },
    ###                {
    ###                  nom => 'Marcelle',
    ###                  prenom => 'Amelac',
    ###                  tels => $VAR1->[0][0]{tels}
    ###                },
    ###                {
    ###                  nom => 'Syvain',
    ###                  prenom => 'Boyer',
    ###                  tels => $VAR1->[0][0]{tels}
    ###                },
    ###                {
    ###                  nom => 'Colette',
    ###                  prenom => 'Masson',
    ###                  tels => $VAR1->[0][0]{tels}
    ###                }
    ###              ]
    Je ne comprends pas. Dans un premier temps le fichier est bien lu et les variables bien affectées. Mais le remplissage de @repertoire avec les téléphones foire. Le seul n° qui peuple le tableau c'est le dernier du fichier et pas au bon endroit.

    Merci pour votre coup de main.

  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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je ne peux pas tester maintenant sur ma tablette, mais je suggère d'essayer le programme modifié suivant:
    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
     
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use diagnostics;
    use Smart::Comments;
    use Data::Dumper;
    use feature ":5.24";
     
    my $repertoire = "repertoire";  # fichier
    my @repertoire ;                # le repertoire (array de hash)
    # my ($nom, $prenom, $tel);       # utiliser des variables locales dans le fonction, pas des variables globales
    # my @tels;                       # idem
     
    sub ouvrir_repertoire {
        if (-e $repertoire) {
            open my $REP, "<", "$repertoire" or die "Impossible de lire $repertoire : $!";
     
            while (<$REP>) {
                chomp;
                say;
                my ($nom, $prenom, @tels) = split(/#/);
                ### nom: $nom
                ### prenom: $prenom
                ### tel: @tels
                push (@repertoire,{ 'prenom' => $prenom,
                                    'nom'    => $nom,
                                    'tels'    => [@tels],  # utilisation du constructeur de tableau anonyme
                                  });
            }
            ### @repertoire
            close $REP;
        } else {
            # ajouter_entree(); # si le fichier n'existe pas creer repertoire
        }
        return;
    }

  3. #3
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Merci. Mais je viens de tester le code et j'ai exactement le même résultat :<

  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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je ne vois pas ce qui ne marche pas chez toi.

    J'ai testé le programme suivant:

    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
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use utf8;
    use Data::Dumper;
    use feature 'say';
     
    my @repertoire ;                # le repertoire (array de hash)
     
    sub lire_données {
     
            while (<DATA>) {
                chomp;
                say;
                my ($nom, $prenom, @tels) = split(/#/);
                push (@repertoire,{ 'prenom' => $prenom,
                                    'nom'    => $nom,
                                    'tels'    => [@tels],  # utilisation du constructeur de tableau anonyme
                                  });
            }
    }
    lire_données;
    print Dumper \@repertoire;
    __DATA__
    Eric#Dumont#1111111111#2222222222#
    Marcelle#Amelac#3333333333#
    Syvain#Boyer#4444444444#5555555555#6666666666#
    Colette#Masson#7777777777#
    Et ça m'affiche ce que tu me paraît désirer:
    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
     
    $ perl repertoire.pl
    Eric#Dumont#1111111111#2222222222#
    Marcelle#Amelac#3333333333#
    Syvain#Boyer#4444444444#5555555555#6666666666#
    Colette#Masson#7777777777#
    $VAR1 = [
              {
                'nom' => 'Eric',
                'prenom' => 'Dumont',
                'tels' => [
                            '1111111111',
                            '2222222222'
                          ]
              },
              {
                'nom' => 'Marcelle',
                'prenom' => 'Amelac',
                'tels' => [
                            '3333333333'
                          ]
              },
              {
                'nom' => 'Syvain',
                'prenom' => 'Boyer',
                'tels' => [
                            '4444444444',
                            '5555555555',
                            '6666666666'
                          ]
              },
              {
                'nom' => 'Colette',
                'prenom' => 'Masson',
                'tels' => [
                            '7777777777'
                          ]
              }
            ];

  5. #5
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Ben en fait je ne sais pas ce que j'avais mal fait, effectivement ça marche. Je te remercie.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Bien que j'ai marqué le sujet comme résolu je continue le fil car le problème suivant est en rapport.
    Problème : comment accéder aux données du tableau dans le hash.

    Avec le programme suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sub affiche_repertoire {
        foreach my $personne (@repertoire) {     # parcours tout le répertoire
            printf ("%-20s %-20s", $personne->{prenom}, $personne->{nom});
            foreach my $tel (@$repertoire->{'tels'}) {
                printf ("%-15s", $tel);
            }
            print "\n";
        }
        return;
    }
    je n'ai pas de problème pour afficher les nom et prénom, sans la boucle "foreach my $tel …", mais je ne peux parcourir le tableau @$repertoire->{'tels'}, Perl me renvoyant l'erreur

    Can't use string ("repertoire") as an ARRAY ref while "strict refs" in use at
    ./test.pl line 58 (#1)
    (F) You've told Perl to dereference a string, something which
    use strict blocks to prevent it happening accidentally. See
    "Symbolic references" in perlref. This can be triggered by an @ or $
    in a double-quoted string immediately before interpolating a variable,
    for example in "user @$twitter_id", which says to treat the contents
    of $twitter_id as an array reference; use a \ to have a literal @
    symbol followed by the contents of $twitter_id: "user \@$twitter_id".
    Un petit coup de main serait le binevenu, merci.

  7. #7
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    la structure des données est la suivante:

    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
    $VAR1 = [
              {
                'nom' => 'Eric',
                'prenom' => 'Dumont',
                'tels' => [
                            '1111111111',
                            '2222222222'
                          ]
              },
              {
                'nom' => 'Marcelle',
                'prenom' => 'Amelac',
                'tels' => [
                            '3333333333'
                          ]
              },
             # ...
            ];
    Dans cette structure, @$repertoire->{'tels'} ne correspond à rien. La liste de téléphones est attachée à une $personne, pas au tableau @repertoire.

    Il faut donc changer le foreach imbriqué comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    foreach my $tel (@{$personne->{'tels'}}) {
    A noter qu'il faut ajouter des accolades pour dire à Perl que le @ déréférence $personne->{'tels'}, et non simplement $personne.

    Ce qui donne la fonction d'affichage suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    sub affiche_repertoire {
        foreach my $personne (@repertoire) {     # parcours tout le répertoire
            printf "%-20s %-20s", $personne->{prenom}, $personne->{nom};
            foreach my $tel (@{$personne->{'tels'}}) {
                printf "%-15s", $tel;
            }
            print "\n";
        }
        return;
    }
    A noter que j'ai retiré au passage les parenthèses inutiles après les appels de la fonction printf, ça donne le même résultat, mais c'est du code Perl un peu plus plus idiomatique.

    Affichage obtenu:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Dumont               Eric                1111111111     2222222222
    Amelac               Marcelle            3333333333
    Boyer                Syvain              4444444444     5555555555     6666666666
    Masson               Colette             7777777777

  8. #8
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Merci pour tes explications très claires, je comprends mieux mon erreur.

  9. #9
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Décidément j'ai beaucoup de mal avec cette structure de données. Le code d'abord :

    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use diagnostics;
    use Smart::Comments;
    use Data::Dumper;
    use feature ":5.24";
     
    my $repertoire = "repertoire";    # fichier
    my @repertoire;                   # le repertoire (array de hash)
     
    sub ouvrir_repertoire {
        if ( -e $repertoire ) {
            open my $REP, "<", "$repertoire"
                or die "Impossible de lire $repertoire : $!";
     
            while (<$REP>) {
                chomp;
                my ( $prenom, $nom, @tels ) = split(/#/);
                push @repertoire, {
                                    'prenom' => $prenom,
                                    'nom'    => $nom,
                                    'tels'   => [@tels]
                                  };
            }
            close $REP;
        }
        else {
            ajouter_entree();    # si le fichier n'existe pas creer repertoire
        }
        return;
    }
     
    sub ecrire_repertoire {
        open my $REP, ">", "$repertoire"
            or die "Impossible d'ouvrir $repertoire en écriture : $!";
     
        foreach my $personne (@repertoire) {
            print $REP $personne->{'prenom'} . "#"    # on sépare les champs
                     . $personne->{'nom'}    . "#";   # avec des dièses
            foreach my $tel (@{$personne->{'tels'}}) {
                print $REP $tel              . "#";
            }
            print $REP "\n";
        }
        close $REP;
        return;
    }
     
    sub affiche_repertoire {
        foreach my $personne (@repertoire) {     # parcours tout le répertoire
            printf "%-20s %-20s", $personne->{prenom}, $personne->{nom};
            foreach my $tel (@{$personne->{'tels'}}) {
                printf "%-15s", $tel;
            }
            print "\n";
        }
        return;
    }
     
    sub ajouter_entree {
        my $reponse = "o";
        my ($nom, $prenom);
        my $tel="";
        my @tels=();
     
        while ($reponse eq "o") {
            print "Prenom : ";
            chomp ($prenom = <>);
            print "Nom : ";
            chomp ($nom = <>);
     
            while ($tel ne ".") {
                print "Téléphone : ";
                chomp ($tel = <> );
                push (@tels, $tel) unless ($tel eq ".");
            }
     
            push @repertoire, {
                               'prenom' => $prenom,
                               'nom'    => $nom,
                               'tel'    => [@tels]
                              };
     
            print "Ajouter une autre entrée ? (o/n) ";
            chomp ($reponse = <>);
        }
        print Dumper @repertoire;
        return;
    }
     
    ouvrir_repertoire;
    ajouter_entree;
    affiche_repertoire;
    J'ai donc créer une fonction ajouter_entree qui comme son nom l'indique permet d'ajouter des entrées au répertoire. Ça marche preuve en est le Dumper. Mais quand j'invoque la fonction affiche_repertoire il manque les n° de téléphone, seuls prénom et nom sont affichés pour les nouvelles entrées créées !

    Help please !

  10. #10
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    il y a un petit bug dans la fonction ajouter_entree.

    Dans la fonction lire_données, la clef des hachages de @repertoire pour les numéros d'appel est tels. Dans affiche_repertoire, on lit également des valeurs avec la clef tels. Mais dans ta nouvelle fonction ajouter_entree, tu alimentes les hachages avec la clef tel (au singulier, au lieu de tels au pluriel). Du coup, affiche_repertoire ne peut pas trouver ces numéros d'appel.

    Exemple du contenu de @repertoire avec data::Dumper:
    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
    $VAR4 = {
              'nom' => 'Colette',
              'prenom' => 'Masson',
              'tels' => [
                          '7777777777'
                        ]
            };
    $VAR5 = {
              'nom' => 'Dupont',
              'prenom' => 'Jean',
              'tel' => [
                         '565432',
                         '5566789',
                         '09876'
                       ]
            };
    Bonne fin de journée.

    PS: n'hésite pas à "plussoyer" () mes message s'ils te sont utiles.

  11. #11
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Wow merci, très perspicace, j'ai eu beau relire le code je suis passé à côté. Bien sûr que je vais plusser tes messages

  12. #12
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Voilà le programme est terminé, enfin pour l'instant, et tout fonctionne. Alors comme je suis un peu fier de moi je le livre ici, et si vous avez des remarques je suis preneur. Merci pour votre aide.


    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use diagnostics;
    use Smart::Comments;
    use Data::Dumper;
    use feature ":5.24";
     
    my @repertoire ;                # le repertoire (array de hash)
    my $repertoire = "repertoire";  # fichier
     
    sub affiche_repertoire;     sub affiche_entrees;    sub ajouter_entree;
    sub ecrire_repertoire;      sub modifier_entree;    sub ouvrir_repertoire;
    sub rechercher;             sub supprimer_entree;
     
    #TODO: supprimer : valider l'entrée
    #TODO: ajouter mail, adresse
    #TODO: plusieurs n° de tél
    # ### programme principal #####################################################
    ouvrir_repertoire();
     
    while (1){
        print "(A)jouter une entrée (R)echercher (V)oir le répertoire (..)quitter\n";
        print "Choix : ";
        my $reponse;
        chomp ($reponse = <>);
        ajouter_entree()        if ($reponse eq "a");
        rechercher()            if ($reponse eq "r");
        affiche_repertoire()    if ($reponse eq "v");
        exit                    if ($reponse eq "..");
    }
     
    ecrire_repertoire();
    # ### fin programme principal #################################################
     
    sub ouvrir_repertoire {
        if (-e $repertoire) {
            open my $REP, "<", "$repertoire" or die "Impossible de lire $repertoire : $!";
     
            while (<$REP>) {
                chomp;
                my ($prenom, $nom, @tels) = split(/#/);
                push (@repertoire,{ 'prenom' => $prenom,
                                    'nom'    => $nom,
                                    'tels'   => [@tels]
                                  });
            }
            close $REP;
        } else {
            ajouter_entree(); # si le fichier n'existe pas creer repertoire
        }
        return;
    }
     
    sub ecrire_repertoire {
      open my $REP, ">", "$repertoire"
        or die "Impossible d'ouvrir $repertoire en écriture : $!";
     
      foreach my $personne (@repertoire) {
        print $REP $personne->{'prenom'} . "#"    # on sépare les champs
                 . $personne->{'nom'}    . "#";   # avec des dièses
        foreach my $tel (@{$personne->{'tels'}}) {
          print $REP $tel . "#";
        }
        print $REP "\n";
      }
      close $REP;
      return;
    }
     
    sub ajouter_entree {
        my $reponse = "o";
        my ($nom, $prenom);
        my $tel="";
        my @tels=();
     
        while ($reponse eq "o") {
            print "Prenom : ";
            chomp ($prenom = <>);
            print "Nom : ";
            chomp ($nom = <>);
     
            while ($tel ne ".") {
                print "Téléphone : ";
                chomp ($tel = <> );
                push (@tels, $tel) unless ($tel eq ".");
            }
     
            push @repertoire, {
                               'prenom' => $prenom,
                               'nom'    => $nom,
                               'tels'    => [@tels]
                              };
     
            print "Ajouter une autre entrée ? (o/n) ";
            chomp ($reponse = <>);
        }
        ecrire_repertoire;
        return;
    }
     
    sub affiche_repertoire {
        foreach my $personne (@repertoire) {     # parcours tout le répertoire
            printf "%-20s %-20s", $personne->{prenom}, $personne->{nom};
     
            foreach my $tel (@{$personne->{'tels'}}) {
                printf "%-15s", $tel;
            }
     
            print "\n";
        }
        return;
    }
     
    sub modifier_entree {
        my $index = shift;
     
        while (1) {
            my $reponse;
     
            printf "%-20s %-20s",
                    $repertoire[$index]{prenom}, $repertoire[$index]{nom};
            my $count = 0;
            foreach (@{$repertoire[$index]{tels}}){
                printf "[%u] %-20s", $count, $_;
                $count++;
            }
            print "\n";
            print "Modifier (P)rénom (N)om (n°)Téléphone (A)jouter tél. (S)upprimer tel. (.)Écrire : ";
            chomp ($reponse = <>);
     
            if ("$reponse" eq "p") {
                print "Nouveau prénom : ";
                chomp (my $nvPrenom = <>);
                $repertoire[$index]{'prenom'} = $nvPrenom;
            } elsif ("$reponse" eq "n") {
                print "Nouveau nom : ";
                chomp (my $nvNom = <>);
                $repertoire[$index]{'nom'} = $nvNom;
            } elsif ($reponse =~ /\d/){
                print "Nouveau téléphone : ";
                chomp (my $nvTel = <>);
                $repertoire[$index]{'tels'}[$reponse] = $nvTel;
            } elsif ("$reponse" eq "a"){
                print "Nouveau téléphone : ";
                chomp (my $telPlus = <>);
                push @{$repertoire[$index]{'tels'}}, $telPlus;
            } elsif ("$reponse" eq "s"){
                $count = 0;
                foreach (@{$repertoire[$index]{tels}}){
                    printf "[%u] %-20s", $count, $_;
                    $count++;
                }
                print "N° à supprimer : ";
                chomp (my $choix = <>);
                splice @{$repertoire[$index]{tels}}, $choix, 1;
            } elsif ("$reponse" eq ".") {
                last;
            }
        }
        ecrire_repertoire;
        return;
    }
     
     
    sub supprimer_entree {
        my $index = shift;
        my $reponse;
     
        printf "Êtes-vous sur de vouloir supprimer : %s %s\n",
                $repertoire[$index]{prenom}, $repertoire[$index]{nom};
        print "o/n : ";
        chomp ($reponse = <>);
     
        splice (@repertoire, $index, 1) if ("$reponse" eq "o");
     
        ecrire_repertoire;
        return;
    }
     
    sub affiche_entrees {
        my @liste = @_;
        my $reponse;
     
        foreach my $i (@liste) {
            my $aff = sprintf "[%5s]: %-20s %-20s",
                      $i,  $repertoire[$i]{'prenom'}, $repertoire[$i]{'nom'};
     
            foreach my $j (@{$repertoire[$i]{'tels'}}){
                $aff .= sprintf "%-15s", $j;
            }
            say $aff;
        }
     
        print "Choix : ";
        chomp (my $index = <>);
     
        my $aff = sprintf "[%5s]: %-20s %-20s",
                  $index,  $repertoire[$index]{'prenom'}, $repertoire[$index]{'nom'};
     
        foreach my $j (@{$repertoire[$index]{'tels'}}){
            $aff .= sprintf "%-15s", $j;
        }
     
        say $aff;
        print "(M)odifier (S)upprimer (.)retour : ";
        chomp ($reponse = <>);
     
        return                    if ("$reponse" eq ".");
        modifier_entree ($index)  if ("$reponse" eq "m");
        supprimer_entree ($index) if ("$reponse" eq "s");
        return;
    }
     
     
    sub rechercher {
        my $motif;              # motif à rechercher
        my @trouves;            # liste des élément trouvés
        my $index = 0;          # index de l'élément dans @repertoire
     
        print "Motif : ";
        chomp ($motif = <>);
     
        foreach my $ligne (@repertoire) {
            while ( my ($clef, $valeur) = each %$ligne ) {
                if ( $valeur =~ /$motif/ ){
                    push (@trouves, $index);
                    next;
                }
            }
            $index++;
        }
     
        affiche_entrees (@trouves);
        return;
    }

  13. #13
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Merci du partage.

    Pas le temps de regarder maintenant en détail, mais je repasserai faire une revue de code (su je n'oublie pas).

  14. #14
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Merci, ce serait sympa.

  15. #15
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    j'ai relu ton programme. Franchement, c'est vraiment pas mal. Mes remarques ci-dessous sont vraiment des points de détail.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my @repertoire ;                # le repertoire (array de hash)
    my $repertoire = "repertoire";  # fichier
    Perl sait très bien faire la différence entre $repertoire et @repertoire, mais ça peut troubler la personne lisant le code. A mon humble avis, il vaut mieux éviter de donner le même nom à une variable scalaire et une variable tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sub affiche_repertoire;     sub affiche_entrees;    sub ajouter_entree;
    sub ecrire_repertoire;      sub modifier_entree;    sub ouvrir_repertoire;
    sub rechercher;             sub supprimer_entree;
    Il est inutile de prédéclarer les fonctions.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ouvrir_repertoire();
    Il serait à mon avis préférable de passer le nom du fichier en paramètre à la fonction, plutôt que de dépendre de variables globales (pareil pour les autres fonctions utilisant $repertoire). Cela implique bien sûr de récupérer le paramètre au début de la fonction appelée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    while (1){
        print "(A)jouter une entrée (R)echercher (V)oir le répertoire (..)quitter\n";
        print "Choix : ";
        my $reponse;
        chomp ($reponse = <>);
        ajouter_entree()        if ($reponse eq "a");
        rechercher()            if ($reponse eq "r");
        affiche_repertoire()    if ($reponse eq "v");
        exit                    if ($reponse eq "..");
    }
    J'ajouterais une ligne de code pour mettre la variable $reponse en minuscules, au cas où l'utilisateur serait tenté d'utiliser des lettres capitales (d'autant plus que la question incite à l'utilisation de lettres capitales).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        print $REP $personne->{'prenom'} . "#"    # on sépare les champs
                 . $personne->{'nom'}    . "#";   # avec des dièses
    Syntaxe un plus brève possible:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    print $REP join "#", $personne->{'prenom'}, $personne->{'nom'};
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    push (@tels, $tel) unless ($tel eq ".");
    Syntaxe un peu plus brève (et à mon avis un peu plus lisible) supprimant les deux paires de parenthèses:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    push @tels, $tel unless $tel eq ".";
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    chomp ($reponse = <>);
    Comme précédemment, il serait utile de mettre $reponse en minuscules. Cela vient trois fois de plus. (D'une façon générale, toujours être prudent avec les réponses de l'utilisateur.)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        foreach my $ligne (@repertoire) {
            while ( my ($clef, $valeur) = each %$ligne ) {
                if ( $valeur =~ /$motif/ ){
                    push (@trouves, $index);
                    next;
                }
            }
            $index++;
        }
    Dans ce genre de cas (où l'on a besoin d'utiliser les indices), personnellement je bouclerais plutôt sur les indices:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        for my $index (0 .. $#repertoire) {
            my $ligne = $repertoire[$index];
            while ( my ($clef, $valeur) = each %$ligne ) {
                if ( $valeur =~ /$motif/ ){
                    push (@trouves, $index);
                    next;
                }
            }
        }
    Bonne fin de weekend,
    Laurent.

  16. #16
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Merci de tes conseils, je vais regarder ça de plus près.
    Les parenthèses m'aident à isoler les choses, progressivement j'apprends à m'en passer.
    Je me suis servi de perlcritic (et Stackoverflow) pour apporter quelques corrections, c'est vraiment pas mal.

  17. #17
    Futur Membre du Club
    Homme Profil pro
    chômeur
    Inscrit en
    Juillet 2017
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : chômeur

    Informations forums :
    Inscription : Juillet 2017
    Messages : 39
    Points : 7
    Points
    7
    Par défaut
    Par contre quand je supprime les déclarations de fonctions je me prends des bareword à la volée ! Peux-tu être plus précis ?

  18. #18
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Raoul_Pinette Voir le message
    Par contre quand je supprime les déclarations de fonctions je me prends des bareword à la volée ! Peux-tu être plus précis ?
    Je ne vois vraiment pas pourquoi. J'ai supprimé ces déclarations, modifié deux instructions useau début:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #!/usr/bin/env perl
    use strict;
    use warnings;
    use diagnostics;
    # use Smart::Comments;       # mis en commentaire parce que Smart::Comments n'est pas installé sur mon ordinateur (et pas utilisé dans le programme)
    use Data::Dumper;
    use feature "say";           # ta syntaxe avec 5.24 ne marchait pas avec ma version  de Perl
    et le programme inchangé à part ces deux instructions usecompile et fonctionne sans problème chez moi.

  19. #19
    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 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    J'ajoute qu'à mon avis, le seul intérêt d'une telle prédéclaration est de permettre d'appeler la fonction sans une paire de parenthèses () vide quand il n'y pas d'arguments, et sans parenthèses autour des arguments s'il y en a.

    Si j'ai besoin de cela, je préfère définir toute la fonction avant de l'utiliser.

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 04/05/2011, 14h50
  2. [C#] - Remplir tableau à deux dimensions avec split
    Par dada4444 dans le forum Windows Forms
    Réponses: 7
    Dernier message: 26/05/2009, 09h26
  3. Réponses: 6
    Dernier message: 23/05/2009, 16h29
  4. [c++] remplir tableau de bool avec cin
    Par djkamikaz dans le forum C++
    Réponses: 5
    Dernier message: 25/12/2007, 05h03
  5. remplir un dropdownlist avec un tableau de datarow
    Par bous_saad317 dans le forum ASP.NET
    Réponses: 1
    Dernier message: 13/07/2007, 09h45

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