Tom's Guide > Forum > Programmation > Utiliser GOTO en C

Utiliser GOTO en C

Forum Programmation : Utiliser GOTO en C

TomsGuide.com : 800 000 inscrits répondent à toutes vos questions high-tech et informatique. Pour obtenir de l'aide, inscrivez-vous gratuitement !
Mot :    Pseudo :           
 

Bonjour

Alors oui je sais, son utilisation est tres deconseillee mais c'est ce qui est le plus propre dans le cas auquel je suis soumis et j'aimerais bien comprendre comment l'utiliser.

Alors j'ai une partie de mon code:

Code :
  1. void importationsequence (void)
  2. {
  3.     int option, Nb_seq, x;
  4.     char sequence;
  5.     printf("Comment voulez vous entrer vos sequence?\n1- manuellement\n2 -en important depuis un fichier .txt\n\nTapez votre reponse:" );
  6. scanf("%d", &option);
  7. if(option == 1){
  8.     printf("Veuillez taper  le nombre de sequences:\nNb_seq =\n" );
  9. scanf("%d", &Nb_seq);
  10. char text[]="seq.txt";
  11. FILE *fp1;
  12. fp1 =fopen(text, "w" );x=1;
  13. do {
  14.     printf("Veuillez taper la sequence:\n" );
  15. scanf ("%s", &sequence);
  16.     fprintf(fp1, ">seq_%d\n", x);
  17.     fprintf(fp1, "%s\n", &sequence);
  18.     x++;
  19. }
  20. while (x<=Nb_seq);
  21.         fclose(fp1); }
  22. else if (option==2) {}
  23. else { goto erreur;} ;
  24. }
  25. erreur : printf("Vous avez entre un mauvais choix." );



Donc j'ai juste un souci avant le lancement:
error: expected identifier before '}' token =>else { goto erreur;} ;
error: expected unqualified-id before ':' token =>else { goto erreur} ; =>erreur : printf("Vous avez entre un mauvais choix." );


Ai je mal itilise mon goto ?

Merci

------------------------------ Les Tuto IDN - Choisir sa RAM - Choisir sa Carte Graphique
Liens sponsorisés
Inscrivez-vous ou connectez-vous pour masquer ceci.

Normalement, tu ouvres { et tu fermes }

Ton label "erreur" est dans une partie du programme qu'il ne comprend pas!

Sinon, pourquoi ne pas simplement créer un p'tit truc du genre:

Code :
  1. else if (option==2) {}
  2. else {
  3. printf("Vous avez entre un mauvais choix." );
  4. } ;

------------------------------ En Restaurant, le coeur de breizh
Répondre à Tybbow

Tybbow a écrit :

Normalement, tu ouvres { et tu fermes }

 

Ton label "erreur" est dans une partie du programme qu'il ne comprend pas!

 

Sinon, pourquoi ne pas simplement créer un p'tit truc du genre:

 
Code :
  1. else if (option==2) {}
  2. else {
  3. printf("Vous avez entre un mauvais choix." );
  4. } ;


 

Parce que je veux reutiliser le meme message plusieurs fois donc "goto erreur" c'est plus propre qu'une enieme boucle.

 

Dans mon programme j'ai une partie avec 16 boucles imbriquees, si j'arrive a comprendre comment utiliser goto je pourrais condenser.
Ce programme marchait avec un if/else if mais je cherche a le rendre plus compact et lisible.

 


Et que je mette ou non des {} autour de:
- goto erreur;
- erreur : printf( .....);
Ca me donne le meme message.

 

Comment doit on declarer un GOTO ?


Message édité par Dafen@IDN le 03-04-2009 à 17:22:24
------------------------------ Les Tuto IDN - Choisir sa RAM - Choisir sa Carte Graphique
Répondre à Dafen@IDN

N'utilise pas goto. Non, sérieusement. N'utilise pas goto, à moins de faire de la programmation système (c'est le seul endroit où je l'ai vu bien utilisé), et encore. C'est se faire chier pour rien (la preuve); une mauvaise habitude (pour un goto propre, j'en ai vu des dizaines sales), et ça n'est pas plus lisible qu'une énième boucle (après tout, ton goto pourrait partir un peu n'importe où dans le code, sans la ). On peut toujours faire sans. Réfléchis à la logique de ce que tu veux faire (quitter? suffit de faire un return; afficher un message? ça peut se faire dans la boucle, etc.) et réorganise ton code en conséquence.

 


Le problème ici, c'est que ton étiquette erreur: se trouve en dehors du "scope" de la fonction (délimité par les void importationsequence (void){} ).
Donc, elle est inaccessible.

 

EDIT: tu as des exemples ici:
http://aelinik.free.fr/c/ch14.htm


Message édité par Rakipu le 03-04-2009 à 21:37:40
Répondre à Rakipu

Ta syntaxe est presque correct: ton label "erreur:" doit se trouver à l'intérieur de la fonction. Toi, tu l'as mis à l'extérieur. Le compilateur cherche alors une définition de variable ou de fonction, alors le :, il ne connait pas.

 

Mais programmer en C comme en VB, c'est caca. :)
Un goto n'est pas propre. Seulement en assembleur, c'est propre (et en Basic parce que les If ne sont pas beaux). :)

 

Un truc propre (et pro) en C, c'est de retourner l'erreur en sortie de fonction:

Code :
  1. int importationsequence (void);
 

Après, si tu ne veux pas montrer le int pour ne pas confondre avec un entier, tu peux faire:

Code :
  1. typedef int tResult;
  2. tResult importationsequence (void);
 

La deuxième étape est de définir les erreurs constantes. Par exemple:

Code :
  1. enum {
  2.   OK = 0x00,
  3.   WARNING_ARE_YOU_SURE = 0x40,
  4.   WARNING_DELETE,
  5.   WARNING_NEW,
  6.   WARNING_BIG,
  7.   ERROR_INVALID_CHOICE = 0x80,
  8.   ERROR_FILE_NOT_FOUND,
  9.   ERROR_INVALID_SEQUENCE
  10. };
 

Dans le code, si tu veux retourner une erreur, tu fais un

Code :
  1. return ERROR_INVALID_CHOICE;
 

Evidemment, on ne traite pas l'erreur dans la fonction de traitement, parce que si tu veux mettre à jour une ou plusieurs erreur, tu es sûr de passer à côté de quelque chose. On peut par exemple implémenter comme ceci:

Code :
  1. #define MESSAGE_SIZE 256
  2. tResult result;
  3. char message[MESSAGE_SIZE];
  4. //...
  5. result = importationsequence();
  6. if( result >= 0x80 )
  7. {
  8.   printf("%s\n", GetResultMessage(result, message, MESSAGE_SIZE));
  9.   // par exemple on arrête le programme
  10.   return;
  11. }
  12. else if( result >= 0x40 )
  13. {
  14.   printf("%s\n", GetResultMessage(result));
  15.   // on affiche le message, mais on continue
  16. }


avec le GetResultMessage qui va bien:

Code :
  1. // For french users ;)
  2. #define MSG_ERROR_HEAD "Erreur : "
  3. #define MSG_WARNING_HEAD "Avertissement :
  4. #define MSG_OK_HEAD "Avertissement :
  5. #define MSG_ERROR_INVALID_CHOICE "Vous avez entre un mauvais choix."
  6. char * GetResultMessage(tResult result, char * message, int size)
  7. {
  8.   char * remainingBuffer = message;
  9.   int remainingSize = size;
  10.   int headerSize = 0;
  11.   if (size < 1)
  12.       return message;
  13.   message[0] = '\0';
  14.   if(result >= 0x80)
  15.   {
  16.       // Set header
  17.       headerSize = strlen(ERROR_HEAD) + 1;
  18.      
  19.       if (headerSize > size)
  20.         return message;
  21.    
  22.       strcpy(message, ERROR_HEAD);
  23.       // Set message
  24.       remainingBuffer = message + headerSize - 1;
  25.       remainingSize = size - headerSize + 1;
  26.       switch(result)
  27.       {
  28.           case ERROR_INVALID_CHOICE:
  29.             msgSize = strlen(MSG_ERROR_INVALID_CHOICE) + 1;
  30.      
  31.             if (msgSize > remainingSize)
  32.                 return message;
  33.    
  34.             strcpy(message, MSG_ERROR_INVALID_CHOICE);
  35.           break;
  36.           // etc
  37.           default:
  38.             // Afficher message inconnu
  39.       }
  40.   }
  41.   // etc
  42.   return message;
  43. }


En C++, c'est plus facile, on utilise string (ou similaire) et on ne s'embête plus sur les tailles (géré par l'objet). :)

 

Bon, j'ai mis les warning, mais on peu simplifier par 1 OK et une suite d'erreurs.
Ensuite, on peut compléter tout ça en utilisant une structure au lieu d'un int, ça prend plus de place sur la pile, mais maintenant l'espace n'est plus un problème. :)

Code :
  1. typedef struct
  2. {
  3.   int errorCode; // on garde le système de codes d'erreur
  4.   int additionalDataSize;
  5.   char additionnalData[256];
  6. } tResult;


Par exemple, si lors d'un mauvais choix on veut indiquer ce qu'était le mauvais choix, on peut le stocker dans les donnée additionnelles.

Code :
  1. additionalDataSize = 4;
  2. *((int *)additionnalData) = option;


Du coup, il faut en tenir compte dans le GetResultMessage().
Là encore, en C++ c'est plus simple, car il suffit de définir une classe qui continent les méthodes getResultMessage(), le code d'erreur et autres données). En C++, on a aussi la possibilité de traiter les erreurs par exceptions (c'est un choix à faire).

 

Bon, évidemment, je pousse au maximum la gestion des erreurs. Il est peut-être plus simple de retourner un int (en utilisant quand même des define ou enum pour être propre) et de traiter au cas par cas.

 

Ceci dit, je complique tout parce que:
1. ça limite l'apparition de bugs dans le traitement d'erreur
2. une fois la structure mise en place, ajouter une erreur est un jeu d'enfant
3. faciliter l'ajout d'erreur pousse à traiter un maximum de cas d'erreur afin de présenter un logiciel ergonomique à l'utilisation. Un logiciel dont les erreurs sont mal gérées se voient rapidement (comportements bizarres + crashes fréquents)
4. ça aide pour l'internationalisation, car les messages centralisés sont facilement manipulables.
5. ça aide à la correction du traitement de l'erreur (et pas seulement changer le texte)
6. un bon traitement d'erreur permet de bien debugger le programme car ça permet de faire remonter les origines d'un bug.

 

Sinon, que ce soit pour une gestion d'erreur ou pas, si je regarde un programme professionnel dont le source contient des goto, j'arrête de le lire et je jette le code source (et le programme qui va avec :) ).

 


Message édité par CRicky le 03-04-2009 à 21:57:17
------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

Merci.

 

Finalement j'ai reussi a le faire marcher.
C'est impeccable.

 

Edit: j'avais pas vu le pave de CRicky.
Merci, vais lire ca en detail et voir ce que je suis capable d'appliquer :jap:


Message édité par Dafen@IDN le 03-04-2009 à 21:59:39
------------------------------ Les Tuto IDN - Choisir sa RAM - Choisir sa Carte Graphique
Répondre à Dafen@IDN
Tom's Guide > Forum > Programmation > Utiliser GOTO en C
Aller à :

Il y a 1257 utilisateurs connus et inconnus. Pour voir la liste des connectés connus, cliquez ici.

Attention

Vous allez répondre sur un sujet resté inactif pendant plus de 6 mois.
Assurez-vous d'apporter des éléments nouveaux à la discussion avant de poursuivre.

Répondre Annuler
Liens