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 :

Comment concevoir une table de liste


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  
    Profil pro
    " "
    Inscrit en
    Janvier 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : " "

    Informations forums :
    Inscription : Janvier 2008
    Messages : 330
    Points : 254
    Points
    254
    Par défaut Comment concevoir une table de liste
    Salut à tous,
    j'aurais besoin un peu d'aide pour contruire ma table %datdir ( qui a pour clef $s_project et pour valeurs des listes @ldat).
    Je veux avoir dans une table datdir tous les liste ldat que je recupere des $s_project de tous les $s_client.
    Mais ceci push @{$datdir{$s_project}}, @ldat ne marche pas,
    Merci pour grain de sel


    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
    sub CheckProjectDir() {
     
    #_:  s_client : Indexe les clefs (client)  de la table %project
    #_:  s_project : Indexe les valeurs (etudes) de la table %project
    #_:  s_dir : stocke le project courant
    #_:  s_dsc : stocke le dsc du projet courant 
            my ($s_client, $s_project, $s_dir, $s_dsc);
            for $s_client (keys (%project))
            {
                    if ($check) {print "Client : $s_client\n" ;}
                    #for $s_project (values (%project))
                    for $s_project (@{$project{$s_client}})
                    {
                            if ($check) { print "\tEtude : $s_project\n"; }
                            $s_dir="$maindir/$s_client/$s_project "; #project courant
                            next if !-d $s_dir ;
                            if ($check) { print "\t\tChemin : $s_dir\n";} # probleme d'affichage du chemin
                            opendir (FHdir, $s_dir);
                            if ($?!=0) { &MyWarning(__LINE__, $!, "Can not open directory $s_dir "); next;}
                            @ldat = glob('*.dat '); # la liste des fichiers .dat du project courant
                            $s_dsc = glob('.dsc');  # dsc du project courant
                            # $s_dsc=$s_project.".dsc";
                            closedir(FHdir);
                    }
            push @{$datdir{$s_project}}, @ldat ; # %datdir a pour clef s_project et pour valeurs @ldat
            push @dscdir, $s_dsc;
            }
     return %datdir; # Retourner la liste des .dat d'un project
     return @dscdir; # Stocke les  dsc des project d'un client
    }

  2. #2
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Tout d'abord, je tiens à dire que ton problème est de ceux qui posent le plus souvent des difficultés aux débutants, et même pas seulement les débutants en fait. Moi-même, ça m'arrive encore d'avoir des difficultés avec les syntaxes de référencement et déréférencement, quand j'ai à gérer des structures complexes, et je suis, disons, un amateur éclairé.

    Je vais essayer de traduire en mots ce que signifie la ligne qui te pose problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @{$datdir{$s_project}}, @ldat ;
    Ajouter, à la fin du tableau obtenu par déréférencement sous forme de tableau de l'élément de la table associative %datdir dont la clé correspond à la valeur de la variable scalaire $s_project, les éléments de la liste des valeurs du tableau @ldat.

    Ou pour développer un peu plus, étape par étape :
    1. On obtient la valeur de la variable scalaire $s_project.
    2. On utilise cette valeur comme clé pour obtenir un élément de la table associative %datdir.
    3. On applique un déréférencement pour obtenir le tableau auquel cet élément fait référence.
    4. On obtient la liste des valeurs du tableau @ldat.
    5. On ajoute cette liste en queue des valeurs déjà présentes dans le tableau déréférencé, au moyen de la fonction native push.


    Les conditions pour que ça marche sont, par étape :
    1. Il faut que $s_project soit défini.
    2. Il faut que la table associative %datdir soit définie et ait déjà un élément défini pour cette clé.
    3. Il faut que ledit élément ait été défini comme référence de tableau.
    4. Il faut que @ldat soit défini.
    5. Pas de condition supplémentaire du moment que toutes les autres sont remplies.


    Rien dans ce que tu as montré de ton code ne garantit que ne serait-ce qu'une seule de ces conditions soient remplies, et elles doivent l'être toutes pour que ton code marche.
    Chacune de ces conditions, si elle n'est pas remplie, produit au moins un avertissement dans tout code Perl écrit normalement.

    Et par "écrit normalement", j'entends "comprenant use warnings; au début", ou à tout le moins l'option -w dans le shebang.

    Et là, je passe en mode tirade...

    Tout code Perl n'activant pas les avertissements est anormal. Activer les avertissements est la norme. Ne pas les activer est l'exception. Il n'y a jamais besoin de chercher des raisons d'activer les avertissements. Il n'y a que si l'on envisage de ne pas les activer qu'on doit se poser des questions. Il faut toujours activer les avertissements, sauf si on a des raisons précises pour ne pas les activer. Dans l'écrasante majorité des cas, on n'a aucune raison de ne pas activer les avertissements. Dans la minuscule fraction de cas où certains avertissements causent des problèmes rédhibitoires et incontournables, il vaut mieux les activer quand même et ne désactiver séléctivement que les avertissements problématiques, et seulement pour la ou les parties du code où les problèmes surviennent. Si l'on choisit de ne pas activer les avertissements, ou de désactiver sélectivemement certains avertissements, il faut mettre des commentaires pour expliquer TRÈS PRÉCISÉMENT POURQUOI - au début du script dans le premier cas, à chaque désactivation d'avertissement dans le second. Si l'on n'est pas capable de formuler cette explication, c'est que la conception du programme est en faute. Il vaut mieux reconsidérer l'intégralité de l'algorithme que l'on applique avant d'en arriver à l'extrémité de ne pas activer, ou de désactiver sélectivement, les avertissements.

    Je sais, le paragraphe qui précède est plein de redondances, et un peu pontifiant, mais je voulais enfoncer le clou. Je veux bien reconnaître que cette tirade peut ne pas s'appliquer aux scripts les plus simples et les plus minimalistes, mais tant qu'on n'a pas une expérience significative, je suis persuadé que "simple et minimaliste" ne peut s'appliquer qu'aux unilignes.

    Ah, et il y a l'autre tirade, plus simple, plus courte...

    Les avertissements sont tes amis, ils t'aident à écrire du bon code, en t'indiquant quand ton code est bancal. Activer systématiquement les avertissements te fait gagner un temps FOU dans ton apprentissage du langage, parce que les avertissements sont généralement très bien formulés et très informatifs. Bien plus que les messages d'erreurs proprement dits.

    Voilà, ça c'est dit. Une variante amusante de tout ce que je viens de dire est celle-ci : si un jour tu envisages d'écrire un programme en Perl sans activer les avertissements, ou en les désactivant sélectivement, viens poster un sujet ici pour demander son avis à la communauté. C'est ce que je ferais si ça m'arrivait un jour. Ça sert à ça, l'intelligence collective.

    --------------------------------------------------------------------------

    Il y a un autre problème dans ce que tu nous présentes de ton code. Plusieurs variables ne sont pas déclarées. En tout cas on ne voit pas où tu les a déclarées, si tu les as déclarées quelque part. Et si elles sont déclarées ailleurs, certaines ne sont peut-être pas déclarées où il faut. C'est difficile à dire sans le reste du code. Puisque je ne vois pas le reste du code, je vais partir du principe que tu utilises le pragma strict. Si ça n'est pas le cas, saches que l'intégralité de ce que j'ai dit à propos du pragma warnings, qui active les avertissements, vaut pour le pragma strict.

    Une chose est sûre : %datdir et @dscdir sont utilisés bizarrement. S'ils ont été déclarés en dehors du sous-programme, pourquoi chercher à les retourner avec return ? Surtout qu'un seul return peut être exécuté, et que du coup @dscdir n'est jamais retourné (ce qui, soit dit en passant, serait l'objet d'un avertissement, il me semble, si les avertissements étaient activés).
    @ldat n'a aucune raison d'être déclaré ailleurs qu'à l'intérieur du sous-programme. Or on ne voit sa déclaration nulle part, ce qui me fait douter un peu que tu aies utilisé le pragma strict.

    --------------------------------------------------------------------------

    Il y a plein de choses à nettoyer dans ton code. C'est d'ailleurs pour ça que je n'ai pas répondu à ta question initiale. Pas directement en tout cas. Les pragmas warning et strict peuvent t'aider à régler tes problèmes par toi-même. Apprends à les aimer.

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par Schmorgluck Voir le message
    Les conditions pour que ça marche sont, par étape :
    1. Il faut que $s_project soit défini.
    2. Il faut que la table associative %datdir soit définie et ait déjà un élément défini pour cette clé.
    3. Il faut que ledit élément ait été défini comme référence de tableau.
    4. Il faut que @ldat soit défini.
    5. Pas de condition supplémentaire du moment que toutes les autres sont remplies.
    Pas tout à fait. Les parties en gras ne sont pas obligatoires dans tous les cas. En effet, en perl 5, il existe un mécanisme (parfois décrié pour ses effets de bord malheureux) nommé l'autovivification ( (1) voir uniligne en exemple à la fin du post) qui fait en sorte de créer toutes les clés nécessaires l'utilisation ou à l'affectation d'une expression mettant en oeuvre une table de hashage.

    Ainsi, il est légal d'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my %personnel = ();
    $personnel{Employé1}->{nom => "Dupont", prenom => "Alain"};
    Dans ce cas, la clé Employé1 de %personnel sera automatiquement créée et sa valeur sera une référence anonyme à une table de hashage (structure) comprenant les clés nom et prenom.

    En revanche, suite à ceci, il ne sera pas possible d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @{$personnel{Employé1}}, ("fonction", "comptable");
    car $personnel{Employé1} n'est pas une référence à un tableau, mais à une table de hashage.
    En revanche, on peut tout à fait réaffecter $personnel{Employé1} comme un tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $personnel{Employé1} = [ %{$personnel{Employé1}}, "fonction", "comptable" ];
    Le contenu de $personnel{Employé1} sera alors une référence à un tableau.

    C'est pourquoi il est possible de ré-écrire la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @{$datdir{$s_project}}, @ldat ;
    ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datdir{$s_project} = [ @ldat ];
    Il y a cependant une différence avec l'écriture précédente : si $datdir{$s_project} existe déjà, sa valeur sera complétée avec @ldat dans la première écriture, alors qu'elle sera remplacée par @ldat dans la deuxième.

    Par contre, ton problème ne situe peut-être pas là où l'on croit :
    si ton indentation est correcte, on constate que la ligne incriminée est placée en dehors de la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for $s_project (@{$project{$s_client}})
    Comme tu n'as pas défini use warnings et use strict, la ligne 25 n'indique pas d'erreur, pourtant $s_project n'a soit aucune valeur, soit toujours la même, ce qui ne doit pas arranger tes affaires.

    (1) Exemple d'auto-vivification :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ perl -M5.10.0 -e 'use warnings; use strict; my @a = qw(1 2 3);my %a = ();push @{$a{valeur}}, @a;say join ",", @{$a{valeur}}'
    1,2,3

  4. #4
    Inactif  
    Profil pro
    " "
    Inscrit en
    Janvier 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : " "

    Informations forums :
    Inscription : Janvier 2008
    Messages : 330
    Points : 254
    Points
    254
    Par défaut
    merci pour vos eclaircissements.
    Mais pour plus de precision,Schmorgluck je te signale que tout ce que t'a evoqué existe, là je n'ai posté qu'une fonction de mon script i.e là où ça bloque dans le synthaxe

  5. #5
    Inactif  
    Profil pro
    " "
    Inscrit en
    Janvier 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : " "

    Informations forums :
    Inscription : Janvier 2008
    Messages : 330
    Points : 254
    Points
    254
    Par défaut un peu plus d'explication
    En gros,
    1- j'ai un repertoire "maindir" qui contient des sous-repertoires "client"
    2-Chaque sous-repertoire client contient a son tour des sous-repertoire "project"
    3-chaque sous-repertoire project conient un fichier d'extension .dsc plusieurs fichiers d'extension .dat


    ce que j'ai fait jusqu'ici:
    1. je cree une table %project qui a pour clef client et chaque client a pour valeurs ses project
    2. dans la 2e boucle j'accede à un project et je veux recuperer dans $s_dsc le .dsc et dans @ldat la liste des .dat.

    Ce que je n'ai pas reussi

    1. Avoir a la sortie de ma fonction sub CheckProjectDir() avoir une table %dscdir ayant pouer clef s_project et pour valeur les dsc de tous les project
    2. une table %datdir ayant pour clef s_project et chaque project aura comme valeur la liste des .dat

    Remarque:
    Toutes les variables ont ete declarées et j'ai aussi utilisé les modules use strict unse warnings
    Merci pour votre eclaircissement

  6. #6
    Inactif  
    Profil pro
    " "
    Inscrit en
    Janvier 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : " "

    Informations forums :
    Inscription : Janvier 2008
    Messages : 330
    Points : 254
    Points
    254
    Par défaut amelioration
    Merci a tous, voila ce que j'ai arrivé à faire, mais j'ai aucun resultat de sortie

    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
    #!/usr/bin/perl -w
     
    use strict;
    use warnings;
     
    my ($maindir) =   shift;  #  le repertoire client
    my ( %project, @dirs, %dsc_label, %dsc_code, @ldat, @dscdir, %datdir );
    print "________________________________________ ReadMainDir($maindir)\n";
    &ReadMainDir($maindir);
     
    print "________________________________________ ReadClientDir\n";
    &ReadClientDir;
     
    print "________________________________________ CheckProjectDir\n";
     
    $check = 1;
    &CheckProjectDir;
     
    print __FILE__. "successfull\n";
    exit 0;
     
     
    #==========================================================
    # Objectif :  Teste sur le repertoire passe en parametre  #
    # Resultat : @dirs contient tous les clients		  #
    #==========================================================
     
    sub ReadMainDir() {
        print "maindir=$maindir\n";
        opendir( FHdir, $maindir )
          || &MyError( __LINE__, $!, "Can not open directory $maindir" );
        @dirs =
          grep( !/^\./, sort( readdir FHdir ) )
          ;    # to exclude all .file especially directories . and ..
        closedir(FHdir);
    }
     
    #==================================================================================
    # Objectif : Parcourir le repertoire maindir  stocke dans @dirs					  #
    # Resultat : une table %project contenant tous les clients et leurs  etudes  #
    #==================================================================================
     
    sub ReadClientDir()
     
    {
     
        #_: s_client   :Indexe du repertoire des clients
        #_: s_path     :Client courant
        #_: s_project  :Indexe les projets du client courant
        #_: s_lproject :Liste des projets du client courant
     
        my ( $s_client, $s_path, @s_lproject, $s_project );
        for $s_client (@dirs) {
            $s_path = "$maindir/$s_client";    # Chemin client courant
            opendir( FHdir, $s_path )
              || &MyError( __LINE__, $!, "Can not open directory $s_path" );
            @s_lproject =
              grep( !/^\./, sort( readdir FHdir ) )
              ;    # to exclude all .file especially directories . and ..
            closedir(FHdir);
     
            foreach $s_project (@s_lproject) {
                $s_path = "$maindir/$s_client/$s_project";  # Chemin project courant
                next if !-d $s_path;
                push @{ $project{$s_client} }, $s_project;
            }
        }
    }
     
    #=========================================================================
    # Objectif : construire un repertoire des .dat et un repertoire des dsc
    # Resultat : une table contenant tous les @dsc de tous les dsc
    # 	     de toutes les etudes de tous les clients et une table
    # 	     contenant les listes des .dat de toutes etudes des clents
    #=========================================================================
     
    sub CheckProjectDir() {
     
        #_:  s_client : Indexe les clefs (client)  de la table %project
        #_:  s_project : Indexe les valeurs (etudes) de la table %project
        #_:  s_dir : stocke le project courant
        #_:  s_dsc : stocke le dsc du projet courant
        my ( $s_client, $s_project, $s_dir, $s_dsc );
        for $s_client ( keys(%project) ) {
            if ($check) { print "Client : $s_client\n"; }
     
            #for $s_project (values (%project))
            for $s_project ( @{ $project{$s_client} } ) {
                if ($check) { print "\tEtude : $s_project\n"; }
                $s_dir = "$maindir/$s_client/$s_project ";    #project courant
                next if !-d $s_dir;
                if ($check) {
                    print "\t\tChemin : $s_dir\n";
                }    # probleme d'affichage du chemin
                opendir( FHdir, $s_dir );
                if ( $? != 0 ) {
                    &MyWarning( __LINE__, $!, "Can not open directory $s_dir " );
                    next;
                }
                @ldat =
                  glob('*.dat ');    # la liste des fichiers .dat du project courant
                $s_dsc = glob('.dsc');    # dsc du project courant
                                          # $s_dsc=$s_project.".dsc";
                closedir(FHdir);
            }
     
    #push @{$datdir{$s_project}}, @ldat ; # %datdir a pour clef s_project et pour valeurs @ldat
            push @dscdir, $s_dsc;
        }
     
        return ( values(%datdir) );         # Retourner la liste des .dat d'un project
     
        return (values (%dscdir));    # Stocke les  dsc des etudes de tous les clients
    }

  7. #7
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Ah, je connaissais l'autovivification, mais j'ignorais qu'elle allait aussi loin. Ou du moins, j'ignorais que l'opérateur de déréférencement pouvait être utilisé pour créer une référence à la volée, rendant possible, sans initialisation préalable, cette écriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @{$datdir{$s_project}}, @ldat;
    En revanche, cette ligne ne fait pas ce que l'on veut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datdir{$s_project} = @ldat;
    Elle affecte la taille du tableau @ldat, pas ses éléments.

    J'aurais plutôt écrit ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datdir{$s_project} = [@ldat];
    Ou, pour utiliser l'écriture que j'ignorais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @{$datdir{$s_project}} = @ldat;

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par Schmorgluck Voir le message
    En revanche, cette ligne ne fait pas ce que l'on veut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datdir{$s_project} = @ldat;
    Tout à fait, j'ai corrigé cette erreur grossière dans mon message, bien vu !
    C'est bien évidemment la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datdir{$s_project} = [ @ldat ];
    que je voulais introduire

    @arm3366 : as-tu vu mon commentaire sur la position de l'affectation du @ldat ?
    (merci d'utiliser la balise CODE pour insérer ton code, icône )

  9. #9
    Inactif  
    Profil pro
    " "
    Inscrit en
    Janvier 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : " "

    Informations forums :
    Inscription : Janvier 2008
    Messages : 330
    Points : 254
    Points
    254
    Par défaut
    c'est noté, mais quand je veux retourner les listes des dsc et .dat, je aucun resultat.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 01/12/2013, 07h49
  2. [MySQL] comment lié une zone de liste à un champ de table en php-mysql sous dreamweaver cs4
    Par kitcarson23 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 27/10/2010, 13h41
  3. Réponses: 8
    Dernier message: 25/01/2010, 09h35
  4. Réponses: 2
    Dernier message: 16/05/2007, 16h13
  5. Réponses: 3
    Dernier message: 18/01/2007, 18h19

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