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

Delphi Discussion :

Affecter des enregistrements


Sujet :

Delphi

  1. #1
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut Affecter des enregistrements
    Salut!

    Dans mon programme, j'ai déclaré des enregistrements du genre :
    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
    Type
      TAgenda = Packed Record
        nom: String[40];
        prenom: String[20];
        adresse: String[40];
        date: String[20];
        tel: String[30];
        fax: String[30];
        mail: String[30];
        note: Integer;
      End;
     
      TRepertoire = Packed Record
        liste1: TAgenda;
        liste2: TAgenda;
        liste3: TAgenda;
        perso: TAgenda;
        pro: TAgenda;
        divers: TAgenda;
      End;
     
    Var Rep1, Rep2: TRepertoire;
    J'ai besoin de comparer 2 variables de type TRepertoire, de modifier les éléments de ces variables, etc... Le problème est que je ne vois pas comment faire pour ne pas avoir des fonctions super longues, avec une ligne de code par enregistrement de TRepertoire, ou pire, une fonction pour chaque enregistrement de TAgenda... Par exemple, pour comparer 2 variables de type TRepertoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Fonction IsEgalRep(R1, R2: TRepertoire): Boolean;
    Begin
      Result := (R1.liste1.nom = R2.liste1.nom) And
                (R1.liste1.prenom = R2.liste1.prenom) And
                (R1.liste1.adresse = R2.liste1.adresse) And
    ...
    Le problème est aussi si un jour j'ai besoin de modifier mes types, ajouter ou supprimer un nouvel enregistrement, je devrais reprendre tout le code. Bref, auriez-vous une méthode à me proposer pour simplifier l'accès aux données ?
    Peut-être en utilisant les Class si ça n'est pas possible avec des enregistrements...

    Merci d'avance.

    ps: Ne tenez pas compte des noms d'enregistrements utilisés, il s'agit d'un exemple, mon programme n'est pas un agenda..

  2. #2
    Membre émérite Avatar de Yurck
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 16
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2005
    Messages : 682
    Par défaut
    Bonjour,

    Un Record c'est une grille de lecture d'un ensemble d'octets.
    Alors change ta grille et compare directement un record avec un autre en le castant avec ta nouvelle grille.

    a+

  3. #3
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Pourrais-tu utiliser mon code d'exemple pour illustrer ta proposition stp ?
    A quoi ressemblera le code de la fonction IsEgalRep ?
    Et comment accèdes-tu / redéfinis-tu les données avec une fonction ?

  4. #4
    Membre émérite Avatar de Yurck
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 16
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2005
    Messages : 682
    Par défaut
    Bien je m'explique, si tu prends deux photos et que tu les regardes au travers d'une passoire tu doit comparer celles-ci trous par trous.

    Alors enlève la passoire.

    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
     
     TAgenda = Packed Record
        nom: String[40];
        prenom: String[20];
        adresse: String[40];
        date: String[20];
        tel: String[30];
        fax: String[30];
        mail: String[30];
        note: Integer;
      End;
     
    { TCompareAgenda = Packed Record
        Ensemble : String[40 + 20 + 40 + 20 + 30 +30 + 30 + SizeOf(integer)] ;
      End;}
     
     TCompareAgenda = Packed Record
        Ensemble : String[212] ;
      End;
    Ta fonction devient plus simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Fonction IsEgalRep(R1, R2: TRepertoire): Boolean;
    Begin
      Result := TCompareAgenda(R1.liste1).ensemble = TCompareAgenda(R2.liste1).ensemble;
    end;
    j'ai tapé le code sans ctrl.

    a+

  5. #5
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Bien, tout d'abord, je te remercie pour ton explication et ta patience. Je me suis mal expliqué. Je rappel que je dois accèder à tous les champs. La fonction de comparaison n'est qu'un exemple type. D'ailleurs, si j'utilise ton code, la fonction IsEgalRep possèdera combien de ligne de code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Fonction IsEgalRep(R1, R2: TRepertoire): Boolean;
    Begin
      Result := 
        TCompareAgenda(R1.liste1).ensemble = TCompareAgenda(R2.liste1).ensemble And
        TCompareAgenda(R1.liste2).ensemble = TCompareAgenda(R2.liste2).ensemble And    
        TCompareAgenda(R1.liste3).ensemble = TCompareAgenda(R2.liste3).ensemble And
        TCompareAgenda(R1.perso).ensemble = TCompareAgenda(R2.perso).ensemble And 
        ...
    end;
    Je rappelle que le code que j'ai donné est un exemple type de la structure que je cherche à obtenir (enregistrements imbriqués). Seulement, imagine que mon enregistrement comporte 200 éléments différents... et que son type comporte lui aussi 200 éléments... La fonction IsEgalRep possèdera combien de ligne de code ?

    Ce que je recherche avant tout, c'est une façon simple d'accèder à des données, genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Procedure GetValue(Var obj; Rep: TRepertoire; Ag: TAgenda; Index: Integer);
    Begin
      obj := Rep.Ag.TAgenda(Index);
    End;
     
    Function SetValue(Var obj; Rep: TRepertoire; Ag: TAgenda; Index: Integer);
    Begin
      Rep.Ag.TAgenda(Index) := obj;
    End;
    Peut-être existe-t-il une solution avec les Classes...

  6. #6
    Membre chevronné Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Par défaut
    Pourquoi ne pas ajouter un champ pour identifier de façon unique chaque enregistrement et ne faire de recherche que sur celui-ci ?
    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
    Type
      TAgenda = Packed Record
        Identificateur : integer;
        nom: String[40];
        prenom: String[20];
        adresse: String[40];
        date: String[20];
        tel: String[30];
        fax: String[30];
        mail: String[30];
        note: Integer;
      End;
    
      TRepertoire = Packed Record
        Identificateur : integer;
        liste1: TAgenda;
        liste2: TAgenda;
        liste3: TAgenda;
        perso: TAgenda;
        pro: TAgenda;
        divers: TAgenda;
      End;
    ...ou est-ce je tape à côté ?

  7. #7
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Citation Envoyé par Bejaia-In
    ...ou est-ce je tape à côté ?
    C'est pas ce soir que j'aurais une solution apparemment.
    Je vais essayer d'utiliser les objets plutôt, merci à+

  8. #8
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    Bonjour,

    Ca me fait penser à la procedure TObjectxxx.Assign(source:TObjectxxx) que je crée dans la plupart de mes classes pour cloner une instance.

    J'ai pas résolu le problème, donc :
    - autant de lignes "varx:=source.varx" dans la procédure que d'éléments varx dans l'objet TObjectxxx,
    - quand je modifie la classe en ajoutant un élément, faut penser à modifier la procedure Assign (et aussi la procédure Clear qui réinitialise); Pfff ...

  9. #9
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    1 085
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2002
    Messages : 1 085
    Par défaut
    Je viens d'essayer ca et ça à l'air de marcher !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if CompareMem(@Rep1,@Rep2,SizeOf(TRepertoire)) 
      then
        Result := True
      else
        Result := False;

  10. #10
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Salut !

    Merci pour vos réponses très intérressantes !

    Le but est de pouvoir modifier la liste des éléments sans avoir à retoucher tout le code (enfin un minimum).
    Voici ce que j'ai trouvé de mon côté (vos avis sont bienvenus) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Type
      Agenda = (nom, prenom, adresse, tel, fax, mail, date, note);
      AgendaList = Array [Agenda] Of String[40];
      Repertoire = (liste1, liste2, liste3, perso, pro, divers);
      RepertoireList = Array [Repertoire] Of AgendaList;
     
      TRep = Packed Record
        Elem: RepertoireList;
      End;
    Pour la comparaison, 2 fonctions :
    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
    {----------------------------------------------------------------}
    Function IsEgalAgenda(Const Ag1, Ag2: AgendaList): Boolean;
    Var i: Integer;
    Begin
      Result := False;
      For i := 0 To SizeOf(Agenda) - 1 Do
        If (Ag1[Agenda(i)] <> Ag2[Agenda(i)]) Then Exit;
      Result := True;
    End;
     
    {----------------------------------------------------------------}
    Function IsEgalRep(Const Rep1, Rep2: TRep): Boolean;
    Var i: Integer;
    Begin
      Result := False;
      For i := 0 To SizeOf(Repertoire) - 1 Do
        If (IsEgalAgenda(Rep1.Elem[Repertoire(i)],
                         Rep2.Elem[Repertoire(i)]) = False) Then Exit;
      Result := True;
    End;
    Et pour accèder aux données, par exemple pour définir une valeur, soit j'utilise le nom des types, soit l'index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Var Rep1: TRep;
     
    Rep1.Elem[perso][nom] := 'Nouveau contact';
    ShowMessage(Rep1.Elem[Repertoire(3)][Agenda(0)]);
    Vous remarquerez que j'ai simplifié le type de base avec string[40]... Je suis en train de faire des tests pour utiliser d'autres types.

    Merci, et continuez à poster vos idées.

  11. #11
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Le code de comparaison que Portu a donné fonctionne vraiment bien !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      Result := CompareMem(@Rep1,@Rep2,SizeOf(TRepertoire))

  12. #12
    Membre émérite Avatar de Yurck
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 16
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2005
    Messages : 682
    Par défaut
    C'est un fait il semble excellent mais au même titre que le mien il semble aussi avoir une faille.
    Prenons deux structure simples a et b de type String[40].
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    a:= 'toto';
    b:= 'toto et titi';
    // CompareMem(@a, @b, sizeof(a)) = false
    b:= 'toto';
    // CompareMem(@a, @b, sizeof(a))  = ??
    Je ne suis pas sur que les tous les octets de a et de b soit égaux sur Sizeof(a) même si pourtant a=b.

    Enfin il faudrait voir à le tester sur plusieurs machine et avec plusieurs compilateurs mais il me semble que sur b il doit rester après la fin de chaîne des résidus de son ancienne valeur.

    a+

  13. #13
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Je ne sais pas, en tous les cas, CompareMem fonctionne très bien d'après les tests que j'ai effectué. Il faut aussi savoir que le 1er octet d'une chaine (index 0) correspond à la taille de cette chaine. Je suppose que cela est pris en compte par le système pour justement éviter ce genre de bug... enfin je l'espère.

    [EDIT]Et bien non en fait. Après avoir testé l'exemple donné ci-dessus, cela ne fonctionnera pas dans le cas des chaînes plus courtes que celles précédemment comparées. Il faudra prévoir de remplir les caractères suivants la chaîne par des espaces, ou réinitialiser les chaînes, à moins que d'autres membres aient une meilleure solution à proposer...

  14. #14
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    Bonjour,

    Le code de portu
    et le tien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    For i := 0 To SizeOf(Agenda) - 1 Do
        If (Ag1[Agenda(i)] <> Ag2[Agenda(i)]) Then Exit;
    peuvent donner des résultats erronés :
    En effet, les caractères aprés la fin de chaine doivent être ignorés.
    si on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Agenda[1]:='ABCD' ;
    Agenda[2]:='XYZ' ;
    Agenda[1]:='' ;
    Agenda[2]:='' ;
    L'expression Agenda[1]=Agenda[2] sera vraie, mais les contenus mémoires différents.

    Pour calculer l'égalité de 2 short string s1 et s2, l'indice de la boucle sur chaque caractère va de zéro (pour vérifier l'égalité des longueur) à length(s1).

  15. #15
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    Au passage, je me suis rendu compte d'une erreur que j'ai fait en pensant que SizeOf me retournait le nombre d'éléments. Par exemple, si je veux accèder à tous les éléments avec une boucle, je dois d'abord calculer leur nombre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Var s1, s2, i, j: Integer;
     
    s1 := SizeOf(AgendaList) Div SizeOf(String[40]);
    s2 := SizeOf(RepertoireList) Div SizeOf(String[40]);
     
    For i := 0 To (s2 Div s1) - 1 Do
     For j := 0 To s1 - 1 Do
      Rep.Elem[Repertoire(i)][Agenda(j)] := 'Valeur défaut;
    J'avais aussi essayé avec les fonctions High et Length, mais elles ne fonctionnent pas et la fonction Count n'existe pas. Je n'ai trouvé que cette méthode pour réaliser ce genre de boucle. Mais si vous avez mieux, je suis preneur...

  16. #16
    Membre émérite Avatar de Yurck
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 16
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2005
    Messages : 682
    Par défaut
    Essaie de démarrer ta boucle au début de ton ensemble jusqu'à sa fin de la façon 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
    19
     
    Type
      Agenda = (nom, prenom, adresse, tel, fax, mail, date, note);
      AgendaList = Array [Agenda] Of String[40];
      Repertoire = (liste1, liste2, liste3, perso, pro, divers);
      RepertoireList = Array [Repertoire] Of AgendaList;
     
      TRep = Packed Record
        Elem: RepertoireList;
      End;
     
    Var 
      i : Repertoire;
      j : Agenda;
     
     
    For i := liste1 to divers Do
     For j := nom To note  Do
      Rep.Elem[Repertoire(i)][Agenda(j)] := 'Valeur défaut';
    Evidemment cela implique que pour modifier le moins possible ton code au fur et à mesure de son avancement tu insère des éléments dans tes ensembles en milieu de tableau et surtout pas en fin (ni au début d'ailleur)

    a+

  17. #17
    Membre Expert
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Par défaut
    oui, cette méthode me convient.
    Pour la comparaison, j'utilise cette boucle.

    Sujet [Resolu] Bravo Messieurs !

    Les modifications sont automatiquement prises en compte avec vraiment un minimum de code à modifier, à+

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 12/11/2010, 14h34
  2. Affecter une couleur à des enregistrements
    Par codial dans le forum Bases de données
    Réponses: 21
    Dernier message: 17/09/2009, 16h14
  3. Réponses: 12
    Dernier message: 24/01/2006, 12h38
  4. Réponses: 3
    Dernier message: 29/12/2003, 13h47
  5. Enlever tous les M&Mme des enregistrements
    Par marc olivier dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 17/07/2003, 12h24

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