Que fait mon programme ?

Que fait mon programme ? - C - Programmation

Marsh Posté le 13-05-2007 à 16:27:41    

Bonjour,
 
Je dois récupérer des données à partir d'un fichier binaire. Les données dans le fichier binaire sont stockées ainsi:
 
Il y a d'abord 1707 caractères ASCII (donc 1 byte chaque caractère) qui correspondent au header.
Ensuite un long unsigned byte (4 bytes) suivi de 1000 short integers (2 bytes) et ce répété un certain nombre de fois.
 
On m'a envoyé un programme en C qui récupère les données, mais j'ai beau le compiler je n'arrive pass à le faire marcher (arguments à mettre avant compilation ou après ?)
 
Quelqu'un aurait-il la gentillesse de décrypter ce code pour moi (en fait uniquement la dernière fonction en bas de la page : int main(int argc, char**argv))
 
Merci bcp
 
/***
 *** READ_TTFILE
 ***/
 
/*
  reads a tt file. The core routine is the read_ttfile function.
  it requires as arguments  
  1. the address of a pointer to a vector of long unsigned integer that  
  will contain the timestamps of the spikes (expressed in 1e-4 seconds)
  2. the address of a pointer to a table of 4 pointers to short integers.
  each of these pointers will correspond to the concatenated spike waveforms  
  for one channel.
  3. the address of the integer for the spike count.
  4. the name of the ttfile
  5. the size of the spike traces (for one channel)
  -that's lazy, the info is in the header-
 
  the main routine just takes the arguments, reads them in and gives an example of  
  how to read the data;
 
 */
 
 
 
 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
 
#define MAXLINE 255
 
#define BLOCK_ALLOC 16384
 
/*magic strings*/
#define MAGIC_SOH_STR "%%BEGINHEADER"
#define MAGIC_EOH_STR "%%ENDHEADER"
#define MAGIC_SOH_STRSIZE 13
#define MAGIC_EOH_STRSIZE 11
 
 
 
 
 
/* unit */
 
void read_ttfile(long unsigned **res_time, short *(* res_traces)[4], int *res_ntrace,  
   char *filename, int slen)  
{
  FILE *f;
  char line[MAXLINE];
  int slen4=slen*4;
  short *buffer;
  int ntrace,i;
  long unsigned *time;
  short *traces[4];
 
  //opens the file
  if ((f=fopen(filename, "r" ))==NULL)  
    {
      fprintf(stderr,"opening of %s failed: %s \n",filename,strerror(errno));
      exit(EXIT_FAILURE);
    }
 
 
  //checks there is a header and skip it
  if(strncmp(fgets(line,MAXLINE,f),MAGIC_SOH_STR,MAGIC_SOH_STRSIZE) != 0)
   {
      fprintf(stderr,"could not find header in file %s\n!",filename);
      exit(EXIT_FAILURE);
    }
 
 
  while( strncmp(fgets(line,MAXLINE,f),MAGIC_EOH_STR,MAGIC_EOH_STRSIZE) != 0)
    {;}
   
   
  //read and allocate the memory as needed
  //alternatively we could read the size of the file.
   
  /*initialize*/
  time=NULL;
  traces[0]=NULL;
  traces[1]=NULL;
  traces[2]=NULL;
  traces[3]=NULL;
 
  ntrace=0;
   
  buffer=calloc(slen4,sizeof(short));
 
  /*run through the file*/
  while(!feof(f))
    {
      /* allocate chunks of BLOCK_ALLOC spikes as needed*/
      if(ntrace%BLOCK_ALLOC==0)
 {
   time=realloc(time, (ntrace+BLOCK_ALLOC)*sizeof(long unsigned));
   if(time==NULL)
     {
       fprintf(stderr,"out of memory\n" );
       exit(EXIT_FAILURE);
     }
   for (i=0;i<4;i++)
     {
       traces[i]=realloc( traces[i], (ntrace+BLOCK_ALLOC)*sizeof(short)*slen4);
       if(traces[i]==NULL)
  {
    fprintf(stderr,"out of memory\n" );
    exit(EXIT_FAILURE);}
     }
 }
       
      /*read the data*/
      if(fread(time

Code :
  1. [cpp][cpp]

[/cpp][/cpp]+ ntrace ,sizeof(long unsigned),1,f)!=1)
 break; //should not happen because of eof;
      if(fread(buffer,sizeof(short),slen4,f)!=slen4)
 {
   fprintf(stderr,"could not read the %dth trace!\n",ntrace+1);
   break;
 }
       
      /*reoder the interlaced buffer in 4 different channels*/
      for (i=0;i<slen4;i++)
 traces[i%4][ntrace *slen+i/4]=buffer[i];
       
      ntrace++;
    }
   
  /*realloc to the final size*/
  time=realloc(time, ntrace * sizeof(long unsigned));
  for (i=0;i<4;i++)
    traces[i]=realloc(traces[i], ntrace*sizeof(short)*slen4) ;
 
  /*output data*/
  for (i=0;i<4;i++)
    (*res_traces)[i]=traces[i];
  *res_ntrace=ntrace;
  *res_time=time;
 
  return;
}
 
 
int main(int argc, char**argv)
{
  int slen=0;
  char *filename=NULL;
  int i,ntrace;
  long unsigned *time;
  short *trace[4];
 
  /*reads the arguments*/
 for (i=1;i<argc;i++)
    {
      if (strcmp(argv[i],"-slen" ) == 0)  
 {
   if (i==(argc-1))
     {
       fprintf(stderr, "-slen: value not specified!\n" );
       exit(EXIT_FAILURE);
     }
   else
     slen=atoi(argv[++i]);
 }
      else
 filename=argv[i];
    }
 
 /*checks everything is there*/
  if(slen<=0 || filename==NULL)
    {
      fprintf(stderr, "usage %s ttfile -slen n_points_per_spikes\n",argv[0]);
      exit(EXIT_FAILURE);
    }
   
  /*fill the tables and count all the traces*/
  read_ttfile(&time, &trace, &ntrace, filename, slen);
 
  /*example. The peak is a the first third of total spike trace*/
  fprintf(stdout,"the spike #%d occured at %gsec\n"
   "It has at its peak an amplitude:\n"
   "\tchan 0:%d\n \tchan 1:%d\n \tchan 2:%d\n \tchan 3:%d\n",7,time[7]*1e-4,  
   trace[0][7*slen+slen/3], trace[1][7*slen+slen/3],
   trace[2][7*slen+slen/3], trace[3][7*slen+slen/3]);
   
  {
    int max=0;
    for (i=0;i<ntrace;i++)
      if(trace[0][i*slen+slen/3]>max) max=trace[0][i*slen+slen/3];
    fprintf(stdout,"The largest spike on chan0 has an amplitude of %d\n",max);
  }
 
  return EXIT_SUCCESS;    
}
 
 
 :jap:

Message cité 1 fois
Message édité par thinkerr le 13-05-2007 à 21:13:11
Reply

Marsh Posté le 13-05-2007 à 16:27:41   

Reply

Marsh Posté le 14-05-2007 à 07:41:58    

Il attend un paramêtre -slen N avec N entier.

Reply

Marsh Posté le 14-05-2007 à 15:51:57    

matafan a écrit :

Il attend un paramêtre -slen N avec N entier.


En plus, si "slen" n'a pas été rempli, il vaut 0. Et s'il vaut 0, cette ligne

Code :
  1. fprintf(stderr, "usage %s ttfile -slen n_points_per_spikes\n",argv[0]);

est exécutée et le programme affiche lui-même la bonne façon de le lancer !!!
 

thinkerr a écrit :


Code :
  1. void read_ttfile(long unsigned **res_time, short *(* res_traces)[4], int *res_ntrace, 
  2.   char *filename, int slen)
  3. {
  4.   <...>
  5.   //opens the file
  6.   if ((f=fopen(filename, "r" ))==NULL)
  7.     {
  8.       fprintf(stderr,"opening of %s failed: %s \n",filename,strerror(errno));
  9.       exit(EXIT_FAILURE);
  10.     }
  11.   //checks there is a header and skip it
  12.   if(strncmp(fgets(line,MAXLINE,f),MAGIC_SOH_STR,MAGIC_SOH_STRSIZE) != 0)
  13.    {
  14.       fprintf(stderr,"could not find header in file %s\n!",filename);
  15.       exit(EXIT_FAILURE);
  16.     }
  17.     <...>
  18. }



Je trouve ce code assez pourri. Déjà sortir du programme par "exit" à l'intérieur d'une fonction c'est limite mais quitter le programme après avoir ouvert un fichier sans le refermer c'est vraiment ignoble.
Surtout qu'après une 2° lecture, je remarque que même si la fonction se déroule jusqu'au bout, elle ne ferme quand-même pas le fichier. Et une 3° lecture me fait réaliser que les mémoires allouées par les calloc/realloc ne sont jamais libérées, ni dans la fonction qui les alloue, ni dans le main qui récupère ces adresses.
Bon, je ne tente pas de 4° lecture...


Message édité par Sve@r le 14-05-2007 à 16:07:09

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 14-05-2007 à 17:14:22    

c normal c un programme MAGIC tout se ferme tout seul [:dawak]

Reply

Marsh Posté le 15-05-2007 à 07:26:26    

De toute façon l'OS ferme tout, pas la peine de se faire chier à tout fermer/libérer proprement pour les sorties en cas d'erreur. Ca ne me choque pas du tout.

Reply

Marsh Posté le 15-05-2007 à 13:16:26    

il vaux mieux prendre le coup de fermer/détruire tout ce qui a été ouvert/créé.
 
ndlr, sinon bonjour les blagues avec les ipcs :D (enfin sous les nux)

Reply

Marsh Posté le 15-05-2007 à 13:26:33    

Ouais, comme ça dans ton code t'as 10000 lignes inutiles qui ne seront quasiment jamais exécutées, qui sont autant de chances d'erreur, et qui gênent la lecture du code utile. En plus comme il est pratiquement impossible de systématiquement tout nettoyer sur toutes les sorties en erreur, ces 10000 lignes n'auront permis de sortir "proprement" que dans 50% des cas. Moi au moins je suis consistent  :-)
 
Après évidemment, les ressources genre sémaphores et mémoire partagée, c'est une autre histoire.

Reply

Marsh Posté le 15-05-2007 à 23:45:18    

matafan a écrit :

Ouais, comme ça dans ton code t'as 10000 lignes inutiles qui ne seront quasiment jamais exécutées, qui sont autant de chances d'erreur, et qui gênent la lecture du code utile. En plus comme il est pratiquement impossible de systématiquement tout nettoyer sur toutes les sorties en erreur, ces 10000 lignes n'auront permis de sortir "proprement" que dans 50% des cas.


Allez, avoue, t'as écrit ceci exprès pour nous faire rire  :pt1cable:  

matafan a écrit :

Moi au moins je suis consistant  :-)


Pour le moins...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 16-05-2007 à 08:38:19    

Ben non vois tu, consistant en français n'a pas le même sens que consistent en anglais. Donc c'est un anglicisme, pas une faute d'orthographe :P

Reply

Marsh Posté le 16-05-2007 à 09:26:05    

matafan a écrit :

Ben non vois tu, consistant en français n'a pas le même sens que consistent en anglais. Donc c'est un anglicisme, pas une faute d'orthographe :P


Tu aurais pu dire "cohérent"...   :na:  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 16-05-2007 à 09:26:05   

Reply

Marsh Posté le 16-05-2007 à 23:14:39    

matafan a écrit :

Ouais, comme ça dans ton code t'as 10000 lignes inutiles qui ne seront quasiment jamais exécutées, qui sont autant de chances d'erreur, et qui gênent la lecture du code utile. En plus comme il est pratiquement impossible de systématiquement tout nettoyer sur toutes les sorties en erreur, ces 10000 lignes n'auront permis de sortir "proprement" que dans 50% des cas. Moi au moins je suis consistent  :-)
 
Après évidemment, les ressources genre sémaphores et mémoire partagée, c'est une autre histoire.


 
nan, si tu séquences bien la gestion des erreurs et des créations/destructions.
tu peux parfaitement faire une routine qui retourne un code d'erreur tout en nettoyant proprement avant le retour.
 
mais bon forcément, quand on mets des exit() dans une sous-fonction c'est plus dur   [:spamafote]

Message cité 1 fois
Message édité par bjone le 16-05-2007 à 23:15:16
Reply

Marsh Posté le 17-05-2007 à 10:03:04    

bjone a écrit :

mais bon forcément, quand on mets des exit() dans une sous-fonction c'est plus dur   [:spamafote]


[:rofl]


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

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