Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1408 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Trier un fichier en C

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Trier un fichier en C

n°1288050
Gattuso
Posté le 20-01-2006 à 08:46:01  profilanswer
 

Bonjour,
 
le code suivant devrait (ce que j'èspère) lire le fichier "lire" et écrire dans le fichier "ecrire" les lignes du fichier précédent trié mais il ne fait pas cela.
 
Si vous pouviez m'aider.
 
Merci d'avance
 
Mon fichier lire est le suivant:

Code :
  1. un
  2. deux
  3. trois
  4. quatre
  5. cinq


 
Dans le fichier ecrire,j'obtiens ceci :

Code :
  1. deux
  2. trois
  3. quatre
  4. cinq


qui n'est pas trié et il manque le "un"
 
Voici le code que j'ai écrit:

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int tri(FILE *flotLecture, FILE *flotEcriture,
  5. int(*cmp)(const char *s1, const char *s2))
  6. {
  7.   char ligne1[15];
  8.   char ligne2[15];
  9.  
  10.   if(flotLecture == NULL)
  11.     return 1;
  12.  
  13.   if(flotEcriture == NULL)
  14.     return 1;
  15.  
  16.   while(fgets(ligne1, sizeof ligne1, flotLecture) != NULL)
  17.     while(fgets(ligne2, sizeof ligne2, flotLecture) != NULL)
  18.       {
  19. char *tmp1;
  20. if((*cmp)(ligne1,ligne2) > 0)
  21.   {
  22.     char buf[BUFSIZ];
  23.     strcpy(buf,ligne1);
  24.    
  25.     tmp1  = malloc(strlen(ligne2)+1);
  26.     if(tmp1 == NULL)
  27.       return 1;
  28.     strcpy(tmp1,ligne2);
  29.    
  30.     char *tmp2 = malloc(strlen(buf)+1);
  31.     if(tmp2 == NULL)
  32.       return 1;
  33.     strcpy(tmp2,buf);
  34.   }
  35. fprintf(flotEcriture,"%s",tmp1);
  36.       }
  37.   return 0;
  38. }
  39. int main()
  40. {
  41.   FILE *lecture = fopen("lire","r" );
  42.   FILE *ecriture = fopen("ecrire","w" );
  43.   if(tri(lecture,ecriture,&strcmp))
  44.     {
  45.       fprintf(stderr,"erreur \n" );
  46.     }
  47.  
  48.   return 0;
  49. }


Message édité par Gattuso le 21-01-2006 à 06:51:43
mood
Publicité
Posté le 20-01-2006 à 08:46:01  profilanswer
 

n°1288138
olivthill
Posté le 20-01-2006 à 10:49:59  profilanswer
 

Problèmes principaux :
 
1. Une fois arrivé à la fin du fichier, il faut repartir plus haut (rembobiner) pour que l'algorithme choisi marche. Donc pour cela, il faut utiliser fseek (et ftell) ou bien fermer et réouvrir le fichier.
 
2. tmp2 n'est pas utilisé. Seul tmp1 est inscrit dans le fichier
 
3. Au lieu de compare ligne1 et ligne2, il faudrait comparer la meilleure ligne trouvée et ligne2, donc pour le premier enregistrement mettre ligne1 dans tmp1, ou inversement tmp1 dans ligne1.
 
Problèmes secondaires :
 
1. Ouverture de fichier sans fermeture
La fermeture permet de vider les buffers.
La fermeture est faite automatiquement à la fin, mais ce n'est pas une bonne habitude de ne pas la faire.
 
2. Allocation de mémoire sans libération
La libération est faite automatiquement à la fin, mais ce n'est pas une bonne habitude de ne pas la faire.
 
3. Allocation incohérente du tas et de la pile
Si l'on sait qu'une ligne a une longueur maximale de 15 caractères, alors, il est bien de faire char ligne1[15];, mais tmp1  = malloc(strlen(ligne2)+1); pourrait être avantageusement remplacé par char tmp1[15]; car malloc prend beaucoup de resource CPU et de ressource mémoire. L'utilisation de la pile pour des petites (moins de 2000 caractères) chaines est presque toujours préférable à l'utilisation du tas par un malloc(). Malloc() doit être utilisé avec parcimonie.
 
4. Choisir des noms plus parlant
Par exemple, au lieu de tmp1, choisir meilleur_ligne_trouvee

n°1288825
Gattuso
Posté le 21-01-2006 à 11:35:15  profilanswer
 

Bonjour,
 
j'aurais besoin d'aide car je n'obtiens pas de fichier trié  
 
 
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int tri(FILE *flotLecture, FILE *flotEcriture,
  5. int(*cmp)(const char *s1, const char *s2))
  6. {
  7.   char ligne1[15];
  8.   char ligne2[15];
  9.  
  10.   if(flotLecture == NULL)
  11.     return 1;
  12.  
  13.   if(flotEcriture == NULL)
  14.     return 1;
  15.  
  16.   long courant;
  17.   while(fgets(ligne1, sizeof ligne1, flotLecture) != NULL)
  18.     {
  19.       courant = ftell(flotLecture);
  20.      
  21.       while(fgets(ligne2, sizeof ligne2, flotLecture) != NULL)
  22. {
  23.   if((*cmp)(ligne1,ligne2) > 0)
  24.     {
  25.       char buf[BUFSIZ];
  26.      
  27.       strcpy(buf,ligne1);
  28.      
  29.       char *tmp1 = malloc(strlen(ligne2)+1);
  30.       if(tmp1 == NULL)
  31.  return 1;
  32.       strcpy(tmp1,ligne2);
  33.      
  34.       char *tmp2 = malloc(strlen(buf)+1);
  35.       if(tmp2 == NULL)
  36.  return 1;
  37.       strcpy(tmp2,buf);
  38.      
  39.       fprintf(flotEcriture,"%s",tmp1);
  40.       free(tmp1);
  41.       free(tmp2);
  42.      
  43.     }
  44.  
  45. }
  46.      
  47.       fseek(flotLecture,courant,SEEK_CUR);
  48.      
  49.     }
  50.  
  51.   fclose(flotEcriture);
  52.   fclose(flotLecture);
  53.  
  54.   return 0;
  55. }
  56. int main(int argc, char *argv[])
  57. {
  58.   FILE *lecture = fopen("lire","r" );
  59.   FILE *ecriture = fopen("ecrire","w" );
  60.  
  61.   if(tri(lecture,ecriture,&strcmp))
  62.     {
  63.       fprintf(stderr,"erreur \n" );
  64.     }
  65.  
  66.   return EXIT_SUCCESS;
  67. }

Message cité 1 fois
Message édité par Gattuso le 21-01-2006 à 11:36:23
n°1288859
Sve@r
Posté le 21-01-2006 à 12:41:05  profilanswer
 

Gattuso a écrit :

Bonjour,
 
j'aurais besoin d'aide car je n'obtiens pas de fichier trié  
 
 
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int tri(FILE *flotLecture, FILE *flotEcriture,
  5. int(*cmp)(const char *s1, const char *s2))
  6. {
  7.   char ligne1[15];
  8.   char ligne2[15];
  9.  
  10.   if(flotLecture == NULL)
  11.     return 1;
  12.  
  13.   if(flotEcriture == NULL)
  14.     return 1;
  15.  
  16.   long courant;
  17.   while(fgets(ligne1, sizeof ligne1, flotLecture) != NULL)
  18.     {
  19.       courant = ftell(flotLecture);
  20.      
  21.       while(fgets(ligne2, sizeof ligne2, flotLecture) != NULL)
  22. {
  23.   if((*cmp)(ligne1,ligne2) > 0)
  24.     {
  25.       char buf[BUFSIZ];
  26.      
  27.       strcpy(buf,ligne1);
  28.      
  29.       char *tmp1 = malloc(strlen(ligne2)+1);
  30.       if(tmp1 == NULL)
  31.  return 1;
  32.       strcpy(tmp1,ligne2);
  33.      
  34.       char *tmp2 = malloc(strlen(buf)+1);
  35.       if(tmp2 == NULL)
  36.  return 1;
  37.       strcpy(tmp2,buf);
  38.      
  39.       fprintf(flotEcriture,"%s",tmp1);
  40.       free(tmp1);
  41.       free(tmp2);
  42.      
  43.     }
  44.  
  45. }
  46.      
  47.       fseek(flotLecture,courant,SEEK_CUR);
  48.      
  49.     }
  50.  
  51.   fclose(flotEcriture);
  52.   fclose(flotLecture);
  53.  
  54.   return 0;
  55. }
  56. int main(int argc, char *argv[])
  57. {
  58.   FILE *lecture = fopen("lire","r" );
  59.   FILE *ecriture = fopen("ecrire","w" );
  60.  
  61.   if(tri(lecture,ecriture,&strcmp))
  62.     {
  63.       fprintf(stderr,"erreur \n" );
  64.     }
  65.  
  66.   return EXIT_SUCCESS;
  67. }



 
Sincèrement, j'ai pas envie de réfléchir sur l'algo parce que je suis en WE. Donc je te donne juste des réflexions très générales que je remarque juste en première lecture
1) ça sert à rien que la fonction teste les flots car c'est un appel inutile (empilement, dépilement, etc). Vaut mieux tester les flots dans le main et n'appeler la fonction que s'ils sont corrects
2) penser à fermer les fichiers dans le main
3) le malloc est un peu inutile puisque la zone ne dépassera pas 15 car. Autant déclarer de suite tmp1 et tmp2 comme des tableaux de 15 octets. Mais si tu tiens quand-même au malloc, alors faut le faire bien. C'est à dire que si tmp2 n'a pas pu être alloué, faut libérer tmp1 avant de quitter la fonction.
4) je vois pas trop à quoi sert "buf"... mais je ne vois aucune définition de "BUFSIZ" => je m'étonne que ça compile chez toi
5) le pointeur sur "strcmp" est inutile... sauf si tu veux t'entrainer à utiliser des pointeurs de fonction. Dans ce cas, le code est correctement écrit
6) on déclare toutes les variables avant la première instruction du bloc => la déclaration "long courant" est mise après les instructions "if" et la déclaration "char *tmp2" est mise après les instructions "if(...)" et "strcpy(...)" => je m'étonne encore plus que ça compile chez toi (sauf si tu compiles en C++)
7) de façon conventionnelle, une fonction en erreur est plus sensée renvoyer "-1" que "1". Mais c'est vraiment du détail et ça n'influe en rien sur l'algo.
 
Sinon, comme j'ai pas envie de réfléchir sur l'algo en lui-même, la seule solution qu'il te reste est de prendre un papier et un crayon et de dérouler l'algo à la main. Comme ton fichier ne fait que 5 lignes, ça devrait pas être trop long...

Message cité 2 fois
Message édité par Sve@r le 21-01-2006 à 12:42:55

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1288872
Gattuso
Posté le 21-01-2006 à 13:09:13  profilanswer
 

Sve@r a écrit :

Sincèrement, j'ai pas envie de réfléchir sur l'algo parce que je suis en WE. Donc je te donne juste des réflexions très générales que je remarque juste en première lecture
1) ça sert à rien que la fonction teste les flots car c'est un appel inutile (empilement, dépilement, etc). Vaut mieux tester les flots dans le main et n'appeler la fonction que s'ils sont corrects
2) penser à fermer les fichiers dans le main
3) le malloc est un peu inutile puisque la zone ne dépassera pas 15 car. Autant déclarer de suite tmp1 et tmp2 comme des tableaux de 15 octets. Mais si tu tiens quand-même au malloc, alors faut le faire bien. C'est à dire que si tmp2 n'a pas pu être alloué, faut libérer tmp1 avant de quitter la fonction.
4) je vois pas trop à quoi sert "buf"... mais je ne vois aucune définition de "BUFSIZ" => je m'étonne que ça compile chez toi
5) le pointeur sur "strcmp" est inutile... sauf si tu veux t'entrainer à utiliser des pointeurs de fonction. Dans ce cas, le code est correctement écrit
6) on déclare toutes les variables avant la première instruction du bloc => la déclaration "long courant" est mise après les instructions "if" et la déclaration "char *tmp2" est mise après les instructions "if(...)" et "strcpy(...)" => je m'étonne encore plus que ça compile chez toi (sauf si tu compiles en C++)
7) de façon conventionnelle, une fonction en erreur est plus sensée renvoyer "-1" que "1". Mais c'est vraiment du détail et ça n'influe en rien sur l'algo.
 
Sinon, comme j'ai pas envie de réfléchir sur l'algo en lui-même, la seule solution qu'il te reste est de prendre un papier et un crayon et de dérouler l'algo à la main. Comme ton fichier ne fait que 5 lignes, ça devrait pas être trop long...


Merci pour toutes ces remarques.
 
J'ai réécrit le code maintenant ça me fait le tri mais pour un seul élémént.
En partant de ce fichier "lire"

Code :
  1. un
  2. deux
  3. trois
  4. quatre
  5. cinq


 
j'obtiens dans "ecrire"

Code :
  1. cinq


 
Ce qui est bien le plus petit mot mais je ne comprends pas pourquoi la boucle ne continue pas alors que j'utilises fseek et ftell pour redémarrer les boucles.
 
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int tri(FILE *flotLecture, FILE *flotEcriture,
  5. int(*cmp)(const char *s1, const char *s2))
  6. {
  7.   char ligne1[15];
  8.   char ligne2[15];
  9.   char *tmp;
  10.   long courant;
  11.  
  12.   while(fgets(ligne1, sizeof ligne1, flotLecture) != NULL)
  13.     {
  14.       courant = ftell(flotLecture);
  15.      
  16.       while(fgets(ligne2, sizeof ligne2, flotLecture) != NULL)
  17. {
  18.   if((*cmp)(ligne1,ligne2) > 0)
  19.     {
  20.      
  21.       tmp = malloc(strlen(ligne2)+1);
  22.       if(tmp == NULL)
  23.  return 1;
  24.       strcpy(tmp,ligne2);
  25.      
  26.     }
  27.  
  28. }
  29.       fprintf(flotEcriture,"%s",tmp);
  30.      
  31.       fseek(flotLecture,courant,SEEK_CUR);
  32.      
  33.     }
  34.  
  35.   return 0;
  36. }
  37. int main(int argc, char *argv[])
  38. {
  39.   FILE *lecture = fopen("lire","r" );
  40.   FILE *ecriture = fopen("ecrire","w" );
  41.  
  42.   if(lecture == NULL)
  43.     return EXIT_FAILURE;
  44.  
  45.   if(ecriture == NULL)
  46.     return EXIT_FAILURE;
  47.  
  48.   if(tri(lecture,ecriture,&strcmp))
  49.     {
  50.       fprintf(stderr,"erreur \n" );
  51.       return EXIT_FAILURE;
  52.     }
  53.  
  54.   fclose(ecriture);
  55.   fclose(lecture);
  56.  
  57.   return EXIT_SUCCESS;
  58. }


n°1288903
Emmanuel D​elahaye
C is a sharp tool
Posté le 21-01-2006 à 14:04:11  profilanswer
 

Sve@r a écrit :

mais je ne vois aucune définition de "BUFSIZ" => je m'étonne que ça compile chez toi


C'est une constante standard définie dans <stdio.h>.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1288942
Sve@r
Posté le 21-01-2006 à 15:14:56  profilanswer
 

Emmanuel Delahaye a écrit :

C'est une constante standard définie dans <stdio.h>.


Ah ben merci. Au moins j'ai appris qqchose... il reste plus qu'à régler les 6 autres points... et puis à dérouler l'algo à la main. Ca devrait pas trop être difficile... mais comme je l'ai dit j'ai déconnecté le brain pour ce WE.  :)


Message édité par Sve@r le 21-01-2006 à 15:15:16

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

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Trier un fichier en C

 

Sujets relatifs
Afficher le contenu d'un fichier texte sur une page WEB ?Comment inclure une font dans un fichier resource ?
Problèmes d'écriture dans un fichier : fichier videEcriture dans un fichier
[css] imposer une police avec le fichier *.ttfC et pas C++, lire et écrire dans un fichier
[Résolu][C# & XML] Valider un fichier xml selon un schémaRenommer un fichier avec la date du jour
[RESOLU] Rechercer & remplacer dans un fichierCrée un fichier d'aide type .chm
Plus de sujets relatifs à : Trier un fichier en C


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR