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 :

[XE2] Modifier un élément d'une boucle for..in


Sujet :

Langage Delphi

  1. #1
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 438
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 438
    Points : 3 076
    Points
    3 076
    Par défaut [XE2] Modifier un élément d'une boucle for..in
    Bonjour

    J'ai ce code suivant qui ne fonctionne pas (je vois bien le problème).

    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
     
     
      TCouple = record
        nom: string;
        nombre: integer;
      end;
      PCouple = ^TCouple;
     
      TCouples = TList<TCouple>;
     
    ......
     
      var
        cpl: TCouple;
      begin
        for cpl in couples do
          if cpl.nom = nc then
          begin
            Inc(cpl.nombre);   <<<==== Partie gauche non affectable
            Break;
          end;
    J'ai essayé de passer par un pointer sur cpl mais rien à faire.

    A votre avis, il y a une solution ou est-ce que je dois passer par une boucle indexée ?

    Papy !
    J-L aka Papy pour les amis

  2. #2
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Pour utiliser une boucle for .. in il te faut implémenter un itérateur. Au plus urgent, utilises une boucle. On est pas dans un langage managé qui s'appuie sur un framework qui prémache tout. Ici, dans un langage natif, il faut tout coder pour que ça marche.
    EDIT : j'ai fait le test, j'ai compris l'origine du problème.

    Comme tu utilises un type record ça ne marchera pas avec la boucle for .. in, il faut déclarer ton type en dérivant d'une classe. L'itérateur existe puisque tu utilises une classe générique.

    Il y a des différences entre le type record et une classe qui font que tantôt on pourra préférer l'un à l'autre.

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 522
    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 522
    Points : 25 052
    Points
    25 052
    Par défaut
    Maintenant, les débutants commencent avec les génériques <> et l'opérateur in apparu respectivement en 2009 et 2007 si je ne m'abuse, alors que Delphi existe depuis 1995 !

    Du coup comme le fait remarquer chaplin, les débutants ne connaissent plus les opérateurs et la syntaxe de base !

    Perso, j'ignore totalement comme cela fonctionne exactement puisque je n'ai pas une version de Delphi assez récente (j'ai BCB6, C++2007 et XE2 mais pas de Delphi), la variable cpl reçoit une copie du record ou une référence ?

    Effectivement, la "boucle indexée" devrait te permettre de résoudre ton problème

    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
      var
        i: integer;
        cpl: TCouple;
      begin
        for i := 0 to couples.Count - 1 do
        begin
          cpl := couples[i];
          if cpl.nom = nc then
          begin
            Inc(cpl.nombre);
            couples[i] := cpl; // très important !
            Break;
          end;
        end;
      end;
    sinon, comme tu utilises un break, j'écrirais cela totalement autrement !

    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
      var
        i: integer;
        found: boolean;
        cpl: TCouple;
      begin
        i := 0;
        found := false;
        while found and (i < Count) do
        begin
          cpl := couples[i];
          found := cpl.nom = nc;
          if found then
          begin
            Inc(cpl.nombre);
            couples[i] := cpl; // très important !
          end;
        end;
      end;
    Enfin, j'utiliserais plutôt un TDictionary ou une TStringList pour optimiser les recherches sur le Nom, surtout si cela sera fréquent
    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

  4. #4
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    la variable cpl reçoit une copie du record ou une référence ?
    Tu as mis exactement le doigt sur l'origine du problème. La valeur fournie par l'itérateur est en lecture seule, pour un type classe ça passe, pour le type record, le compilateur refuse.

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 522
    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 522
    Points : 25 052
    Points
    25 052
    Par défaut
    On voit donc apparaître de nouveau problème qui n'en était pas à l'époque

    En C++, l'itérateur sur un struct fourni une référence que l'on peut modifier !

    Code c++ : 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
    //---------------------------------------------------------------------------
      typedef struct
      {
        AnsiString Name;
        int Value;
      } TNamedInt;
    //---------------------------------------------------------------------------
    #include <vector>
    //---------------------------------------------------------------------------
    void __fastcall TLanguageBasicsForm::BtnStdVectorBasicsClick(TObject *Sender)
    {
      typedef std::vector<int> TIntVector;
      TIntVector IntVector;
     
      IntVector.push_back(11);
      IntVector.push_back(22);
      IntVector.push_back(33);
     
      MemoTrace->Lines->Add("IntVector : ");
      int i = 0;
      for (TIntVector::const_iterator it = IntVector.begin(); it != IntVector.end(); ++it)
        MemoTrace->Lines->Add(AnsiString().sprintf("IntVector[%d] = %d", i++, *it));
     
      TIntVector::const_iterator itOpTest = IntVector.begin();
      MemoTrace->Lines->Add(IntToStr(*itOpTest++));
     
      for (TIntVector::iterator it = IntVector.begin(); it != IntVector.end(); ++it)
        *it = *it * 2;
     
      MemoTrace->Lines->Add("IntVector * 2 : ");
      i = 0;
      for (TIntVector::const_iterator it = IntVector.begin(); it != IntVector.end(); ++it)
        MemoTrace->Lines->Add(AnsiString().sprintf("IntVector[%d] = %d", i++, *it));
     
     
      typedef std::vector<TNamedInt> TNamedIntVector;
      TNamedIntVector NameIntVector;
     
      TNamedInt tmp = {"Toto", 11};
      NameIntVector.push_back(tmp);
      TNamedInt tmp2 = {"Titi", 22};
      NameIntVector.push_back(tmp2);
      TNamedInt tmp3 = {"Tata", 33};
      NameIntVector.push_back(tmp3);
     
      MemoTrace->Lines->Add("NameIntVector : ");
      i = 0;
      for (TNamedIntVector::const_iterator it = NameIntVector.begin(); it != NameIntVector.end(); ++it)
        MemoTrace->Lines->Add(AnsiString().sprintf("IntVector[%d] = \"%s\", %d", i++, it->Name, it->Value));
     
      i = 0;
      for (TNamedIntVector::iterator it = NameIntVector.begin(); it != NameIntVector.end(); ++it)
      {
        it->Name = it->Name + "_Modified";
        it->Value = it->Value * 2;
      };
     
      i = 0;
      for (TNamedIntVector::const_iterator it = NameIntVector.begin(); it != NameIntVector.end(); ++it)
        MemoTrace->Lines->Add(AnsiString().sprintf("IntVector[%d] = \"%s\", %d", i++, it->Name, it->Value));
    }

    Code rien : 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
     
    IntVector : 
    IntVector[0] = 11
    IntVector[1] = 22
    IntVector[2] = 33
    11
    IntVector * 2 : 
    IntVector[0] = 22
    IntVector[1] = 44
    IntVector[2] = 66
    NameIntVector : 
    IntVector[0] = "Toto", 11
    IntVector[1] = "Titi", 22
    IntVector[2] = "Tata", 33
    IntVector[0] = "Toto_Modified", 22
    IntVector[1] = "Titi_Modified", 44
    IntVector[2] = "Tata_Modified", 66


    vous notere l'accès via *it ou it->C'est plus subtil que l'utilisation de pointeur, en fait derrière il y a une surcharge de l'opérateur du type const_iterator qui fourni le type générique ...

    on voit que le C++ possède les génériques depuis bien plus longtemps que Delphi !
    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
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 438
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 438
    Points : 3 076
    Points
    3 076
    Par défaut
    Citation Envoyé par chaplin Voir le message
    [S]
    EDIT : j'ai fait le test, j'ai compris l'origine du problème.

    Comme tu utilises un type record ça ne marchera pas avec la boucle for .. in, il faut déclarer ton type en dérivant d'une classe. L'itérateur existe puisque tu utilises une classe générique.

    Il y a des différences entre le type record et une classe qui font que tantôt on pourra préférer l'un à l'autre.
    Avec une classe, ça passerait effectivement. Mais je pensais plutôt à un équivalent de ce qui existe en php et qui permet de modifier les éléments dans une situation équivalente.

    Je suis finalement passé par une boucle "normale"

    Merci
    J-L aka Papy pour les amis

  7. #7
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 438
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 438
    Points : 3 076
    Points
    3 076
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message

    Enfin, j'utiliserais plutôt un TDictionary ou une TStringList pour optimiser les recherches sur le Nom, surtout si cela sera fréquent
    C'est vrai que c'était aussi une solution mais la question était plus pour la connaissance qu'autre chose. C'était pour un problème ponctuel mais qui m'évitera de poser la question à un moment critique .

    Merci
    J-L aka Papy pour les amis

  8. #8
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 438
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 438
    Points : 3 076
    Points
    3 076
    Par défaut
    Je n'ai jamais "appris" le C++ ... mais je tacherai de m'y mettre , à l'occasion


    Merci à tous
    J-L aka Papy pour les amis

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

Discussions similaires

  1. [Batch] Evaluation d'une variable modifiée dans une boucle FOR
    Par dedz dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 22/10/2009, 17h55
  2. modifier le pas d'une boucle for ?
    Par pouponsaltro dans le forum Débuter
    Réponses: 3
    Dernier message: 07/03/2009, 09h11
  3. Modifier une boucle <<for>>
    Par Mataka dans le forum MATLAB
    Réponses: 22
    Dernier message: 31/05/2007, 08h20
  4. Réponses: 5
    Dernier message: 30/05/2007, 18h08
  5. [Débutant] Modifier la limite d'une boucle For dynamiquement
    Par seiryujay dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 15/12/2006, 18h45

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