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 :

GOTO dans boucle While


Sujet :

Delphi

  1. #1
    Membre du Club
    GOTO dans boucle While
    Bonjour

    Dans une boucle While j exécute une requête sur une date, si le nombre de résultat est 0 alors je fais un goto vers une partie du code qui ajoute un jour à la date recherchée.
    Selon ma logique cela fonctionnerait mais le compilateur n est pas du même avis que moi.
    Je précise que j utilise GOTO parce que je débute totalement en Delphi et que j'ai le souvenir du basic amstrad et que depuis cette date je n ai jamais essayé de programmer...


    J ai le code 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
     
     with form1.qry do
      begin
     
      while iTemp < 1 do 
        begin
          Req := 'ma requete contenant Jour_Cherche';
          sql.clear();
          sql.Add(Req);
          try
            Open();
            if RowsAffected = 0 then
            begin
              goto SuiteBoucle;
            end;
            sTemp := fieldbyname('Ladate').AsString;
          except
            result := false;
            exit;
          end;
     
        SuiteBoucle:
          Jour_Cherche := incday(Jour_Cherche, 1);
          inc(iTemp);
        end;
    End;


    A la compilation il affiche le message d erreur suivant :
    'GOTO SuiteBoucle' conduit dans ou hors d'une instruction TRY, ou hors d'une instruction FOR-IN dont l'énumérateur a un destructeur

    Si je comprends bien dans mon cas précisément, cela fait sortir de la boucle ? Alors comment conserver un goto dans une boucle while ?

    Donc ma question est la suivante :
    Comment procéder en sachant que je fais une suite de requêtes du même type et que chaque fois que le résultat est nul je souhaite ne pas exécuter les requêtes suivantes.
    Je pourrais mettre un boolean et le tester à chaque nouvelle requête mais j essaie d'apprendre à coder proprement et je trouve cette façon de procéder plus tôt 'simpliste' alors que le goto me donnait l impression d un code plus propre.
    merci de vos conseils

  2. #2
    Membre émérite
    Bonjour,

    je pense que ce qui ne lui plait pas c'est la sortie du try Except ?
    Je vais peut être dire une grosse bêtise, mais cela change quoi si tu mets l'étiquette SuiteBoucle après l'instruction 16 ?

    A+
    Charly

  3. #3
    Rédacteur/Modérateur

    Bonjour,

    un GOTO , un Exit dans une boucle while

    le goto me donnait l'impression d'un code plus propre.
    Alors là non ! Déjà je ne comprends pas ce que vous voulez faire exactement , Itemp n'est pas initialisée et pire incrémentée donc la boucle sera infinie


    s'il s'agit de trouver la date après un "trou"

    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
    var jourcherche : TDate;
    ....
     
    jourcherche:=Date;
    with qry do
      begin
       Text:='SELECT LaDate FROM latable WHERE LaDate=:J'
       repeat
          Close;
          ParamByName('J').asInteger:=JourCherche;      
          Open;
             if FieldByName('JOUR').isnull  then Jour_Cherche := incday(Jour_Cherche, 1);
          else begin                    
              sTemp := fieldbyname('Ladate').AsString;
              break;
          end;
        until (1=1)  
       Close;
    end;
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  4. #4
    Membre du Club
    Déjà je ne comprends pas ce que vous voulez faire exactement
    A priori mes explications sont aussi limpides que mon code.

    I est initialisé avant à 0. Il n est là que parce que je voulais limiter la durée du test, j ai prévu de boucler sur Jour_Cherche...

    Ce que je cherche à faire est une suite de requêtes basées sur une date.

    Si la première renvoi quelque chose, on passe à la suivante, si elle renvoi quelque chose, on passe à la 3eme.

    Si une requête ne renvoi rien, on n exécute pas les suivantes, on incrémente de un jour et on repart au début de la boucle.

    Le try...except est là pour que si une erreur intervient durant la requête, on sort de la fonction en renvoyant nul.

  5. #5
    Rédacteur/Modérateur

    Bonjour,
    A priori mes explications sont aussi limpides que mon code.
    Et Je ne comprends toujours pas quel est l'objectif final surtout s'il n'y a aucun traitement. Pourquoi passer par un incrément de jour alors qu'une requête sur la table entière permet d'obtenir la suite de date ?
    Déjà, indiquez exactement ce que vous voulez obtenir en faisant votre boucle, ensuite des indications comme le SGBD, la structure de la table, la version de Delphi, les composants de connexion seront des indications importantes

    autre exemple :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    with query do 
       begin 
         SQL.Text:='SELECT LADATE FROM LATABLE WHERE condition ORDER BY LADATE'; // bien sûr un index sur LADATE optimisera
         Open;
         while not EOF do 
           begin
               // traitement quelconque sur date existante; 
              Next;
              // if (test d'arrêt) then break;
           end;
         Close; // ou pas 
    end;
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  6. #6
    Expert éminent sénior
    je n'ai pas lu le code mais voici quelques rappels

    GOTO c'est moche

    pour sortir d'une boucle WHILE on peut utiliser BREAK
    pour boucler directement dans un WHILE on peut utiliser CONTINUE (on saute sur la condition du WHILE)

    si le code devient alambiqué, le plus simple et de faire un appel de fonction (éventuellement locale) qui pourra utiliser EXIT pour revenir dans le code de la boucle.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    begin
      Done := False;
      while not Done do
      begin
        if not <prerequis> then Continue; // attention à ne pas faire un boucle infinie !
        if <terminé> then Break; // sort de la boucle
        Done := Traitement(); // la logique de traitement
      end;
    end;


    avec

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function Traitement: Boolean;
    begin
      if <condition1> Exit(False); // il faut continuer la boucle
      if <condition2> then Exit(True); // c'est bon c'est fini
      Result := False; // par défaut on continue
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Membre actif
    Bonjour MoiStéphane,

    Avec un titre comme celui-là, tu vas faire hérisser les poils de bon nombre de programmeurs.
    Les Goto, Jump et autre sauts sont à proscrire autant que possible car avec un peu d'abus, le code devient très compliqué à comprendre et à maintenir.
    Certains langage n'implémente même pas cette fonction, ce qui montre qu'avec un peu de recherche, on peux s'en passer. Evidemment, il existe des cas, ou des applications qui le justifie mais elles sont assez rares.

    Comme tu prends soin de gérer les exceptions, il semble tu cherches à construire un code solide et que ce n'est pas un test un peu bidouillé...
    En grattant un peu, tu trouveras une solution plus efficace que celle ci plutôt que de chercher à la faire fonctionner...

    Bon code,
    Windows 7 / Delphi Tokyo
    "Les choses ne changent pas. Change ta façon de les voir, cela suffit" Lao Tseu

  8. #8
    Membre du Club
    @ Galet
    Comme tu prends soin de gérer les exceptions, il semble tu cherches à construire un code solide et que ce n'est pas un test un peu bidouillé...
    Effectivement cen est pas un test bidouillé, j essaie de prendre de bonnes pratiques et teste au maximum au fil du code car je débute et tout n est pas évident...

    @ Paul TOTH
    pour boucler directement dans un WHILE on peut utiliser CONTINUE (on saute sur la condition du WHILE)
    Merci, cela correspond parfaitement à ce que je cherchais à faire.

    @ SergioMaster
    Et Je ne comprends toujours pas quel est l'objectif final surtout s'il n'y a aucun traitement. Pourquoi passer par un incrément de jour alors qu'une requête sur la table entière permet d'obtenir la suite de date ?
    Déjà, indiquez exactement ce que vous voulez obtenir en faisant votre boucle, ensuite des indications comme le SGBD, la structure de la table, la version de Delphi, les composants de connexion seront des indications importantes
    Parce que je débute et que je ne maîtrise pas plus delphi que sqlite... Mais il faut bien commencer alors je vais à ce que je pense être le plus logique même si ma logiques est pas nécessairement celle d un développeur...helas
    S il n y a aucun traitement c est que je n ai pas pu l implanter car lors du test de la boucle, le goto rendait la suite impossible et ne pouvait le solutionner je me suis dirigé sur le forum...

    Mais à priori mon principal souci est tout de même de ne pas être capable d'exposer mon problème

    Merci pour votre aide ! et votre patience ;-)

  9. #9
    Expert éminent sénior
    et si je prend le code, il pourrait s'écrire comme ceci
    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
     
    with form1.qry do
      begin
     
      try
     
        while iTemp < 1 do 
        begin
          Req := 'ma requete contenant Jour_Cherche';
          sql.Text := Req;
          Open();
          if RowsAffected = 0 then
          begin
              goto SuiteBoucle;
          end;
          sTemp := fieldbyname('Ladate').AsString;
     
        SuiteBoucle:
          Jour_Cherche := incday(Jour_Cherche, 1);
          inc(iTemp);
        end;
     
      except
        result := false;
        exit;
      end;
     
    End;


    ce qui peut donc s'écrire comme ceci

    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
     
    with form1.qry do
      begin
     
      try
     
        while iTemp < 1 do 
        begin
          Req := 'ma requete contenant Jour_Cherche';
          sql.Text := Req;
          Open();
          if RowsAffected <> 0 then
          begin
            sTemp := fieldbyname('Ladate').AsString;
          end;
          Jour_Cherche := incday(Jour_Cherche, 1);
          inc(iTemp);
        end;
     
      except
        result := false;
        exit;
      end;
     
    End;


    mais une chose me chagrine, iTemp n'est pas inialisé, mais en admettant qu'il soit à 0 au départ, le boucle ne bouclera jamais
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #10
    Membre du Club
    mais une chose me chagrine, iTemp n'est pas inialisé, mais en admettant qu'il soit à 0 au départ, le boucle ne bouclera jamais
    initialement je bouclais sur les dates mais je l ai utilisé pour pouvoir contrôler le nombre d itérations plus simplement car dans mes requêtes sur les jours je dois tester tout un tas de truc dont les jours fériés, les week-end etc. Ainsi je pouvais chercher dans la base, visuellement je jour ferié et executer le nombre d iterations suffisante pour y parvenir et ainsi savoir, s il y avait un pb, s il était du au jour férié ou au reste....

    je pense que les programmeurs expérimentés doivent mettre en place des moyens de contrôles plus précis .

    j ai vu, alors que je cherchais un langage à utiliser qui me semblait à ma portée, que dans windev il existe une fonction trace ( de mémoire) qui permet de tester au fil du code, les variables. j aurais aimé avoir cette possibilité mais à la place j’arrête le code quand je connais par avance la valeur de ce que je cherche et ainsu peut comparer.
    ça fait peut être très amateurs mais je n en suis qu'au début, j ai installé delphi le week end dernier. je m initie...


    merci pour tous ces conseils

  11. #11
    Expert éminent sénior
    sous Delphi j'utilise souvent deux astuces toutes bêtes

    1) afficher des valeurs

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
      AllocConsole;
      WriteLn('la valeur de s = ', s);


    2) mettre un point d'arrêt qui ne prend pas des plombes

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if <condition>then
      begin
        AllocConsole;  // mettre un point d'arrêt sur cette ligne
        WriteLn('La condition est vraie');
      end;


    un point d'arrêt sans condition c'est pas pratique dans une boucle
    un point d'arrêt avec condition c'est très lent car Delphi doit évaluer la condition à chaque itération
    en mettent test directement dans le code on retrouve une exécution rapide avec un point d'arrêt sans condition qui ne ralenti pas le debuger
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  12. #12
    Membre du Club
    Merci pour ces conseils.

    Je me suis inscrit à un webinaire pour débutant et je me suis acheté, d occasion, ce bouquin pour acquerir de bonnes bases. par contre il n y a plus le CD. Existe t il un lien ou les exemples seraient toujours disponibles en téléchargement ?

  13. #13
    Expert éminent sénior
    les exemples du livre

    http://www.execute.fr/CODE-LIVRE.zip
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Membre du Club
    merci super