iagine ce que ça donne avec une centaine de champs, quand tous saufs le dernier ne sont pas présents.... tu marques un if avec cent tests dedans? Pas très lisible tout ça...Envoyé par gege2061
iagine ce que ça donne avec une centaine de champs, quand tous saufs le dernier ne sont pas présents.... tu marques un if avec cent tests dedans? Pas très lisible tout ça...Envoyé par gege2061
Bonjour,
Le "goto" c'est très bien si on ne l'utilise qu'à bon escient !
Il est, à mon avis, parfaitement correct d'utiliser cette instruction décriée
dans le cas des traitements d'erreur où il est nécessaire de stopper l'exécution du programme sans autre forme de réflexion, le "goto" renvoie à la routine d'erreur qui termine le programme ou la fonction.
J'ai aussi vu des utilisations du "goto" (en COBOL) pour envoyer directement à la fin d'une procédure utilisée en "PERFORM".
Dans les autres cas il vaut mieux éviter le "goto" qui rend souvent le code plus difficile à lire. Quoique les "bardées" de "if" imbriqués ne soient pas plus faciles a suivre s'il y a (je l'ai déjà vu) plus de deux niveaux d'imbrication. Mais il s'agit là plus d'une mauvaise structuration du code...
Cordialement
je code en asm, j'ai pas encore implémenté tout dans ma lib, mais le goto n'est pas prévu du tout. pour la simple raison que le goto, il est souvent implicite.
remarquez donc que la boucle for est obligée de faire un test, puis un branchement conditionnel, donc, un goto conditionnel.
je dirait que l'utilisation du goto peut être cool si utilisé à l'intérieur d'une fonction, sans jamais en sortir.
si l'on doit faire un goto vers un truc en dehors de notre fonction, il faut alors passer un paramètre indiquant le goto à faire avant de sortir de la fonction, puis avec un petit bout de code, effectuer notre goto à l'intérieur d'une condition.
le goto est implicite dans tellement d'instructions C de base qu'il est inutile de les lister.
le goto pur, lui, c'est juste un ordre pour signaler qu'il faut changer de bout de code, un peut comme si l'on faisait de la gestion de multitache, des trucs de système, pas des trucs d'applications.
cela dit, personne n'interdit un codeur de créer un microsysteme dans une application, pour gérer des choses, et utiliser des gotos, en général un seul dans la fonction tache_exec(), et utiliser des gotos dans le code principal pour appeler périodiquement la fonction tache_exec(), sans se soucier du contexte, ce quyi revient en fait à une interruption, ce qui est un goto asynchrone, périodique ou non.
mais bon, il y a le call, c'est à dire appel de fonction, qui permet de faire encore mieux.
donc, le goto passe à la trappe. même en asm, car jmp semble plus approprié pour signifier l'action du goto.
et oui, on jumpe, on saute littéralement dans une autre partie de code. une action nette.
j'ai pris au hasard un code asm, et j'en ai isolé le nombre de JMP purs (goto).
j'ai trouvé une fonction avec 5 goto (jmp) à l'intérieur
et je vais en faire une petite analyse simple.
case1 ou case2
Code asm : 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 proc MainDlg hdlg, msg, wparam, lparam push ebx esi edi cmp [msg], WM_INITDIALOG ;case WM init dialog je .wminitdlg ;on fait donc ce qui est là bas. cmp [msg], WM_COMMAND ;idem, autre case je .wmcommand ;autre case, autre routine cmp [msg], WM_CLOSE ;encore un case je .wmclose;etc.. xor eax, eax ;retourner 0 car on à rien fait, eax, c'est le return ? du C jmp .finish ;on a terminé les cases, donc, endcase .wminitdlg:;case 1 invoke capCreateCaptureWindow, _camtitle, WS_VISIBLE + WS_CHILD, 10, 10,\ 266, 252, [hdlg], 0 mov [hWebcam], eax jmp .finish ;ho, on a encore fini notre bout de case .wmcommand:;case 2 cmp [wparam], BN_CLICKED shl 16 + ID_START je .startbutton ;case2.1 cmp [wparam], BN_CLICKED shl 16 + ID_STOP je .stopbutton ;case2.2 cmp [wparam], BN_CLICKED shl 16 + ID_CLICK je .clickbutton ;case2.3 .wmclose: invoke SendMessage, [hWebcam], WM_CAP_DRIVER_DISCONNECT, _camtitle, 0 invoke EndDialog, [hdlg], 0 ;on sort ici, notre endcase, endfor, endif, end_quelque_chose... .finish: pop edi esi ebx ;petit bout d'out-it impossible à contourner, sinon crack!!! ret .startbutton: ;case2.3 invoke SendMessage, [hWebcam], WM_CAP_DRIVER_CONNECT, [nDevice], 0 invoke SendMessage, [hWebcam], WM_CAP_SET_SCALE, TRUE, 0 invoke SendMessage, [hWebcam], WM_CAP_SET_PREVIEWRATE, [nFPS], 0 invoke SendMessage, [hWebcam], WM_CAP_SET_PREVIEW, TRUE, 0 jmp .finish ;fini le case .stopbutton:;case2.2 invoke SendMessage, [hWebcam], WM_CAP_DRIVER_DISCONNECT, _camtitle, 0 jmp .finish ;etc... .clickbutton:;case2.1 invoke SendMessage, [hWebcam], WM_CAP_FILE_SAVEDIB, 0, _filename jmp .finish;etc... endp
dans case2, il y a 3 sous cases.
et tous font partie de la même fonction, qui est mainDlg, la fonction de dialogue principale d'une application win32, donc, du code système pour faire simple.
ce type de code est généré par le compilo C, ou le codeur ASM, mais pas le codeur C.
tout ces goto vont au même endroit, l'étiquette .finish n'est qu'une adresse dans le code.
ce sont de simples raccourcis vers la sortie.
ils sont indispensables dans un code machine, car en théorie, le cpu ne voit qu'une ligne de code à la fois, pas 30 comme nos éditeurs de texte, et donc, il lui faut bien des indications pour lui montrer la sortie de la fonction.
en C, ces jmp sont invisibles, ils sont implicites.
par exemple, pour exécuter un simple if x=0 x++, le CPU à besoin d'un:
évidement, le if n'est pas traduit ainsi dans GCC, il en faut bien plus, pour mettre en forme toutes les données, et exploiter le résultat...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 cmp [x],0 ;x est egal à 0? jne LA ;non, on saute LA inc [x] ;oui, alors on va incrémenter x, x++ LA: ;on arrive LA si x est différent de 0, ou à la fin de notre x++
mais l'idée est là, le goto est conditionnel, et implicite.
si l'on ajoute une ou deux conditions de tests, on aura tout à gagner à faire un case.
et lors de chaque tests de case, il y aura lieu de sortir en cas de résultat positif.
le goto est encore une fois implicite.
je ne connais pas encore l'instruction case du C, je débute dans deux jours seulement.
mais en gros, lorsqu'un cas est rencontré, il est inutile de continuer les tests, il faut donc sortir du case. et donc, chaque cas possède son petit bout de code, terminé par un jmp .finish, c'est à dire un goto .FIN.
et en parlant de fin, le goto est utile en prog système, car doit surement être encodé directement en jmp (enfin, j'espère). ce qui explique qu'il ne faut pas l'utiliser dans le code C, car si vous voyez le résultat de la compilation d'une fonction C, mettre un JMP dedans, c'est du suicide. les initialisations sont nombreuses, et sortir ou entrer dans passer par ces initialisations est le danger évoqué sur le GOTO
le goto ne doit donc pas sortir d'une fonction.
évidement, ça peut fonctionner car par exemple, notre code ne fait rien de complexe et donc, notre goto n'a aucune influence sur le reste.
mais si on devient un vrai programmeur, qu'on fait la maintenance du code, on va vite s'apercevoir que les goto (jump forcés), sont vraiment inutiles, et obligent à frapper 40 fois plus de code pour corriger les problèmes d'init et out-it de fonctions.
Le goto n'est pas dangereux s'il est utilisé ponctuellement et intelligemment. Utiliser un héritage de l'assembleur n'est pas un crime. Il faut cependant bien faire attention à ce qu'on fait avec un goto. De nombreux logiciels/bibliothèques bas niveau l'utilisent (noyau linux, GCC ABI c++).
Un exemple d'utilisation méritant la pendaison :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 funcA() { goto Etiq; } funcB() { Etiq: // traitements }
Un exemple d'utilité :
Maintenant, est-ce qu'un enchaînement de boucles est vraiment nécessaire ? On pourrait aussi mettre la condition d'arrêt dans toutes les boucles, ce qui peut allourdir la lisibilité du code.
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 for () { while () { for() { if (resultat_trouvé) goto End; } } } End: // cool !
Si on dit que goto réduit à néant un code structuré, qu'en est-il de break et continue ? Ce sont des sauts inconditionnels aussi... mais limités ! Alors goto n'est pas plus dangereux qu'un break ou un continue, seulement il faut savoir l'utiliser correctement pour éviter de déstructurer complètement son code.
A vrai dire, dans mon code perso, je n'utilise le break que dans une seule situation : entre deux cas d'un test à choix multiple (case d'un switch), et jamais de continue...
Il y a tout à fait moyen de s'en passer dans les autres cas, d'autant plus que le simple fait d'imbriquer trois boucles mériterait presque lui aussi la pendaison
J'ai énormément de mal à envisager une situation dans laquelle trois boucles seraient imbriquées dans laquelle le principe de la responsabilité unique serait malgré tout respecté, et j'ai déjà repris pas mal de code dans ce sens:
Si une fonction ne doit avoir qu'une seule boucle non imbriquée et qu'elle doit se contenter d'appele une autre fontion qui contiendra la boucle "réellement active", pour moi, cela mérite d'être fait.
Et si, pour sortir de cette boucle, un return s'avère utile dans le cas où une condition est remplie, on sait au moins exactement où l'on va se retrouver par la suite![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
C'est dommage parce que continue a un avantage non-négligeable dans le cas de for : celui d'honorer dans tous les cas la post-condition (généralement l'incrémentation de la variable). L'autre solution consiste à faire un if qui englobe tout ce qui aurait suivi le continue. Les deux approches se valent.
Ben, chaque fois que l'on a affaire à plusieurs dimensions :J'ai énormément de mal à envisager une situation dans laquelle trois boucles seraient imbriquées dans laquelle le principe de la responsabilité unique serait malgré tout respecté, et j'ai déjà repris pas mal de code dans ce sens:
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 int tab[10][10][10]; int longueur; int largeur; int hauteur; for (hauteur =0;hauteur <10;hauteur++) for (largeur =0;largeur <10;largeur++) for (longueur=0;longueur<10;longueur++) tab[hauteur][largeur][longueur] = 0;
'faut se méfier des grands principes énoncés en programmation. Généralement, ils permettent d'identifier un cas de figurer récurrent en informatique et de s'y pencher scientifiquement. Mais c'est aussi bien souvent une manière d'inhiber le libre arbitre du codeur. Tout ces principes ne sont pas forcément valables, et ils sont généralement trop jeunes pour qu'on en fasse des dogmes.Si une fonction ne doit avoir qu'une seule boucle non imbriquée et qu'elle doit se contenter d'appele une autre fontion qui contiendra la boucle "réellement active", pour moi, cela mérite d'être fait.
Dans le cas du principe de la responsabilité unique, bon nombre de gens soulèvent justement le problème de sa granularité ; jusqu'où faut-il pousser le vice ?
Même chose avec un break, un continue et une fin de boucle ordinaire. Reconnais que trois fonctions pour les boucles ci-dessus seraient de trop, surtout si on tient compte du fait qu'elles sont les composantes indissociables de l'espace qu'elles forment.Et si, pour sortir de cette boucle, un return s'avère utile dans le cas où une condition est remplie, on sait au moins exactement où l'on va se retrouver par la suite![]()
Sauf que, remis dans l'optique où un goto, un break ou un continue serait nécessaire, la fonction ne se contentera que rarement de mettre un élément à 0, et que, très souvent, il y aura des instructions dans les trois niveaux d'imbriquations
Je te l'accorde sans aucun problème!'faut se méfier des grands principes énoncés en programmation. Généralement, ils permettent d'identifier un cas de figurer récurrent en informatique et de s'y pencher scientifiquement. Mais c'est aussi bien souvent une manière d'inhiber le libre arbitre du codeur. Tout ces principes ne sont pas forcément valables, et ils sont généralement trop jeunes pour qu'on en fasse des dogmes.
Mais, encore une fois, mis dans le contexte ou break, goto ou continue s'avèrent nécessaires, ils ont l'avantage de te forcer à garder des fonctions "aussi simples que possibles", et tout le monde y gagne
jusqu'au point adapté à la situationDans le cas du principe de la responsabilité unique, bon nombre de gens soulèvent justement le problème de sa granularité ; jusqu'où faut-il pousser le vice ?
Cette "réponse de normand" n'apporte peut être pas beaucoup d'éclaircissement, mais elle permet de généraliser et d'exprimer la notion que j'essaye de faire passer : une fonction ne devrait avoir à s'occuper que d'une seule ressource et ne devrais pas avoir à la modifier de plus d'une manière.
Si une fonction doit gérer plus d'une ressource ou si elle doit la modifier de plus d'une manière, il est sans doute intéressant de prévoir une fonction plus "atomique" pour chaque modification à apporter et une autre pour chaque ressource à gérer, de manière à ce que la fonction qui, justement, doit effectuer l'ensemble du traitement n'aie "qu'à appeler" les trois ou "quatre fonctions plus basiques", qu'il sera sans doute utile de pouvoir appler séparément dans certaines situations
Bien que la fonction ne présente ni break, ni goto, ni continue, je reconnais que ce serait un peu exagéré pour cette fonction particulière, non pas parce que les boucles font partie d'un espace indissociable, mais bien parce que la fonction elle même reste suffisamment simple pour ne pas (forcément) justifier le fait de la scinder en trois...Même chose avec un break, un continue et une fin de boucle ordinaire. Reconnais que trois fonctions pour les boucles ci-dessus seraient de trop, surtout si on tient compte du fait qu'elles sont les composantes indissociables de l'espace qu'elles forment.
Et encore!!! Pour moi, tout code devant être écrit plus d'une fois justifie le fait de créer une fonction particulière, et donc, si pour une raison ou une autre tu en venais, à un moment donné, à n'écrire ne serait ce qu'un code proche de
il serait peut etre intéressant d'envisager la création d'une fonction setLineToZero(int A, int B)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 for(int i=0;i< MAXI;++i) truc[A][B][i]=0;![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Bizarre je n’ai jamais utilisé de goto...
Pourtant je code souvent...
Alors on pourrait s'en passer ??
A par dans de très très très rare cas...
Non, je revoie ma façon de codéeEnvoyé par ulukahio
![]()
"Coder" .. ça ne veut rien dire ... tout dépend si tu fais du temps-réel critique (genre switch en bas de la ms avec un OS très performant) ou si tu fais des applications plus standardEnvoyé par Ti-R
![]()
Dans la mesure du possible, oui, mais c'est un peu comme l'école qui refuse les "continue" dans les forAlors on pourrait s'en passer ??
A par dans de très très très rare cas...![]()
sauf que pour mon programme ce switch marche mais est tres lourd à programmer... Pourquoi? Parcequ'il il faudrait que je l'écrive cent fois:Envoyé par gege2061
En effet, la valeur de ligne [i] ne correspond pas au champ dans lequel se placer, mais au nombre de champs à sauter. Donc le case 3 peut m'emmener dans le champ 3 comme dans le champ 10, et il faudrait que je mette ce switch à chaque fois que je teste la valeur de ligne[i] avec un corps différent. Et du coup je vois pas ce que je gagne en lisibilité.
Une autre piste pour ton problème, à condition que tes ligne[i] renvoit toujours des entiers:
Bien sûr, tu modifies le type de retour "void" de la fonction en ce que tu aurais besoin de récupérer éventuellement...
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 main(...) { traitement_champs(ligne[i]); //.... } void traitement_champs(int nombre) { switch(nombre) { case 1: // traitement champs 1 case 2: // traitement champs 2 case 3: // traitement champs 3 default: // traitement divers... } }
Enfin, c'est dur de proposer une solution sans avoir tous les tenants et les aboutissants du problème...
C'est juste une piste...
je ne demande que ça... Je ne suis absolument pas un programmeur né et je ne demande qu'à faire des progrès.Envoyé par gege2061
Je suis d'accord que chez Micro$oft ils ne sont pas complètement nuls, mais quand même, ils pourraient faire quelques efforts :Envoyé par mat.M
Tiré de MSDN
Le goto est-il vraiment utile ici ??
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
29
30
31
32
33
34
35
36
37
38
39 BOOL ProcessCmdLine(LPSTR lpCmdLine, LPDWORD pdwRegisterCF, LPDWORD pdwRegisterActiveObject, int nCmdShow) { LPCLASSFACTORY pcf = NULL; HRESULT hr; *pdwRegisterCF = 0; *pdwRegisterActiveObject = 0; // Expose class factory for application object if command line // contains the /Automation switch. if (_fstrstr(lpCmdLine, "-Automation") != NULL || _fstrstr(lpCmdLine, "/Automation") != NULL) { pcf = new CApplicationCF; if (!pcf) goto error; pcf->AddRef(); hr = CoRegisterClassObject(CLSID_Lines, pcf, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, pdwRegisterCF); if (hr != NOERROR) goto error; pcf->Release(); } else // Show window if started as stand-alone. g_pApplication->ShowWindow(nCmdShow ); // Register Lines Application object in the running object table // (ROT). Use weak registration so that the ROT releases its reference // when all external references are released. RegisterActiveObject(g_pApplication, CLSID_Lines, ACTIVEOBJECT_WEAK, pdwRegisterActiveObject); return TRUE; error: if (pcf) pcf->Release(); return FALSE; }
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Peux-tu poster ton code de traitement de champs qu'on comprenne un peu plus ce que tu veux dire ?Envoyé par ulukahio
En quoi cette utilisaation est elle risquée? (par contre trap D, si on pouvait éviter de faire dévier le topic sur l'incapacité à programmer des gens de grosoft ça m'arrangeraitEnvoyé par calogerogigante
)
Effectivement dans ce cas, il est possible de faire une fonction mais je trouve que le programme est clair quant même. Je n'est pas mis plus de temps à comprendre le programme que s'il y avait eu une fonction. Contrairement au code de ulukahio.Envoyé par Trap D
Envoyé par DavG
un exemple: le fichier original contient une centaine de champs présentés comme suit:
mais si le premier champ n'est pas présent, on a:Michel; Barnier; 21rue machin; c'est la fête
si le premier et le deuxième ne sont pas présents, on a:1; Barnier; 21rue machin; c'est la fête
Si le premier, le deuxieme et le troisieme ne sont pas présents:2; 21rue machin; c'est la fête
Si le deuxieme n'est pas présent:3; c'est la fête
Si le deuxieme et le troisieme ne sont pas présents:Michel; 1; 21rue machin; c'est la fête
Et ainsi de suite...Michel; 2; c'est la fête
Au plus tu rajoutes de "petits jump" à saute mouton au-dessus de petits bouts de code, au plus tu risques de louper une étape logique du déroulement de ton code... Surtout si tu dis toi-même qu'il risque d'y avoir une centaine de traitements de champs...
Je ne suis pas foncièrement contre, mais je trouve cela dangereux car tu risques de louper plus facilement une incohérence dans ton code...
A moins d'être sûr de ce que tu fais à 100 % (exemple: t'as écrit un petit ordinogramme clair qui représente toutes les possibilités de cette partie de ton programme utilisant les gotos...), alors OK...
Mais à mon avis: ordonner les choses clairement avec un switch, dans ton cas, serait beaucoup plus propre et plus lisible... Notamment en cours de déboguage...
il faut se rappeler que les instructions "return", "break", "continue"
sont des "goto" déguisés et maîtrisés
par contre il n'existe aucune instruction pour sortir élégamment de
2 boucles imbriquées. à part "goto".
Partager