IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

pb avec les strings et les caractères \0 et \n


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut pb avec les strings et les caractères \0 et \n
    Bonjour, je me mêle les pinceaux entre les caractères \0 et \n.

    Voilà mon pb : je lis une ligne dans un fichier txt à l'aide de fgets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char line[10000];
    fgets(line,sizeof line,file);
    La ligne en question est par exemple

    ou bien, dans le cas où l'utilisateur mais un commentaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TEMP 350 400 450  ! commentaires de l'utilisateur
    Ce que je désire faire est tout simple :
    1) supprimer le caractère fin de ligne \n (car mon fichier txt contient plusieurs lignes) --> cf la fonction DeleteCharEndOfLigne
    2) supprimer le commentaire --> cf la fonction DeleteComment
    3) rentrer les 3 valeurs dans un tableau --> je sais faire cette étape

    J'ai un pb pour les étapes 1 et 2. Voici mes deux fonctions annexes :

    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
     
    void DeleteCharEndOfLine(char * line_,unsigned short nl,unsigned short nl_)
    {
      /*
        Delete char '\n' if this one was founded in the string line_,
        send an error message otherwise
        nl is the number of line of the input file
        nl_ is the number of the line which contains the string line_
      */
     
      char * p = strchr(line_,'\n'); /* char '\n' is sought */
      if (p != NULL) /* if it was founded it is cleared */
        *p =0;
      else if(nl_!=nl) /* the last line of input file can not to have char '\n' */
      {
        /* tabular is too short. Exit program */
        fprintf(stderr,"Error in file %s line %d in function %s : tabular line_ is too short\nIncrease its size\nExit program\n",__FILE__,__LINE__,__FUNCTION__);
        exit(1);
      }
    }
    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
     
    void DeleteComment(char * line_)
    {
      /* This function deletes the char '!' and all the char after it of
         the string line_.
         This function deletes also all the spaces befor the char '!' and
         the last char of line_ which isn't a space
      */
      char * p=strchr(line_,'!');
      if(p!=NULL)
      {
        /* d is the index of string line_ which contains the char '!' 
           Remark : the first index is 0
        */
        int d=p-line_,i; 
        for(i=d-1;line_[i]==' ';--d,--i);
        char dest[d];
        char * s3=strncpy(dest,line_,d);
     
         /* we add char '\0' at the end of s3 so at the end of line_ */
        s3[d]='\0';    
        char * aux=strcpy(line_,s3);
        assert(aux!=NULL);
      }
      /* we add char '\0' at the end of line_. The last index is
         strlen(line_)-1
      */
      //else line_[strlen(line_)-1]='\0';
    }
    Voici mon prgm

    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
     
    printf("line = %s\n",line);
     
    if(strchr(line,'\0')!=NULL) printf("oui\n"); else printf("non\n");
    if(strchr(line,'\n')!=NULL) printf("oui\n"); else printf("non\n");
    printf("%d\n",strlen(line));
     
    DeleteCharEndOfLine(line,countline,countline2);
     
    if(strchr(line,'\0')!=NULL) printf("oui\n"); else printf("non\n");
    if(strchr(line,'\n')!=NULL) printf("oui\n"); else printf("non\n");
    printf("%d\n",strlen(line));
     
    DeleteComment(line);
     
    if(strchr(line,'\0')!=NULL) printf("oui\n"); else printf("non\n");
    if(strchr(line,'\n')!=NULL) printf("oui\n"); else printf("non\n");
    printf("%d\n",strlen(line));
    Les sorties sont :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    line = TEMP 350 400 450.613
     
    oui
    oui
    22
    oui
    non
    21
    oui
    non
    21
    En revanche, si dans la fonction DeleteComment, je supprime le commentaire devant le else, j'obtiens comme sorties :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    line = TEMP 350 400 450.613
     
    oui
    oui
    22
    oui
    non
    21
    oui
    non
    20
    Je ne comprends donc pas bien : ma ligne line, est-elle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    line = TEMP 350 400 450.613\0\n
    j'ai mis explicitement les caracètres \0 et \n ou seulement \n mais après, est-ce qu'elle devient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    line = TEMP 350 400 450.613\0
    ou bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    line = TEMP 350 400 450.613
    Savez-vous où se trouvent les coquilles dans ces deux fonctions ? Normalement je dois toujours avoir le caractère \0 à la fin de ma string non ?

    Merci.

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Le \0 n'est pas supposé être dans le fichier d'origine.

    Normalement, avec fgets(), on a ceci (avec un buffer assez grand: on va dire 10 chars, et ligne "salut") :

    ['s', 'a', 'l', 'u', 't', 10, 0, ?, ?, ?]

    Donc, le \n a été lu, et le \0 a été inséré juste après.

    Par contre, avec un buffer trop petit, on est supposé avoir ceci:
    ['a', 'n', 't', 'i', 'c', 'o', 'n', 's', 't', 0]
    Le \0 termine toujours la chaîne, mais le \n n'a pas été lu: Il est encore dans le fichier d'entrée, avec la suite du mot: Ces caractères seront lus lors du prochain fgets().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut
    Bonjour,

    '\0' signifit la fin d'une chaine de caratère
    '\n' signifit un retour à la ligne dans un fichier ou une sortie.

    Pour ma part, il me semble qu'un petite fonction comme ceci suffit :

    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
    int SupprimerCommentaire(char Ligne[])
    {
    int n, i ;
     
    n = strlen(Ligne) ;
     
    for (i=0 ; i < n ; i++) /* On parcours, ligne */
        if ( Ligne[i] == '!' ) /* Si on trouve un commentaire, on s'arrete */
             {
              Ligne[i] = '\n' ; /* On marque la fin de ligne, la suite sera donc ignorée */
              return 1 ; /* On a trouvé un commentaire, donc on renvoi 1 */
             }
     
    return 0 ; /* Aucun commentaire trouvé, on renvoi 0 */
    }
    bon courage
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Bonjour, merci pour vos réponses, mais je n'arrive pas à m'expliquer les sorties de mon prgm. Je vous envoie mon prgm, pouvez-vous s'il vous plait y jeter un coup d'oeil ? Les sorties sont à la fin.

    voici mon fichier input.txt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    TEMP 350 400 450.613
    PRES 1.5 1.7 1.6       ! initial pressures in bar
    et voici mon prgm (enfin une partie)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    fgets(line,sizeof line,file);
    DeleteCharEndOfLine(line,countline,countline2);
    DeleteComment(line);
    if(strstr(line,"TEMP ")!=NULL)
    {
    ReadLineWithDouble(line,temp);
    for(i=0;i<*N;++i)
      assert((*temp)->data[i]>0.0);
    }
    et voici mes fonctions annexes :

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    void DeleteComment(char * line_)
    {
      /* This function deletes the char '!' and all the char after it of
         the string line_.
         This function deletes also all the spaces befor the char '!' and
         the last char of line_ which isn't a space
      */
      char * p=strchr(line_,'!');
      if(p!=NULL)
      {
        /* d is the index of string line_ which contains the char '!' 
           Remark : the first index is 0
        */
        int d=p-line_,i; 
        for(i=d-1;line_[i]==' ';--d,--i);
        char dest[d];
        char * s3=strncpy(dest,line_,d);
     
         /* we add char '\0' at the end of s3 so at the end of line_ */
        s3[d]='\0';    
        char * aux=strcpy(line_,s3);
        assert(aux!=NULL);
      }
      /* we add char '\0' at the end of line_. The last index is
         strlen(line_)-1
      */
      //else line_[strlen(line_)-1]='\0';
    }
     
    void DeleteCharEndOfLine(char * line_,unsigned short nl,unsigned short nl_)
    {
      /*
        Delete char '\n' if this one was founded in the string line_,
        send an error message otherwise
        nl is the number of line of the input file
        nl_ is the number of the line which contains the string line_
      */
     
      char * p = strchr(line_,'\n'); /* char '\n' is sought */
      if (p != NULL) /* if it was founded it is cleared */
        *p =0;
      else if(nl_!=nl) /* the last line of input file can not to have char '\n' */
      {
        /* tabular is too short. Exit program */
        fprintf(stderr,"Error in file %s line %d in function %s : tabular line_ is too short\nIncrease its size\nExit program\n",__FILE__,__LINE__,__FUNCTION__);
        exit(1);
      }
    }
     
    void ReadLineWithDouble(char * s,Tableau ** tab)
    {
         /*
            s est une string qui contient des doubles.
            Cette fonction remplit le tableau tab avec ces doubles
         */
         printf("debut de ReadLineWithDouble\n");
         printf("s = titi%stata\n",s);
         if(strchr(s,'\0')!=NULL) printf("oui\n"); else printf("non\n");
         if(strchr(s,'\n')!=NULL) printf("oui\n"); else printf("non\n");
         //s[strlen(s)-1]='\0';
         char * p = strstr(s," ");
         if(p!=NULL)
         {
           unsigned int ind=0;
           while (*p)
           {     
              (*tab)->data[ind]=strtod(p,&p);
    	  printf("ind = %d\n",ind);
    	  printf("tab = %g\n",(*tab)->data[ind]);
              ++ind;
           }
         }
    }
     
    short NumberSpaces(char * s)
    {
    /* count number spaces of the string s */
    unsigned short count=0, i;
    for(i=0;i<strlen(s);++i)
      if(s[i]==' ')
        ++count;
     
    return count;
    }
    La sortie de ma fonction ReadLineWithDouble est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tatatitiTEMP 350 400 450.613
    Pourquoi n'ai-je pas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    titiTEMP 350 400 450.613tata
    Mon prgm me renvoie un segmentation fault. si je mets un commentaires à la ligne TEMP mon prgm marche bien, sinon il ne marche pas. Savez-vous pourquoi ?
    Merci de votre patience

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    ne compile pas.

    On n'a pas le main, etc.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    salut, bon je vous envoie ton mon prgm (avec le main).
    Voici mon fichier input.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ! initial condition
     
    TEMP 350 400 450.613
    PRES 1.5 1.7 1.6       ! initial pressures in bar
    EGR 20 30        45 ! taux d'EGR in %
         RICHESSE 0.6 0.5 0.4 ! initial air fuel ratio
     
    ! engine data
    RPM 1500 ! rotation per minute
    PS : c'est normal que rien ne soit aligné, je fais des fonctions annexes qui doivent tout aligner.

    Je vous envoie après mon prgm. Si à la fin de la ligne TEMP blabla je mets un commentaire (donc un point d'exclamation), tout tourne très bien, en revanche, si je ne mets rien (donc comme ci dessous), il y a un bug lorsque je charge les valeurs de TEMP dans mon tableau. Le souci vient de la longueur de la chaine TEMP blabla.
    Voici mon code (c'est un peu long, mais au moins il y a le main et toutes les autres fonctions).

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<assert.h>
    #include<string.h>
     
    typedef struct t_tab
    {
        int dim; // dimension du tableau
        double * data;
    } Tableau;
     
    Tableau * alloc_Tableau(unsigned int,double);
    void free_Tableau(Tableau *);
    void affiche_Tableau(Tableau *);
    Tableau * Tableau_vide(void);
    void copie_Tableau(Tableau *,Tableau *);
     
    Tableau * alloc_Tableau(unsigned int dim_,double val)
    {
    // alloue un espace memoire pour creer le tableau t et l'initialise a val
        assert(dim_>=0);
     
        Tableau * t=malloc(sizeof(*t));
        assert(t!=NULL);
     
        if(dim_==0) // si dim_==0 on considere que le tableau est vide
        {
    	t->dim=0;
    	t->data=NULL;
        }
        else
        {
    	t->dim=dim_;
    	t->data=malloc(dim_*sizeof(*t->data));
    	assert(t->data!=NULL);
    	unsigned int i;
    	for(i=0;i<dim_;i++)
    	    t->data[i]=val;
        }
        return t;
    }
     
    void free_Tableau(Tableau * t)
    {
        t->dim=0;
    // libere la memoire
        if(t->data!=NULL)
        {
    	free(t->data);
    	t->data=NULL;
        }
        free(t);
        t=NULL;
        return ;
    }
     
    Tableau * Tableau_vide(void)
    {
        Tableau * t=malloc(sizeof(*t));
        t->dim=0;
        t->data=NULL;
        return t;
    }
     
    void affiche_Tableau(Tableau * t)
    {
        if(t->data==NULL)
    	printf("\nTableau vide\n");
        else
        {
    	int i;
    	for(i=0;i<t->dim;i++)
    	    printf("%15.15g\t",t->data[i]);
    	printf("\n");
        }
        printf("\n");
        return;
    }
     
    void copie_Tableau(Tableau * t,Tableau * out)
    {
    // copie le tableau *t dans le tableau *out
     
        int i;
     
     
    	if(t->dim==0) // tableau vide
    	    out=Tableau_vide();
    	else
    	{
    	    for(i=0;i<out->dim;++i)
    		out->data[i]=t->data[i];
    	}
     
        return;
    }
     
    void LoadInitialInputs(char * input_file,unsigned short * N,Tableau** temp,Tableau ** pres,Tableau ** richesse,Tableau ** EGR,double * rpm);
     
    void ReadLineWithDouble(char * s,Tableau ** tab)
    {
         /*
            s est une string qui contient des doubles.
            Cette fonction remplit le tableau tab avec ces doubles
         */
         char * p = strstr(s," ");
         if(p!=NULL)
         {
           unsigned int ind=0;
           while (*p)
           {    
              (*tab)->data[ind]=strtod(p,&p);
              ++ind;
           }
         }
    }
     
    short IsCommentLine(char * s)
    {
          /* 
             The output is 1 if s is a line with only comments, else 0
             A comment line is a line which begins by the char '!'
          */
     
          char * p=strchr(s,'!');
          if(p==NULL)
            return 0;
          else
          {
            int d=p-s; /* index of string s which contains the char '!'  Remark : the first index is 0 */
            int i;
            for(i=0;(i<=d) && (s[i]==' ');++i);
            return (i==d) ? 1 : 0;
          }
    }
     
    void DeleteInitialSpaces(char * s)
    {
      /* this function deletes all the chars in the string s between the
         first char which is not a space
      */
      unsigned int n,i; /* n is the number of spaces which must be removed */
      for(n=0;s[n]==' ';++n);
      if(n!=0)
      {
        for(i=0;i<strlen(s)-n;++i)
          s[i]=s[i+n];
        s[strlen(s)-n]='\0';
      }
     
     
    }
     
    void DeleteConsecutiveSpaces(char * s)
    {
      /* if there are many spaces between two chars of the string s, this
         function deletes all these spaces in order to it remains only one
         space between these two chars
      */
      unsigned int i,j;
      for(i=0;i<strlen(s);++i)
      {
        if(s[i]==' ')
        {
          for(j=i+1;(s[j]==' ') && (j<strlen(s));++j);
          short n=j-i-1; /* number of spaces which should be erased */
          if(n!=0)
          {
            for(j=i+1;j<strlen(s)-n;++j)
              s[j]=s[j+n];
    	s[strlen(s)-n]='\0';
          }
        }
      }
     
    }  
     
    short NumberSpaces(char * s)
    {
    /* count number spaces of the string s */
    DeleteInitialSpaces(s);
    DeleteConsecutiveSpaces(s);
    unsigned short count=0, i;
    for(i=0;i<strlen(s);++i)
    if(s[i]==' ')
    ++count;
     
    return count;
    }
     
    void DeleteComment(char *);
    void DeleteCharEndOfLine(char * ,unsigned short,unsigned short);
     
    int main()
    {
    Tableau * temp=Tableau_vide();
    Tableau * pres=Tableau_vide();
    Tableau * richesse=Tableau_vide();
    Tableau * EGR=Tableau_vide();
    unsigned short N;
    double rpm;
     
    LoadInitialInputs("input.txt",&N,&temp,&pres,&richesse,&EGR,&rpm);
     
    printf("affichage de temp\n");
    affiche_Tableau(temp);
    printf("affichage de pres\n");
    affiche_Tableau(pres);
    printf("affichage de EGR\n");
    affiche_Tableau(EGR);
    printf("affichage de richesse\n");
    affiche_Tableau(richesse);
    printf("rpm = %g\n",rpm);
     
    free_Tableau(temp);
    free_Tableau(pres);
    free_Tableau(richesse);
    free_Tableau(EGR);
     
    return 0;
    }
     
    void DeleteComment(char * line_)
    {
      /* This function deletes the char '!' and all the char after it of
         the string line_.
         This function deletes also all the spaces befor the char '!' and
         the last char of line_ which isn't a space
      */
      char * p=strchr(line_,'!');
      if(p!=NULL)
      {
        /* d is the index of string line_ which contains the char '!' 
           Remark : the first index is 0
        */
        int d=p-line_,i; 
        for(i=d-1;line_[i]==' ';--d,--i);
        char dest[d];
        char * s3=strncpy(dest,line_,d);
     
         /* we add char '\0' at the end of s3 so at the end of line_ */
        s3[d]='\0';    
        char * aux=strcpy(line_,s3);
        assert(aux!=NULL);
      }
    }
     
    void DeleteCharEndOfLine(char * line_,unsigned short nl,unsigned short nl_)
    {
      /*
        Delete char '\n' if this one was founded in the string line_,
        send an error message otherwise
        nl is the number of line of the input file
        nl_ is the number of the line which contains the string line_
      */
     
      char * p = strchr(line_,'\n'); /* char '\n' is sought */
      if (p != NULL) /* if it was founded it is cleared */
        *p =0;
      else if(nl_!=nl) /* the last line of input file can not to have char '\n' */
      {
        /* tabular is too short. Exit program */
        fprintf(stderr,"Error in file %s line %d in function %s : tabular line_ is too short\nIncrease its size\nExit program\n",__FILE__,__LINE__,__FUNCTION__);
        exit(1);
      }
    }
     
    void LoadInitialInputs(char * input_file,unsigned short * N,Tableau ** temp,Tableau ** pres,Tableau ** richesse,Tableau ** EGR,double * rpm)
    {
    /*
    input_file est le nom du fichier contenant les input
    N est le nombre de particules
    temp est un tableau contenant les temperatures initiales de chaque particule
    pres est un tableau contenant les pressions initiales de chaque particule
    richesse est un tableau contenant la richesse initiale de chaque particule
    EGR est un tableau contenant le taux d'EGR (en %) de chaque particule
    */
     
    /* opening of the file in reading mode */
    FILE * file=fopen(input_file,"r");
    if (file==NULL)
    {
    fprintf(stderr,"Error in file %s line %d in function %s : file %s wasn't found\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file);
    exit(1);
    }
     
    int i;
     
    /* definition of a table of char intended to receive the line */
    char line[10000];
     
    /* on compte le nombre de lignes du fichier d'entrees */
    unsigned int countline=0;
    for(;fgets (line, sizeof line, file) != NULL;++countline);
    if(ferror(file))
    {
    fprintf(stderr,"Error in file %s line %d in function %s : a misreading occurred in file %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file);               
    exit(1);
    }
    fclose(file);
     
    file=fopen(input_file,"r");
    unsigned int countline2=0;
     
    do
    {
      fgets (line, sizeof line, file);
      ++countline2;
      if(feof(file))
      {
        fprintf(stderr,"Error in file %s line %d in function %s : key word TEMP wasn't found in file %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file);
        exit(1);
      }
    }
    while(strstr(line,"TEMP ")==NULL);
     
    fclose(file);
     
    DeleteCharEndOfLine(line,countline,countline2);
    DeleteComment(line);
     
    *N=NumberSpaces(line);
     
    /* creation des tableaux */
     
    free_Tableau(*temp);
    free_Tableau(*pres);
    free_Tableau(*richesse);
    free_Tableau(*EGR);
     
    *temp=alloc_Tableau(*N,0.0);
    *pres=alloc_Tableau(*N,0.0);
    *richesse=alloc_Tableau(*N,0.0);
    *EGR=alloc_Tableau(*N,0.0);
     
    /* initialisation des tableaux */
     
    file=fopen(input_file,"r");
     
    char keyword[50]; /* tableau stockant le mot cle */
    countline2=0; /* line counteur */
     
    while(fgets (line, sizeof line, file) != NULL)
    {      
    ++countline2;
     
    /* si strlen(line_)==2 alors cela veut dire que la ligne est une ligne "blanche" et que line_='\n'
       il vaut mieux utiliser le test strlen(line_)!=2 plutot que le test strcmp(line_,"\n") car suivant
       le cas ou le fichier input_file a ete ecrit sous windows ou unix, le format des retours chariot n'est
       pas le meme, ce qui peut etre cause d'erreur du prgm
       cf <a href="http://emmanuel-delahaye.developpez.com/notes.htm" target="_blank">http://emmanuel-delahaye.developpez.com/notes.htm</a>
    */
    if( (!IsCommentLine(line)) && (strlen(line)!=2) )
    {
    DeleteCharEndOfLine(line,countline,countline2);
    DeleteComment(line);
     
    if(strstr(line,"TEMP ")!=NULL)
    {
    ReadLineWithDouble(line,temp);
    for(i=0;i<*N;++i)
      assert((*temp)->data[i]>0.0);
    }
    else if(strstr(line,"PRES ")!=NULL)
    {
    assert(NumberSpaces(line)==*N);
    ReadLineWithDouble(line,pres);
    for(i=0;i<*N;++i)
      assert((*pres)->data[i]>0.0);
    }
    else if(strstr(line,"RICHESSE ")!=NULL)
    {
    assert(NumberSpaces(line)==*N);
    ReadLineWithDouble(line,richesse);
    for(i=0;i<*N;++i)
      assert((*richesse)->data[i]>0.0);
    }
    else if(strstr(line,"EGR ")!=NULL)
    {
    assert(NumberSpaces(line)==*N);
    ReadLineWithDouble(line,EGR);
    for(i=0;i<*N;++i)
      assert( ((*EGR)->data[i]/=100.0) >=0.0);
    }
    else if(strstr(line,"RPM ")!=NULL)
    {
    assert(NumberSpaces(line)==1);
    sscanf(line,"%s%lf",keyword,rpm);
    assert(*rpm>0.0);
    }
    else
    {
    fprintf(stderr,"Error in file %s line %d in function %s : none keyword was found in file %s at line %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file,line);
    exit(1);
    }
    } /* end of if( (!IsCommentLine(line_)) && strcmp(line_,"\n") ) */
    } /* end of while */
     
    if(!feof(file))
    {
    fprintf(stderr,"Error in file %s line %d in function %s : a misreading occurred in file %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file);               
    exit(1);
    }
     
    if(ferror(file))
    {
    fprintf(stderr,"Error in file %s line %d in function %s : a misreading occurred in file %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,input_file);               
    exit(1);
    }
     
    fclose(file);
    }
    Merci de votre aide en tous les cas !

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Déjà, quelques reproches à faire:
    1°) Absence totale de const
    2°) et un manque de compréhensibilité des noms de variables.
    3°) Tu devrais utiliser un type perso booléen là où c'est pertinent (comme IsCommentLine())

    Puis, avant même de compiler, j'ai relevé 2-3 petites erreurs:
    (voici le code avec les erreurs relevées, j'ai viré les fonctions où je n'avais rien à dire
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    #include<stdlib.h>
    #include<stdio.h>
    #include<assert.h>
    #include<string.h>
     
    //--- structures ---
    typedef struct t_tab
    {
    int dim; // dimension du tableau
    double * data;
    } Tableau;
     
     
    //--- Prototypes de fonctions ---
     
    ...
     
    void LoadInitialInputs(
     char const * input_file,	//J'ai rajouté const, maintenant ça compile en -Wwrite-strings
     unsigned short * N,
     Tableau** temp,
     Tableau ** pres,
     Tableau ** richesse,
     Tableau ** EGR,
     double * rpm
     );
    void DeleteComment(
     char *
     );
    void DeleteCharEndOfLine(
     char * ,
     unsigned short,
     unsigned short
     );
     
     
     
    /* Fonction alloc_Tableau()
       ------------------------ */
    Tableau * alloc_Tableau(
     unsigned int dim_,
     double val
     )
    {
    // alloue un espace memoire pour creer le tableau t et l'initialise a val
    /* ***ATTENTION***
    Assertion foireuse en non-signé
    */
    //assert(dim_>=0);
     
    Tableau * t = malloc(sizeof(*t));
    assert(t!=NULL);
     
    if(dim_ == 0) // si dim_==0 on considere que le tableau est vide
    	{
    	t->dim = 0;
    	t->data = NULL;
    	}
    else
    	{
    	t->dim = dim_;
    	t->data = malloc(dim_*sizeof(*t->data));
    	assert(t->data!=NULL);
     
    	unsigned int i;
    	for(i=0 ; i<dim_ ; i++)
    		t->data[i]=val;
    	}
    return t;
    }
     
     
    /* Fonction Tableau_vide()
       ----------------------- */
    Tableau * Tableau_vide(
     void
     )
    {
    Tableau * t = malloc(sizeof(*t));
    /* *****ERREUR*****
    Le retour de malloc() n'est pas testé
    */
    t->dim = 0;
    t->data = NULL;
    return t;
    }
     
     
    /* Fonction copie_Tableau()
       ------------------------ */
    void copie_Tableau(
     Tableau * t,
     Tableau * out
     )
    {
    // copie le tableau *t dans le tableau *out
     
    int i;
     
    /* *****ERREUR*****
    out = Tableau_vide() ne modifie pas le pointeur dans la fonction appelante...
    */
    if(t->dim==0) // tableau vide
    	out = Tableau_vide();
    else
    	{
    	for(i=0 ; i<out->dim ; ++i)
    		out->data[i]=t->data[i];
    	}
     
    return;
    }
     
     
    /* Fonction ReadLineWithDouble()
       ----------------------------- */
    void ReadLineWithDouble(
     char * s,
     Tableau ** tab
     )
    {
    /*
    s est une string qui contient des doubles.
    Cette fonction remplit le tableau tab avec ces doubles
    */
    /* ***ATTENTION***
    La dimension du tableau n'est pas vérifiée
    */
    char * p = strstr(s," ");
     
    if(p!=NULL)
    	{
    	unsigned int ind=0;
    	while(*p)
    		{
    		(*tab)->data[ind] = strtod(p,&p);
    		++ind;
    		}
    	}
    }
     
     
    /* Fonction NumberSpaces()
       ----------------------- */
    short NumberSpaces(char * s)
    {
    /* count number spaces of the string s */
    DeleteInitialSpaces(s);
    DeleteConsecutiveSpaces(s);
     
    unsigned short count=0, i;
     
    for(i=0 ; i<strlen(s) ; ++i)
    	if(s[i] == ' ')
    		++count;
     
    return count;
    }
     
     
    /* Fonction DeleteComment()
       ------------------------ */
    void DeleteComment(
     char * line_
     )
    {
    /* This function deletes the char '!' and all the char after it of
    the string line_.
    This function deletes also all the spaces befor the char '!' and
    the last char of line_ which isn't a space
    */
    char * p = strchr(line_, '!');
     
    if(p != NULL)
    	{
    	/* d is the index of string line_ which contains the char '!'
    	Remark : the first index is 0
    	*/
    	int d = p-line_,i;
    	for(i=d-1 ; line_[i]==' ' ; --d,--i);
     
    	/* ***ATTENTION***
    	Je rappelle que strncpy() retourne dest, donc s3==dest.
    	De plus, c'est beaucoup de bruit pour pas grand-chose:
    	Il suffirait de remplacer le premier caractère inutile par un \0,
    	nul besoin de jouer avec une copie de la chaîne...
    	*/
    	char dest[d];
    	char * s3 = strncpy(dest, line_, d);
     
    	/* we add char '\0' at the end of s3 so at the end of line_ */
    	s3[d] = '\0';
    	char * aux = strcpy(line_,s3);
    	assert(aux!=NULL);
    	}
    }
     
     
    /* Fonction DeleteCharEndOfLine()
       ------------------------------ */
    void DeleteCharEndOfLine(
     char * line_,
     unsigned short nl,
     unsigned short nl_
     )
    {
    /*
    Delete char '\n' if this one was founded in the string line_,
    send an error message otherwise
    nl is the number of line of the input file
    nl_ is the number of the line which contains the string line_
    */
    /* *ANGLAIS*
    Le participe passé du verbe "find" est "found".
    De plus, il peut être plus explicite d'employer '\0' au lieu de simplement zéro
    */
    char * p = strchr(line_, '\n'); /* char '\n' is sought */
     
    if(p != NULL) /* if it was founded it is cleared */
    	*p = 0;
    else if(nl_ != nl) /* the last line of input file can not to have char '\n' */
    	{
    	/* tabular is too short. Exit program */
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : tabular line_ is too short\n"
    	  "Increase its size\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__
    	 );
    	exit(1);
    	}
    }
     
     
    /* Fonction LoadInitialInputs()
       ---------------------------- */
    void LoadInitialInputs(
     char const * input_file, //j'ai rajouté le const ici aussi...
     unsigned short * N,
     Tableau ** temp,
     Tableau ** pres,
     Tableau ** richesse,
     Tableau ** EGR,
     double * rpm
     )
    {
    ....
    }
    Rien que pour l'amour de l'art, je vais essayer de corriger un peu.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Salut, je corrige de suite ces erreurs.
    Merci !!

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Bon, après de sérieuses corrections (NON-TESTÉES!!) voici ceci:

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    #include<stdlib.h>
    #include<stdio.h>
    #include<assert.h>
    #include<string.h>
    #include<ctype.h>
     
    //--- structures ---
    /*
    Note:
    Un tableau const interdit de modifier sa taille ou son pointeur de données,
    mais les données pointées peuvent l'être.
    */
    typedef struct t_tab
    {
    size_t dim; // dimension du tableau
    double * pt_data;
    double const *ptc_data;//Pointeur redondant mais const
    } Tableau;
     
    //--- Type booléen ---
    typedef short BOOLEEN;
    #define VRAI    ((BOOLEEN)1)
    #define FAUX    ((BOOLEEN)0)
     
    //--- Autrez types ---
    typedef unsigned short NUMBEROFDATAS;
    typedef unsigned short NUMLIGNE;
     
    //--- Prototypes de fonctions ---
    Tableau * AllocTableau(
     size_t const nTaille,	//[in] Taille du tableau (nb de doubles)
     double const dValeurInitiale	//[in] Double qui remplit le tableau
     );
    Tableau * AllocTableauVide(
     void
     );
    void FreeTableau(
     Tableau * const pt_tab	//[in] Tableau à détruire
     );
    void AfficheTableau(
     Tableau const * const ptc_tab	//[in] Tableau à afficher
     );
    void CopieTableau(
     Tableau const * const ptc_tabIn,	//[in] Tableau source
     Tableau * const pt_tabOut	//[out] Tableau destination
     );
    void ReadLineWithDouble(
     char const * const sczChaine,	//[in] Chaîne contenant des doubles
     Tableau const * const ptc_tab	//[out] Tableau dont les data sont modifiées
     );
    BOOLEEN IsCommentLine(
     char const * const sczLigne	//[in] Chaîne à tester
     );
    void DeleteInitialSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     );
    void DeleteConsecutiveSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     );
    NUMBEROFDATAS GetPurifiedNumberOfSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     );
    void DeleteComment(
     char * const szLigne	//[in/out] Chaine à épurer
     );
    void DeleteCharEndOfLine(
     char * const szLigne,	//[in/out] Chaine à épurer
     NUMLIGNE const nNblignes,	//[in] Nombre Total de lignes
     NUMLIGNE const nNumligne	//[in] N° de ligne
     );
    void LoadInitialInputs(
     char const * const sczInputFile,	//[in] Nom du fichier d'entrée
     NUMBEROFDATAS * const pt_N,	//[out] Recoit le nombre de données de la dernière entrée ?
     Tableau ** const pt_pt_tabTemp,	//[out] tableau temp
     Tableau ** const pt_pt_tabPres,	//[out] tableau pres
     Tableau ** const pt_pt_tabRichesse,	//[out] tableau richesse
     Tableau ** const pt_pt_tabEGR,	//[out] tableau EGR
     double * const pt_dRpm	//[out] recoit rpm
     );
     
     
     
    /* Fonction pour allouer la mémoire pour un tableau
       ------------------------------------------------ */
    Tableau * AllocTableau(
     size_t const nTaille,	//[in] Taille du tableau (nb de doubles)
     double const dValeurInitiale	//[in] Double qui remplit le tableau
     )
    {
    Tableau * pt_tabRetour = malloc(sizeof(*pt_tabRetour));
    assert(pt_tabRetour != NULL);
     
    if(nTaille == 0)
    	{
    	//taille nulle : On retourne un tableau vide
    	pt_tabRetour->dim = 0;
    	pt_tabRetour->pt_data = NULL;
    	pt_tabRetour->ptc_data = pt_tabRetour->pt_data;
    	}
    else
    	{
    	size_t i;
     
    	//Taille non-nulle : On retourne un tableau rempli
    	pt_tabRetour->dim = nTaille;
    	pt_tabRetour->pt_data = malloc(nTaille * sizeof(*pt_tabRetour->pt_data));
    	pt_tabRetour->ptc_data = pt_tabRetour->pt_data;
    	assert(pt_tabRetour->pt_data != NULL);
     
    	//Remplit le tableau avec dValeurInitiale
    	for(i=0 ; i<nTaille ; i++)
    		pt_tabRetour->pt_data[i] = dValeurInitiale;
    	}
    assert(pt_tabRetour->ptc_data == pt_tabRetour->pt_data);
    return pt_tabRetour;
    }
     
     
    /* Fonction pour allouer un tableau vide
       ------------------------------------- */
    Tableau * AllocTableauVide(
     void
     )
    {
    Tableau * pt_tabRetour = malloc(sizeof(*pt_tabRetour));
    assert(pt_tabRetour != NULL);
     
    pt_tabRetour->dim = 0;
    pt_tabRetour->pt_data = NULL;
    pt_tabRetour->ptc_data = pt_tabRetour->pt_data;
     
    assert(pt_tabRetour->ptc_data == pt_tabRetour->pt_data);
    return pt_tabRetour;
    }
     
     
    /* Fonction pour détruire un tableau
       --------------------------------- */
    void FreeTableau(
     Tableau * const pt_tab	//[in] Tableau à détruire
     )
    {
    if(pt_tab)
    	{
    	assert(pt_tab->ptc_data == pt_tab->pt_data);
    	pt_tab->dim = 0;
    	// libère la mémoire des données si non-null (free() fait le test)
    	free(pt_tab->pt_data);
    	// Libère la mémoire du tableau
    	free(pt_tab);
    	}
    }
     
     
    // Fonction affiche_Tableau()
    /* Fonction pour afficher un tableau sur la sortie standard
       -------------------------------------------------------- */
    void AfficheTableau(
     Tableau const * const ptc_tab	//[in] Tableau à afficher
     )
    {
    if(ptc_tab==NULL)
    	{
    	printf("\nTableau NULL\n");
    	}
    assert(ptc_tab->ptc_data == ptc_tab->pt_data);
     
    if(ptc_tab->ptc_data == NULL)
    	printf("\nTableau vide\n");
    else
    	{
    	size_t i;
     
    	for(i=0 ; i<ptc_tab->dim ; i++)
    		printf("%15.15g\t", ptc_tab->ptc_data[i]);
    	printf("\n");
    	}
    printf("\n");
    }
     
     
    /* Fonction pour copier un tableau dans un autre
       --------------------------------------------- */
    void CopieTableau(
     Tableau const * const ptc_tabIn,	//[in] Tableau source
     Tableau * const pt_tabOut	//[out] Tableau destination
     )
    {
    assert(pt_tabOut->ptc_data == pt_tabOut->pt_data);
     
    // Nettoyage du tableau de destination
    if(ptc_tabIn->dim != pt_tabOut->dim)
    	{
    	//Libère les données du tableau destination si elles existent
    	pt_tabOut->dim = 0;
    	free(pt_tabOut->pt_data);
    	pt_tabOut->pt_data = NULL;
    	pt_tabOut->ptc_data = pt_tabOut->pt_data;
    	}
     
    if(ptc_tabIn->dim == 0)
    	{
    	//Le tableau d'origine est vide: Puisque le tableau destination doit être
    	//vide aussi, rien à faire...
    	assert(pt_tabOut->dim == 0);
    	assert(pt_tabOut->pt_data == NULL);
    	assert(pt_tabOut->ptc_data == pt_tabOut->pt_data);
    	}
    else
    	{
    	//Les tableaux sont de tailles différentes
     
    	//Allocation des données du tableau destination si manquantes
    	if(pt_tabOut->dim == 0)
    	    {
    		pt_tabOut->dim = ptc_tabIn->dim;
    		pt_tabOut->pt_data = malloc(pt_tabOut->dim * sizeof(*pt_tabOut->pt_data));
    		pt_tabOut->ptc_data = pt_tabOut->pt_data;
    		assert(pt_tabOut->pt_data != NULL);
    		}
    	size_t i;
    	for(i=0 ; i<pt_tabOut->dim ; ++i)
    		pt_tabOut->pt_data[i] = ptc_tabIn->ptc_data[i];
    	}
    }
     
     
    // Fonction ReadLineWithDouble()
    /* Fonction pour lire le contenu d'une chaîne pour remplir un tableau
       ------------------------------------------------------------------ */
    void ReadLineWithDouble(
     char const * const sczLigne,	//[in] Chaîne contenant des doubles
     Tableau const * const ptc_tab	//[out] Tableau dont les data sont modifiées
     )
    {
    char const * sczNombre = strstr(sczLigne, " ");
     
    if(sczNombre != NULL)
    	{
    	size_t ind = 0;
    	while(*sczNombre)
    		{
    		char *szFin = NULL;
     
    		assert(ind < ptc_tab->dim);
     
    		ptc_tab->pt_data[ind] = strtod(sczNombre, &szFin);
    		++ind;
    		sczNombre = szFin;
    		}
    	}
    }
     
     
    // Fonction IsCommentLine()
    /* Fonction pour savoir si une ligne ne contient qu'un commentaire
       --------------------------------------------------------------- */
    BOOLEEN IsCommentLine(
     char const * const sczLigne	//[in] Chaîne à tester
     )
    {
    /*
    The output is VRAI if s is a line with only comments, else FAUX
    A comment line is a line which begins by the char '!'
    */
     
    char const * sczExclam = strchr(sczLigne, '!');
     
    if(sczExclam==NULL)
    	return FAUX;
    else
    	{
    	/* The line contains a !
    	If there are only spaces before it, the line is a comment
    	*/
    	size_t const iExclam = sczExclam - sczLigne; //Index of exclamation mark
    	size_t i;
    	for(i=0 ; (i<=iExclam) && isspace(sczLigne[i]) ; ++i);
     
    	return (i==iExclam) ? VRAI : FAUX;
    	}
    }
     
     
    // Fonction DeleteInitialSpaces()
    /* Fonction pour supprimer les espaces en tête de ligne
       ---------------------------------------------------- */
    void DeleteInitialSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     )
    {
    /* this function deletes all the chars in the string s between the
    first char which is not a space
    */
    size_t nSpaces; /* nSpaces is the number of spaces which must be removed */
     
    for(nSpaces=0 ; isspace(szLigne[nSpaces]) ; ++nSpaces);
     
    if(nSpaces != 0)
    	{
    	size_t i;
     
    	for(i=0 ; szLigne[i+nSpaces]!='\0' ; ++i)
    		szLigne[i] = szLigne[i+nSpaces];
    	szLigne[i] = '\0';
    	}
    }
     
     
    // Fonction DeleteConsecutiveSpaces()
    /* Fonction pour supprimer les espaces consécutifs
       ----------------------------------------------- */
    void DeleteConsecutiveSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     )
    {
    /* if there are many spaces between two chars of the string s, this
    function deletes all these spaces in order to it remains only one
    space between these two chars
    */
    size_t i,j;
    BOOLEEN bVuPremierEspace = FAUX;
     
    for(i=0,j=0 ; szLigne[i]!='\0' ; ++i)
    	{
    	if(isspace(szLigne[i]))
    		{
    		//Le caractère est un espace
    		if(bVuPremierEspace)
    		    {
    			//On a déjà vu le premier espace d'une série: on ne fait rien
    			}
    		else
    		    {
    			//C'est le premier espace d'une série:
    			//On le copie et on marque le flag
    			szLigne[j] = szLigne[i];
    			++j;
    			bVuPremierEspace = VRAI;
    			}
    		}
    	else
    	    {
    		//Le caractère n'est pas un espace : On le copie
    		szLigne[j] = szLigne[i];
    		++i;
    		bVuPremierEspace = FAUX;
    		}//if /isspace
    	}//for
    }
     
     
    // Fonction NumberSpaces()
    /* Fonction pour purifier une ligne et obtenir son nombre d'espaces
       ---------------------------------------------------------------- */
    NUMBEROFDATAS GetPurifiedNumberOfSpaces(
     char * const szLigne	//[in/out] Chaine à épurer
     )
    {
    /* count number spaces of the string s */
    DeleteInitialSpaces(szLigne);
    DeleteConsecutiveSpaces(szLigne);
     
    NUMBEROFDATAS nSpaces=0;
    size_t i;
     
    for(i=0 ; szLigne[i]!='\0' ; ++i)
    	if(isspace(szLigne[i]))
    		++nSpaces;
     
    return nSpaces;
    }
     
     
    /* M A I N
       ------- */
    int main(void)
    {
    //Inutile de les allouer, la première chose qu'on fait est de les supprimer
    Tableau * pt_tabTemp = NULL;
    Tableau * pt_tabPres = NULL;
    Tableau * pt_tabRichesse = NULL;
    Tableau * pt_tabEGR = NULL;
    NUMBEROFDATAS N;
    double dRpm;
     
    LoadInitialInputs(
     "input.txt",
     &N,
     &pt_tabTemp,
     &pt_tabPres,
     &pt_tabRichesse,
     &pt_tabEGR,
     &dRpm
     );
     
    printf("affichage de temp\n");
    AfficheTableau(pt_tabTemp);
    printf("affichage de pres\n");
    AfficheTableau(pt_tabPres);
    printf("affichage de EGR\n");
    AfficheTableau(pt_tabEGR);
    printf("affichage de richesse\n");
    AfficheTableau(pt_tabRichesse);
    printf("rpm = %g\n", dRpm);
     
    FreeTableau(pt_tabTemp);
    FreeTableau(pt_tabPres);
    FreeTableau(pt_tabRichesse);
    FreeTableau(pt_tabEGR);
     
    return 0;
    }
     
     
    // Fonction DeleteComment()
    /* Fonctin pour effacer les commentaires après une ligne
       ----------------------------------------------------- */
    void DeleteComment(
     char * const szLigne	//[in/out] Chaine à épurer
     )
    {
    /* This function deletes the char '!' and all the char after it of
    the string line_.
    This function deletes also all the spaces befor the char '!' and
    NOT the last char of line_ which isn't a space
    */
    assert( !IsCommentLine(szLigne) );
     
    char * const szExclam = strchr(szLigne, '!');
     
    if(szExclam != NULL)
    	{
    	/* d is the index of string line_ which contains the char '!'
    	Remark : the first index is 0
    	*/
    	size_t iExclam = szExclam - szLigne;
    	size_t i;
    	//Le commentaire n'est pas supposé commencer à zéro
    	//(ni les espaces qui le précèdent)
    	assert(iExclam > 0);
    	for(i = iExclam-1 ; isspace(szLigne[i]) ; --i);
     
    	assert(i > 0);
     
    	//Tronque la chaîne juste après le dernier caractère non-espace
    	//(ce caractère est garanti exister:
    	//la chaîne ne commence PAS par un commentaire)
    	szLigne[i+1] = '\0';
    	}
    }
     
     
    // Fonction DeleteCharEndOfLine()
    /* Fonction pour supprimer le caractère de fin de ligne
       ---------------------------------------------------- */
    void DeleteCharEndOfLine(
     char * const szLigne,	//[in/out] Chaine à épurer
     NUMLIGNE const nNblignes,	//[in] Nombre Total de lignes
     NUMLIGNE const nNumligne	//[in] N° de ligne
     )
    {
    char * const szLF = strchr(szLigne, '\n');
     
    if(szLF != NULL)
    	{
    	//le \n a été trouvé
    	*szLF = '\0';
    	}
    /* Only the last line is allowed to pass without a LineFeed character */
    else if(nNumligne != nNblignes)
    	{
    	/* tabular is too short. Exit program */
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : tabular line_ is too short\n"
    	  "Increase its size\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__
    	 );
    	exit(1);
    	}
    }
     
     
    /* Fonction LoadInitialInputs()
       ---------------------------- */
    void LoadInitialInputs(
     char const * const sczInputFile,	//[in] Nom du fichier d'entrée
     NUMBEROFDATAS * const pt_N,	//[out] Recoit le nombre de données
     Tableau ** const pt_pt_tabTemp,	//[out] tableau temp
     Tableau ** const pt_pt_tabPres,	//[out] tableau pres
     Tableau ** const pt_pt_tabRichesse,	//[out] tableau richesse
     Tableau ** const pt_pt_tabEGR,	//[out] tableau EGR
     double * const pt_dRpm	//[out] recoit rpm
     )
    {
    /*
    input_file est le nom du fichier contenant les input
    N est le nombre de particules
    temp est un tableau contenant les temperatures initiales de chaque particule
    pres est un tableau contenant les pressions initiales de chaque particule
    richesse est un tableau contenant la richesse initiale de chaque particule
    EGR est un tableau contenant le taux d'EGR (en %) de chaque particule
    */
     
    // --- Première passe ---
    /* opening of the file in reading mode */
    FILE * file = fopen(sczInputFile,"r");
    if(file == NULL)
    	{
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : file %s wasn't found\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__,
    	 sczInputFile
    	 );
    	exit(1);
    	}
     
    int i;
     
    /* definition of a table of char intended to receive the line */
    char szLigne[10000];
     
    /* on compte le nombre de lignes du fichier d'entrees */
    NUMLIGNE nNbLignes=0;
    for( ; fgets(szLigne, sizeof szLigne, file) != NULL ; ++nNbLignes);
     
    if(ferror(file))
    	{
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : a misreading occurred in file %s\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__,
    	 sczInputFile
    	 );
    	exit(1);
    	}
    fclose(file);
     
    // --- Seconde passe ---
    file = fopen(sczInputFile,"r");
    NUMLIGNE nNumLigne=0;
     
    do	{
    	char * const szResultatFgets = fgets(szLigne, sizeof szLigne, file);
    	++nNumLigne;
    	if(szResultatFgets==NULL && feof(file))
    		{
    		fprintf(
    		 stderr,
    		 "Error in file %s line %d in function %s : key word TEMP wasn't found in file %s\n"
    		  "Exit program\n",
    		 __FILE__,
    		 __LINE__,
    		 __FUNCTION__,
    		 sczInputFile
    		 );
    		exit(1);
    		}
    	} while(strstr(szLigne, "TEMP ") == NULL || IsCommentLine(szLigne));
     
    fclose(file);
     
    DeleteCharEndOfLine( szLigne, nNbLignes, nNumLigne);
    DeleteComment(szLigne);
     
    *pt_N = GetPurifiedNumberOfSpaces(szLigne);
     
    /* creation des tableaux */
     
    //On commence par s'arrurer qu'il n'existent pas
    FreeTableau(*pt_pt_tabTemp);
    *pt_pt_tabTemp = NULL;
    FreeTableau(*pt_pt_tabPres);
    *pt_pt_tabPres = NULL;
    FreeTableau(*pt_pt_tabRichesse);
    *pt_pt_tabRichesse = NULL;
    FreeTableau(*pt_pt_tabEGR);
    *pt_pt_tabEGR = NULL;
     
    *pt_pt_tabTemp = AllocTableau(*pt_N, 0.0);
    *pt_pt_tabPres = AllocTableau(*pt_N, 0.0);
    *pt_pt_tabRichesse = AllocTableau(*pt_N, 0.0);
    *pt_pt_tabEGR = AllocTableau(*pt_N, 0.0);
     
    /* initialisation des tableaux */
     
    // --- Troisième passe ---
    file = fopen(sczInputFile,"r");
     
    char szKeyword[50]; /* tableau stockant le mot cle */
    nNumLigne = 0; /* line counteur */
     
    while(fgets(szLigne, sizeof szLigne, file) != NULL)
    	{
    	++nNumLigne;
     
    	/* si strlen(line_)==2 alors cela veut dire que la ligne est une ligne "blanche" et que line_='\n'
    	   il vaut mieux utiliser le test strlen(line_)!=2 plutot que le test strcmp(line_,"\n") car suivant
    	   le cas ou le fichier input_file a ete ecrit sous windows ou unix, le format des retours chariot n'est
    	   pas le meme, ce qui peut etre cause d'erreur du prgm
    	   cf <a href="http://emmanuel-delahaye.developpez.com/notes.htm" target="_blank">http://emmanuel-delahaye.developpez.com/notes.htm</a>
    	*/
    	if( (!IsCommentLine(szLigne)) && (strlen(szLigne)!=2) )
    		{
    		DeleteCharEndOfLine(szLigne, nNbLignes, nNumLigne);
    		DeleteComment(szLigne);
     
    		if(strstr(szLigne, "TEMP ") != NULL)
    			{
    			ReadLineWithDouble(szLigne, *pt_pt_tabTemp);
    			for(i=0 ; i<*pt_N ; ++i)
    				assert((*pt_pt_tabTemp)->ptc_data[i] > 0.0);
    			}
    		else if(strstr(szLigne, "PRES ") != NULL)
    			{
    			NUMBEROFDATAS const nDatas = GetPurifiedNumberOfSpaces(szLigne);
    			assert(nDatas==*pt_N);
    			ReadLineWithDouble(szLigne, *pt_pt_tabPres);
    			for(i=0 ; i<*pt_N ; ++i)
    				assert((*pt_pt_tabPres)->ptc_data[i] > 0.0);
    			}
    		else if(strstr(szLigne, "RICHESSE ") != NULL)
    			{
    			NUMBEROFDATAS const nDatas = GetPurifiedNumberOfSpaces(szLigne);
    			assert(nDatas==*pt_N);
    			ReadLineWithDouble(szLigne, *pt_pt_tabRichesse);
    			for(i=0 ; i<*pt_N ; ++i)
    				assert((*pt_pt_tabRichesse)->ptc_data[i] > 0.0);
    			}
    		else if(strstr(szLigne, "EGR ") != NULL)
    			{
    			NUMBEROFDATAS const nDatas = GetPurifiedNumberOfSpaces(szLigne);
    			assert(nDatas==*pt_N);
    			ReadLineWithDouble(szLigne, *pt_pt_tabEGR);
    			for(i=0 ; i<*pt_N ; ++i)
    			    {
                    (*pt_pt_tabEGR)->pt_data[i] /= 100.0;
    				assert((*pt_pt_tabEGR)->pt_data[i] >= 0.0);
    				}
    			}
    		else if(strstr(szLigne, "RPM ") != NULL)
    			{
    			NUMBEROFDATAS const nDatas = GetPurifiedNumberOfSpaces(szLigne);
    			assert(nDatas == 1);
    			/* ***ATTENTION***
    			Risque de dépassement de capacité de keyword
    			 */
    			sscanf(szLigne, "%50s%lf", szKeyword, pt_dRpm);
    			szKeyword[50-1] = '\0';
    			assert(*pt_dRpm > 0.0);
    			}
    		else
    			{
    			fprintf(
    			 stderr,
    			 "Error in file %s line %d in function %s : none keyword was found in file %s at line %s\n"
    			  "Exit program\n",
    			 __FILE__,
    			 __LINE__,
    			 __FUNCTION__,
    			 sczInputFile,
    			 szLigne
    			 );
    			exit(1);
    			}
    		} /* end of if( (!IsCommentLine(line_)) && strcmp(line_,"\n") ) */
    	} /* end of while */
     
    if(!feof(file))
    	{
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : a misreading occurred in file %s\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__,
    	 sczInputFile
    	 );
    	exit(1);
    	}
     
    if(ferror(file))
    	{
    	fprintf(
    	 stderr,
    	 "Error in file %s line %d in function %s : a misreading occurred in file %s\n"
    	  "Exit program\n",
    	 __FILE__,
    	 __LINE__,
    	 __FUNCTION__,
    	 sczInputFile
    	 );
    	exit(1);
    	}
     
    fclose(file);
    }
    Je ne sais pas si ça marche, mais c'est supposé corriger pas mal d'erreurs...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    salut, je ne sais plus où me mettre. Merci bcp ! Je pense que j'ai pas mal à méditer sur toutes tes corrections.
    Encore merci !!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 14/01/2010, 18h11
  2. Réponses: 165
    Dernier message: 03/09/2009, 15h35
  3. Crypter ou obfusquer les String dans les .class
    Par Luke58 dans le forum Langage
    Réponses: 12
    Dernier message: 14/08/2009, 11h24
  4. Sale problème avec les strings et les fichiers
    Par acieroid dans le forum C++
    Réponses: 18
    Dernier message: 26/04/2006, 09h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo