goto et Objective-C

Philippe49Philippe49 Membre
11:00 modifié dans API AppKit #1
Quelqu'un a déjà  rencontré des problèmes avec le goto en Objective-C ?

if(condition) goto LABEL;
.....


LABEL:
  char ** cStrings
.....


J'ai un projet C qui fonctionne avec ce branchement, ce qui est on ne peut plus normal, et en l'incluant dans un projet Obj-C, j'ai le message d'erreur syntax error before char ?  ???


«1

Réponses

  • schlumschlum Membre
    11:00 modifié #2
    #import &lt;Foundation/Foundation.h&gt;<br /><br />int main (int argc, const char * argv&#91;]) {<br /> &nbsp; &nbsp;NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />	int i;<br />	for(i=0;;++i)<br />		if(i==10) goto LABEL;<br />LABEL:<br /> &nbsp; &nbsp;// insert code here...<br /> &nbsp; &nbsp;NSLog(@&quot;Hello, World!&quot;);<br /> &nbsp; &nbsp;[pool release];<br /> &nbsp; &nbsp;return 0;<br />}
    


    --> Pas de problème...
    Essaie de faire "preprocess" histoire de voir si LABEL n'est pas une macro définie dans ton projet  :P

    PS : "goto" c'est une technologie d'un autre âge  :o
  • CéroceCéroce Membre, Modérateur
    11:00 modifié #3
    Oui, mais nous, tu sais, nous sommes des vieux...  ;)
    ça reste encore le meilleur moyen pour sortir de deux boucles imbriquées.  >:)
  • Philippe49Philippe49 Membre
    novembre 2008 modifié #4
    dans 1226924233:

    Oui, mais nous, tu sais, nous sommes des vieux...  ;)
    ça reste encore le meilleur moyen pour sortir de deux boucles imbriquées.   >:)

    Dans mon cas, cela me semblait le plus élégant :

    action1
    arrêter si réussite
    action2 utilisant la construction faite dans l'action1, mais pas la même méthode
    arrêter si réussite
    ...

    et les actions sont des fonctions C .


    dans 1226921901:

    Essaie de faire "preprocess" histoire de voir si LABEL n'est pas une macro définie dans ton projet  :P

    J'ai remplacé mon étiquette par MACHINTRUCCHOUETTE, pareil.
    Bon, je fais autrement ... mais je ne comprends pas.

    action1
    if(pas reussite) action2
    if(pas reussite) action3
    ...

    ...

    Cela fait un certain nombre de tests faits inutilement, mais bon.
  • schlumschlum Membre
    11:00 modifié #5
    Ben... En général pour faire ça on utilise une fonction et des "return"  :P
  • Philippe49Philippe49 Membre
    novembre 2008 modifié #6
    Non mes actions correspondent à  des fonctions différentes et des arguments différents en plus. Il me faudrait boucler sur un tableau de fonctions, et sans doute un argument void *. La lisibilité serait beaucoup plus faible qu'avec

    action1(..,..); if(condition) goto BAIL_OUT;
    action2(..,..,..,..); if(condition) goto BAIL_OUT;
    ....
    action8(..); if(condition) goto BAIL_OUT;

    BAIL_OUT:

  • schlumschlum Membre
    11:00 modifié #7
    Non, je voulais dire avoir une fonction "actions" :

    void actions(...) {<br />&nbsp; &nbsp; action1(..,..); if(condition) return;<br />&nbsp; &nbsp; action2(..,..,..,..); if(condition) return;<br />&nbsp; &nbsp; // ...<br />&nbsp; &nbsp; action8(..); if(condition) return;<br />&nbsp; &nbsp; // ...<br />}
    

  • Philippe49Philippe49 Membre
    novembre 2008 modifié #8
    Ah ok, j'avais pas compris ton idée , mais bon, ça ne fait que cacher un branchement identique à  un goto.
  • schlumschlum Membre
    11:00 modifié #9
    Euh... Tout cache des branchements identiques à  un goto... Les boucles, les branchements conditionnels...  :o
  • Philippe49Philippe49 Membre
    11:00 modifié #10
    Oui , mais je suis toujours réticent aux dogmes. Par exemple, j'ai des collègues informaticiens pour qui mettre plusieurs return dans une fonction est une hérésie, il y a d'ailleurs souvent des warnings dans ce type de situation.
    Pour moi la disparition du goto dans les années 80 était la volonté de supprimer ces codes en organigramme où la multiplicité des branchements nuisaient à  une bonne structuration du programme. De là  à  ne pas l'utiliser quand c'est une solution simple et lisible ...
    Le seul dogme que j'admets c'est : " un code doit être clair, sans astuce qui demande une double lecture "
     
  • schlumschlum Membre
    11:00 modifié #11
    Ah ben c'est pas un problème de "goto" ici, c'est juste que la solution de fonction dédiée est plus propre et plus lisible  ;)
  • Philippe49Philippe49 Membre
    11:00 modifié #12
    " plus propre et plus lisible " est ici une question d'appréciation dans un certain contexte, et si il y a sûrement des contextes où ta solution paraà®t plus propre, il y a d'autres contextes où la lecture est plus simple avec des goto. D'ailleurs, plusieurs exemples d'Apple et de Mac OS Programming (le second livre du Big Nerd Ranch) sont écrits ainsi.
    Mon problème , que je n'ai d'ailleurs toujours pas résolu, c'est pourquoi j'ai un bug.

    Merci pour ta solution que je n'avais pas envisagée.
  • schlumschlum Membre
    11:00 modifié #13
    Ce n'est pas une question de contexte je trouve...  ???
    Quand on lit un code et qu'on tombe sur un "goto", il faut chercher l'étiquette et aucune indication d'indentation ou autre peut nous dire rapidement où elle est ; particulièrement quand il y a plusieurs étiquettes (d'où le " plus lisible "  ;) ).
    Sans compter que les étiquettes se mettent en général en tout début de ligne et de ce fait perturbent la visibilité des indentations  :(
    Le " propre " étant en effet une notion subjective  8--)

    Pour le problème de compilation, je ne vois pas puisque mon exemple ci-dessus fonctionne  :P
  • Philippe49Philippe49 Membre
    11:00 modifié #14
    dans 1227187981:

    Quand on lit un code et qu'on tombe sur un "goto", il faut chercher l'étiquette et aucune indication d'indentation ou autre peut nous dire rapidement où elle est ; particulièrement quand il y a plusieurs étiquettes (d'où le " plus lisible "  ;) ).

    En l'occurence le nom choisi pour l'étiquette (BAIL_OUT) indique où elle se trouve, et de plus j'ai huit lignes avant cette étiquette, franchement la lecture est claire. Alors que l'appel d'une fonction à  but astucieux mais relativement abstrait, qui sera peut-être physiquement éloignée dans mon code, je ne suis prêt à  en payer le prix que si son contenu est lourd.
    En réalité dans le code au-dessus j'ai reporté la lourdeur du contenu dans trois fonctions annexes, dont le rôle est bien précis.
  • CéroceCéroce Membre, Modérateur
    11:00 modifié #15
    Je dois dire que je suis totalement d'accord avec Philippe sur ce coup-là  (comme quoi, des fois ça arrive  ;) )

    Pour comparaison, sans goto:
    BOOL sortie = NO;<br />for(x = 0; x &lt; 100000; x++)<br />{<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000; y++)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000; z++)<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Du code ici //<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortie = YES;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; if(sortie)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; if(sortie)<br />&nbsp; &nbsp; &nbsp; &nbsp; break;<br />}<br /><br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x,y,z);
    


    Avec goto:
    for(x = 0; x &lt; 100000; x++)<br />{<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000; y++)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000; z++)<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Du code ici //<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto SORTIE;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}<br /><br />SORTIE:<br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x,y,z);
    


    Il ne faut faire des sauts qu'en avant, autrement, ça revient à  faire des plats de spaghetti. Mais dire "ah non le goto c'est mal", c'est bien un dogme.

    [size=12pt]Avant le goto, mon code était terne. Maintenant, je suis bien dans mon code, et le regards des femmes à  mon sujet a changé. Alors faà®tes comme moi... adoptez le goto ![/size]

  • Philippe49Philippe49 Membre
    11:00 modifié #16
    dans 1227206343:

    [size=12pt]Avant le goto, mon code était terne. Maintenant, je suis bien dans mon code, et le regards des femmes à  mon sujet a changé. Alors faà®tes comme moi... adoptez le goto ![/size]

    v50xlfip.jpg

  • schlumschlum Membre
    novembre 2008 modifié #17
    BOOL sortie = NO;<br />for(x = 0; x &lt; 100000&amp;&amp;!sortie; x++) {<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000&amp;&amp;!sortie; y++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000&amp;&amp;!sortie; z++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortie = YES;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}<br /><br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x,y,z);
    


    Tu me permettras de le réécrire de cette manière ?  :P

    Mais pareil... pour ce genre de cas (somme toute assez rare), je préfère une fonction avec un return  :P


    De toute manière, il faut bien connaà®tre les techniques, car nombre de langages n'ont pas cette instruction (dont le Java !)  ;)
  • schlumschlum Membre
    11:00 modifié #18
    Allez, une autre technique qui me semble assez élégante  :)

    do {<br />	action1(..,..); if(condition) break;<br />	action2(..,..,..,..); if(condition) break;<br />	// ...<br />	action8(..); if(condition) break;<br />	// ...<br />} while(0);
    
  • psychoh13psychoh13 Mothership Developer Membre
    11:00 modifié #19
    En général, pour avoir un code propre et facile à  lire il vaut mieux limiter le plus possible les break, return et goto... Ma préférence est dans cet ordre personnellement... Je n'utilise pour ainsi dire jamais le goto.
  • AntilogAntilog Membre
    11:00 modifié #20
    dans 1227206343:

    [size=12pt]Avant le goto, mon code était terne. Maintenant, je suis bien dans mon code, et le regards des femmes à  mon sujet a changé. Alors faà®tes comme moi... adoptez le goto ![/size]


    YES!!
    GOTO POWER !!!
    :adios!: :brule:
  • AliGatorAliGator Membre, Modérateur
    11:00 modifié #21
    Hérésie !!

    Bon, je dois avouer que je suis loin d'être un fan du goto, et préfère largement les break ou surtout le découpage en fonctions distinctes sinon. Mais bon de là  à  brûler au bûcher ceux qui l'utilisent quand c'est justifié... faut savoir faire la part des choses. Le tout est surtout que ça ne devienne pas une habitude, le goto venant de la programmation itérative (ça me rappelle mes programmes en BASIC sur Apple ][e :) ou les fichiers BAT de windoze  ;D).
    Donc pour moi, c'est à  éviter... mais c'est toléré... à  condition que ce soit justifié  :P
  • Eddy58Eddy58 Membre
    11:00 modifié #22
    Pour ma part, quand je veux terminer une boucle, souvent, quand c'est possible, je force la valeur des variables à  la valeur voulue pour terminer la boucle, comme ça pas de problèmes.

    <br />for(x = 0; x &lt; 100000; x++) {<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000; y++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000; z++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; z=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}<br /><br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x,y,z);
    

  • schlumschlum Membre
    11:00 modifié #23
    dans 1227260834:

    Pour ma part, quand je veux terminer une boucle, souvent, quand c'est possible, je force la valeur des variables à  la valeur voulue pour terminer la boucle, comme ça pas de problèmes.

    <br />for(x = 0; x &lt; 100000; x++) {<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000; y++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000; z++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; z=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}<br /><br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x,y,z);
    




    Ouais mais là  pour le coup tu perds tes valeurs  ;) (du coup le NSLog à  la fin est foireux...)
  • psychoh13psychoh13 Mothership Developer Membre
    11:00 modifié #24
    Oui pour le coup c'est LE truc à  éviter. :)
  • ChachaChacha Membre
    11:00 modifié #25
    Pour ma part, j'ai une philosophie psycho-rigide :
    ni goto, ni break, ni return.

    Je m'explique : quand une fonction doit renvoyer une valeur, je ne mets qu'un seul return, et c'est la dernière instruction. Pour les contrôles de boucle, je traà®ne une variable d'erreur qui me permet de les stopper dans la condition des "for". Avec des "if", je décompose la fonction en morceaux à  exécuter uniquement s'il n'y a pas eu d'erreur précédemment.
    Exemple :

    int frululu(void)
    {
      int result = 0; //ma variable s'appelle toujours result
      int error = 0;
      if (!error)
        error = action1();
      if (!error)
        error = action2();
      for(int bla = 0 ; !error && bla < bliblu ; ++bla)
        ...
      return result; //Dernière instruction
    }


    Avant de me traiter de psychopathe, voici les raisons :
    -Quand on lit le code on sait tout de suite comment s'appelle la variable de retour, quel est son type, etc.
    -Quand on veut débugguer, on peut mettre des printfs partout, il seront toujours affichés dans le même ordre. Et pas de surprise : aucun goto ou break ne risque de passer par dessus.
    -Quand on se met à  poser des verrous (style NSLock() et compagnie), avec mon système, on a beaucoup moins de chances de sortir de la fonction en ayant sauté le unLock().

    En réalité, je m'autorise les break dans un seul cas : au début d'un for "nouvelle syntaxe".

    for(id glubglub in kapouik)
    {
      if (error) break;
      ...
    }


    Il est vraiment très rare que mon schéma soit plus contraignant à  lire/écrire que la sécurité qu'il apporte.

    +
    Chacha
  • ChachaChacha Membre
    11:00 modifié #26

    YES!!
    GOTO POWER !!!


    Alors pour les malades comme vous, je conseille le GOTO++ (http://www.gotopp.org//)
    C'est un langage dont le but est de rendre l'exécution la plus imprévisible possible.
    C'est un langage évolué : on peut même utiliser des sockets (fonction enfiler_chaussette(), je crois).
    C'est un langage avec des particularités inédites : une instruction permet d'effectuer un GOTO aléatoire.

    Oui, c'est drôle :)

    +
    Chacha
  • schlumschlum Membre
    11:00 modifié #27
    Ceux qui évitent les "break"... Vous n'utilisez pas "switch" non plus alors je suppose...  ???
  • Eddy58Eddy58 Membre
    11:00 modifié #28
    dans 1227263903:

    Ouais mais là  pour le coup tu perds tes valeurs  ;) (du coup le NSLog à  la fin est foireux...)


    Oui c'est vrai, comme je l'ai dis, ça dépend des cas, ici, il faut juste recopier le résultat dans d'autres variables si on a besoin des valeurs.

    <br />for(x = 0; x &lt; 100000; x++) {<br />&nbsp; &nbsp; for(y = 0; y &lt; 100000; y++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; for(z = 0; z &lt; 100000; z++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(condition) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; z2=z;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y2=y;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x2=x;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; z=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x=10000;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}<br /><br /><br /><br />NSLog(@&quot;Trouvé pour %i;%i;%i&quot;,x2,y2,z2);
    



  • ChachaChacha Membre
    11:00 modifié #29
    dans 1227271508:

    Ceux qui évitent les "break"... Vous n'utilisez pas "switch" non plus alors je suppose...  ???

    Ah ben si, je l'avais oublié celui-là . Bon, mais là  c'est pas trop pareil, puisque le break d'un case est toujours à  la fin de son bloc. Donc il ne saute pas au-dessus d'un bloc qui aurait pu être exécuté (ou alors ça devient vraiment un switch subtil).
    Bon, mais j'ai quand même, là  aussi, une ligne de conduite très claire :
    Je n'utilise le switch que sur les type énumérés, pour faire la part belle à  -Wswitch-enum.
    Pour tout le reste, c'est if...else if... else if...
    Alors ce serait moi le grand malade  :) ?

    +
    Chacha
  • AliGatorAliGator Membre, Modérateur
    11:00 modifié #30
    Non moi quand j'ai vraiment à  faire ça je le fait tout simplement :
    bool stop = 0;<br />for(x=0;(x&lt;maxX) &amp;&amp; !stop;x++) {<br /> &nbsp;for(y=0;(y&lt;maxY) &amp;&amp; !stop;y++) {<br /> &nbsp; &nbsp;for(z=0;(z&lt;maxZ) &amp;&amp; !stop;z++) {<br /> &nbsp; &nbsp; &nbsp;// blablabla<br /> &nbsp; &nbsp; &nbsp;if (condition) stop = 1;<br /> &nbsp; &nbsp;}<br /> &nbsp;}<br />}
    
    Comme schlum, en somme. On garde ainsi les valeurs de x,y,z et on sort jusqu'au niveau qu'on veut, etc.
  • Eddy58Eddy58 Membre
    11:00 modifié #31
    Il est vrai que je connaissais pas le truc du test dans les parenthèses du for. Bon à  savoir.
Connectez-vous ou Inscrivez-vous pour répondre.