[Gestion d'erreur] comment remplacer un goto ?

comment remplacer un goto ? [Gestion d'erreur] - C - Programmation

Marsh Posté le 02-06-2011 à 14:31:13    

Bonjour,
 
Je me balade assez souvent sur le site pour trouver des solutions à mes divers problèmes de programmation (surtout en C++ en fait) Mais j'avoue que là, bien que j'ai trouvé 2 ou 3 pistes, je n'arrive pas à faire ce que je voudrais et devrais faire... :cry: j'ai une super gestion d'erreur, sauf que celle-ci passe par un "goto", ce qui, dans ma section, nous est interdit du à la rupture de séquence... du coup j'ai essayé de remplacer cette gestion d'erreur par une fonction, mais, je sais pas pourquoi, j'arrive pas à trouver comment faire, ça change ma logique, ou ça appelle des fonctions qui ne me viennent pas à l'esprit... j'en sais rien. Si vous avez des idées elles sont les bienvenues...
Voici mon extrait de code le plus simple (j'ai une bonne vingtaine de sources dans le même genre si ça vous intéresse :P, il faut que je les corriges tous...).
 

Code :
  1. #include <stdio.h>
  2. #include <NIDAQmx.h>
  3. #define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else
  4. int main(void)
  5. {
  6. int32       error=0;
  7. TaskHandle  taskHandle=0;
  8. int32       read;
  9. float64     data[10];
  10. char        errBuff[2048]={'\0'};
  11. int   i=0;
  12. /*********************************************/
  13. // DAQmx Configure Code
  14. /*********************************************/
  15. DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
  16. DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev3/ai1","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
  17. DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",10,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,10));
  18. /*********************************************/
  19. // DAQmx Start Code
  20. /*********************************************/
  21. DAQmxErrChk (DAQmxStartTask(taskHandle));
  22. /*********************************************/
  23. // DAQmx Read Code
  24. /*********************************************/
  25. DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,10,10.0,DAQmx_Val_GroupByChannel,data,10,&read,NULL));
  26. printf("Acquired %d points\n",read);
  27. for(i=0;i<10;i++)
  28. {
  29.  printf("TEST %f points\n", data[i]);
  30. };
  31. Error:
  32. if( DAQmxFailed(error) )
  33.  DAQmxGetExtendedErrorInfo(errBuff,2048);
  34. if( taskHandle!=0 )  {
  35.  /*********************************************/
  36.  // DAQmx Stop Code
  37.  /*********************************************/
  38.  DAQmxStopTask(taskHandle);
  39.  DAQmxClearTask(taskHandle);
  40. }
  41. if( DAQmxFailed(error) )
  42.  printf("DAQmx Error: %s\n",errBuff);
  43. printf("End of program, press Enter key to quit\n" );
  44. getchar();
  45. return 0;
  46. }


Donc vous l'aurez compris, à chaque ligne je test ce que me renvoie la fonction, et je trouverai idiot de recopier entièrement tout mon code de gestion d'erreur à chaque ligne...
Merci d'avance !


Message édité par gilou le 02-06-2011 à 18:47:08
Reply

Marsh Posté le 02-06-2011 à 14:31:13   

Reply

Marsh Posté le 02-06-2011 à 17:51:14    

Ben faudra faire un paquet de refactoring, et je doute que tu puisses automatiser ça. Je ferais un truc du genre :

Code :
  1. #include <stdio.h>
  2. #include <NIDAQmx.h>
  3.  
  4. #define DAQmxErrChk(functionCall) DAQmxFailed(error=(functionCall))
  5.  
  6. int main(void)
  7. {
  8.    int32      error=0;
  9.    TaskHandle taskHandle=0;
  10.    int32      read;
  11.    float64    data[10];
  12.    char       errBuff[2048]={'\0'};
  13.    int        i = 0;
  14.  
  15.    /*********************************************/
  16.    // DAQmx Configure Code
  17.    /*********************************************/
  18.    if (! DAQmxErrChk(DAQmxCreateTask("",&taskHandle)) &&
  19.        ! DAQmxErrChk(DAQmxCreateAIVoltageChan(taskHandle,"Dev3/ai1","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL)) &&
  20.        ! DAQmxErrChk(DAQmxCfgSampClkTiming(taskHandle,"",10,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,10)))
  21.    {
  22.  
  23.        /*********************************************/
  24.        // DAQmx Start Code
  25.        // DAQmx Read Code
  26.        /*********************************************/
  27.        if (! DAQmxErrChk(DAQmxStartTask(taskHandle)) &&
  28.            ! DAQmxErrChk(DAQmxReadAnalogF64(taskHandle,10,10.0,DAQmx_Val_GroupByChannel,data,10,&read,NULL)))
  29.     {
  30.            printf("Acquired %d points\n",read);
  31.  
  32.            for (i=0;i<10;i++)
  33.                printf("TEST %f points\n", data[i]);
  34.        }
  35.    }
  36.  
  37.    if (DAQmxFailed(error))
  38.        DAQmxGetExtendedErrorInfo(errBuff,2048);
  39.    if (taskHandle)  {
  40.        /*********************************************/
  41.        // DAQmx Stop Code
  42.        /*********************************************/
  43.        DAQmxStopTask(taskHandle);
  44.        DAQmxClearTask(taskHandle);
  45.    }
  46.    if (DAQmxFailed(error))
  47.        printf("DAQmx Error: %s\n",errBuff);
  48.  
  49.    printf("End of program, press Enter key to quit\n" );
  50.    getchar();
  51.    return 0;
  52. }


 
Le truc, c'est de regrouper les initialisations/allocations qui nécessite un nettoyage explicite dans une instruction if. Si ça foire, tu nettoies dans le bloc contenant, puis en cascade ensuite. De cette manière, à la fin du traitement normal, ça va nettoyer tout comme il faut.
 
Ou alors faire comme tu as fais: si ça foire à un endroit, tu te redirige le code au plus vite dans une partie qui va tout nettoyer.
 
 
 

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed