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 Delphi Discussion :

Comment vérifier si une structure n'est pas vide [FAQ]


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    803
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 803
    Points : 182
    Points
    182
    Par défaut Comment vérifier si une structure n'est pas vide
    Bonjour,

    Si je déclare une structure telle que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Type
      TmyStruc = record
        ... blabla ...
      end;
    Var
      myStruc : TMystruc;
    et que je prenne la précaution de vider ma structure par FullChar(myStruc,SizeOf(TmyStruc),#0) avant de l'adresser comme paramètre à une procédure ou fonction, comment savoir si elle est vide ?

    Je veux dire que si ma fonction est du type FaisQuelqueChose( myStruc ) avant de commencer l'algorithme de ma fonction comment vérifier que myStruc n'est pas vide sans contrôler tous les champs du record ?

    Quelqu'un connait-il un truc ?

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Tu peux faire un ZeroMemory (FillChar #0), et tester l'égalité à Zéro pour les entiers, les doubles, nil pour les chaines et pointeurs ... sinon passer avec du variant qui gère la nullité, le vide et une valeur ... sinon en faisant croire à Delphi que ton record est un tableau de Byte, genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var
      PtrS, Ptr: PByte;
    begin
      Ptr:= PByte(@myStruc); 
      PtrS := Ptr;
      While Ptr <> nil do
        Inc(Ptr); 
     
      Vide := (Integer(Ptr) = Integer(PtrS) + SizeOf(myStruc));
     
      ...
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    803
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 803
    Points : 182
    Points
    182
    Par défaut test de ta proposition
    J'ai essayé le code suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function TristiIsEmpty(const Rec:TPeekTristimulus ): boolean;
    var
      PtrS, Ptr: PByte;
    begin
      Ptr:= PByte(@Rec);
      PtrS := Ptr;
      While Ptr <> nil do
        Inc(Ptr);
     
      Result := (Integer(Ptr) = Integer(PtrS) + SizeOf(TPeekTristimulus));
    end;
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var
      Tristi: TPeekTristimulus;
    begin
      FillChar(Tristi,SizeOf(TPeekTristimulus),#0);
      if TristiIsEmpty(Tristi) then beep;
    Gros silence ! pas plus de beep que...

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    803
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 803
    Points : 182
    Points
    182
    Par défaut Trace de la fonction
    curieusement à la ligne result :
    Ptr est à nil et donc Integer(Ptr) = 0
    Ptrs est une adresse de type $12F544 et donc Integer(Ptrs) = 1242436
    SizeOf(TPeekTristimulus) = 52

    Donc result est à false

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    si tu lit la boucle, tu vois qu'elle continue jusqu'à ce que cela soit nil, avec le inc, cela se produit, cela indique en général que tu n'es plus dans de la mémoire accessible ... si quelqu'un pourrait expliquer ce phénomène, je serais preneur ...

    peut être que mettre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      While (Ptr^ = 0) and (Ptr < PtrS) do
    cette variante devrait avoir plus d'effet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function IsEmptyRecord(const Rec; SizeOfRec: Cardinal): boolean;
    var
      Ptr: PByte;
      PtrEnd: Cardinal;
    begin
      Ptr:= PByte(@Rec);
      PtrEnd := Cardinal(Ptr) + SizeOfRec;
      While (Ptr^ = 0) and (Cardinal(Ptr) < PtrEnd) do
        Inc(Ptr);
     
      Result := (Cardinal(Ptr) = PtrEnd);
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TFrmTestMemory.BtnIsEmptyRecord(Sender: TObject);
    var
      Tristi: TPeekTristimulus;
    begin
      FillChar(Tristi,SizeOf(TPeekTristimulus),#0);
      if IsEmptyRecord(Tristi, SizeOf(TPeekTristimulus)) then
        beep;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Dans l'autre sens ce serait mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    While (Cardinal(Ptr) < PtrEnd) and (Ptr^ = 0) do
    Sinon tu risques de lire ptr^ alors que tu as Cardinal(Ptr)>=PtrEnd.
    Autrement dit, tu risques de lire un octet en dehors de la structure, ce qui peut se traduire par un access violation si tu n'as pas de chance...

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    803
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 803
    Points : 182
    Points
    182
    Par défaut Fonction IsEmptyRecord
    Ok ça marche

    C'est d'autant plus intéressant que cette fonction peut être appelée pour n'importe quelle structure.

    Mile merci

  8. #8
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    sinon tu peux aussi comparer la memoire avec un objet vide.
    Par contre, il te faut initialiser une variable qui servira de comparatif, et n'est pas valable quel que soit le type de record. Le bon cote de la chose, c'est que si tu as des constantes pour ton record, tu peux directement les comparer.

    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
      TMyRec = record
        x: word;
        y: char;
        z: pointer;
      end;
     
    const
      MyEmptyRec: TMyRec = (); //tout  0, nil, ...
      MyFilledRec: TMyRec = (x: 5098; y: 'C'; z: Pointer($123456)); 
     
    var
      mr: TMyRec;
      x: boolean;
    begin
      mr := MyEmptyRec;
      CompareMem(@mr, @MyEmptyRec , sizeof(TMyRec)); //true
      mr := MyFilledRec;
      CompareMem(@mr, @MyFilledRec, sizeof(TMyRec)); //true
      CompareMem(@mr, @MyEmptyRec , sizeof(TMyRec)); //false
    end;

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 13/09/2013, 15h04
  2. Valider qu'une ListBox n'est pas vide
    Par davelop dans le forum ASP.NET
    Réponses: 9
    Dernier message: 23/05/2013, 15h17
  3. [AC-2003] Vérifier que le résultat d'une requête (n')est (pas) vide
    Par pedrus16 dans le forum VBA Access
    Réponses: 3
    Dernier message: 25/06/2009, 15h34
  4. Vérifier qu'une chaîne n'est PAS un nombre
    Par foxbond dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 06/03/2009, 08h21
  5. Réponses: 10
    Dernier message: 15/01/2008, 12h03

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