fgetc

fgetc - C - Programmation

Marsh Posté le 25-09-2005 à 23:23:36    

Bonjour @ tous!!
Bon voila je dois faire un programme utilisant l'algo d'huffman(j'ai vu qu'il y avait un precedent sur le forum).Je rappel la 1er etape: determiner le nombre d'apparition de chaque caracteres d'une phrase, sauf que j'ai un fichier.txt en entré et je dois m'occuper que ds minuscule et du caractere espace. Mais voila j'ai un gros doute quand a mon utilisation de la fonction fgetc mais je ne vois pas comment faire sinon, donc si vous pouviez y jeter un oeil ainsi qu'au reste svp... merci d'avance
 

Code :
  1. #include<stdio.h>
  2. struct noeud{
  3.     char lettre;
  4.     int frequence;
  5. }tab[27];
  6. // fontion permettant de savoir combien de fois apparaitra un caractere dans un fichier//
  7. int occurence(int value){ /*value est de type entier car en fait plus bas*/
  8.                                    /*je mets value=fgetc mais je ne sais pas*/
  9.    for(i=0;i<27;i++){        /*si il arrivera a faire le test dans mon if*/
  10.        if(value==tab[i].lettre)
  11.           tab[i].frequence=tab[i].frequence+1;
  12.        return 1;
  13.    }
  14. }
  15. //fontion pour traiter le fichier rentré en parametre//
  16. int lecture (char *fichier){
  17.      FILE *fp;
  18.      int value;
  19.      if((fp=fopen(fichier,"r" ))==NULL){
  20.         printf("erreur lors de l ouverture du fichier\n" );
  21.         return 0;
  22.      }
  23.      while(!feof(fp)){
  24.          value=fgetc(fp);
  25.          occurence(value);
  26.      }
  27.      fclose(fp);
  28.      return 1;
  29. }
  30. main(){
  31.  
  32.    int i;
  33.  
  34.    for(i=0;i<27;i++){     //initialisation de mon tableau de structure//
  35.       if(i==0)
  36.           tab[i].lettre='a';
  37.        else{
  38.           if(i==26)
  39.              tab[i].lettre=' ';
  40.           else
  41.              tab[i].lettre=tab[i-1].lettre+1;
  42.        }
  43.       tab[i].frequence=0;
  44.    }
  45.  
  46.    lecture(mon_amour.txt);
  47. }


 
PS:c'est mon 1er post et je plante quand j appui sur aperçu donc je sais pas comment ca va apparaitre...
PPS:j'espere que ce sera mieu..

Message cité 2 fois
Message édité par Zaroastre le 25-09-2005 à 23:39:46
Reply

Marsh Posté le 25-09-2005 à 23:23:36   

Reply

Marsh Posté le 25-09-2005 à 23:25:30    

oula dsl je vois que j'ai mal posté dsl...j essaye de refaire

Reply

Marsh Posté le 25-09-2005 à 23:55:31    

Zaroastre a écrit :

Bonjour @ tous!!
Bon voila je dois faire un programme utilisant l'algo d'huffman(j'ai vu qu'il y avait un precedent sur le forum).Je rappel la 1er etape: determiner le nombre d'apparition de chaque caracteres d'une phrase, sauf que j'ai un fichier.txt en entré et je dois m'occuper que ds minuscule et du caractere espace. Mais voila j'ai un gros doute quand a mon utilisation de la fonction fgetc mais je ne vois pas comment faire sinon, donc si vous pouviez y jeter un oeil ainsi qu'au reste svp... merci d'avance


int lecture (char *fichier){
 
     FILE *fp;
     int value;
 
     if((fp=fopen(fichier,"r" ))==NULL){
        printf("erreur lors de l ouverture du fichier\n" );
        return 0;
     }
     while(!feof(fp)){
         value=fgetc(fp);
         occurence(value);
     }
     fclose(fp);
     return 1;
}



J'écris ça comme ça :  


static int lecture (char const *fichier)
{
   FILE *fp = fopen (fichier, "r" );
 
   if (fp != NULL)
   {
      int value;
 
      while ((value = fgetc (fp)) != EOF)
      {
         occurence (value);
      }
      fclose (fp);
   }
   else
   {
      perror (fichier);
   }
   return 1;
}


Détails ici:  
 
http://mapage.noos.fr/emdel/notes.htm#fichiers


---------------
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/
Reply

Marsh Posté le 26-09-2005 à 00:08:08    

oki merci beaucoup pour la simplification et la page je pense que ca m'aidera beaucoup pour la suite...on nous a fait faire du C de fevrier a fin avril et la en 2ieme anné on en fait pas en cour mais on nous donne ce genre de tp..  :(  Mais bon je pense que c'est tout de meme benefique je fait des recherche et j'en apprend plus...par exemple le "static" devant la fonction je vais chercher lool :)

Reply

Marsh Posté le 26-09-2005 à 14:55:02    

Zaroastre a écrit :

oki merci beaucoup pour la simplification et la page je pense que ca m'aidera beaucoup pour la suite...on nous a fait faire du C de fevrier a fin avril et la en 2ieme anné on en fait pas en cour mais on nous donne ce genre de tp..  :(  Mais bon je pense que c'est tout de meme benefique je fait des recherche et j'en apprend plus...par exemple le "static" devant la fonction je vais chercher lool :)


 
Tu devrais mieux lire la correction d'Emmanuel. Le détail crucial de sa correction n'est pas le mot "static" mis devant la fonction (comme ton post le laisse penser) mais dans la manière dont on teste qu'on est arrivé en fin de fichier. Il ne faut absolument pas utiliser "feof" car cette fonction ne sert pas à ça. Elle sert juste à indiquer si la dernière lecture à échouée à cause de "eof". Pour vérifier qu'on est en fin de fichier, on teste la valeur renvoyée par la fonction de lecture. En fin de fichier, cette valeur vaut "EOF".
 
Le mot "static" devant une fonction permet de restreindre la fonction au source dans lequel elle est écrite. Dans le cadre d'un grand projet avec plusieurs sources, tu peux ainsi réutiliser, pour de petites fonctions utilitaires, le même nom pour tes fonctions dans différents sources. Tu peux alors avoir des fonctions intitulées "lecture" dans chacun de tes sources sans qu'il y ait ambigüité lors de l'édition de lien.

Reply

Marsh Posté le 27-09-2005 à 03:19:43    

Merci Sve@r , en fait quand j'ai lu le post d'Emmanuel je croyai que mon code etait bon mais qu'il me proposai une facon plus simple (voir plus optimal) de coder...je te remercie pour ta reponse sans quoi j'aurai continué a croire que " while(!feof(fp)) " etait correct...et merci a Emmanuel pour la correction de mon code ^^

Reply

Marsh Posté le 27-09-2005 à 08:43:16    

Zaroastre a écrit :

je te remercie pour ta reponse sans quoi j'aurai continué a croire que " while(!feof(fp)) " etait correct...


Pourtant, je t'avais passé un lien  

Citation :


Détails ici:  
 
http://mapage.noos.fr/emdel/notes.htm#fichiers  


expliquant exactement le rôle de feof().  
Tu ne l'as pas vu/lu ?  
Tu ne l'as pas compris ?


Message édité par Emmanuel Delahaye le 27-09-2005 à 08:44:42

---------------
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/
Reply

Marsh Posté le 27-09-2005 à 11:43:52    

Zaroastre a écrit :

for(i=0;i<27;i++){     //initialisation de mon tableau de structure//
     if(i==0)
          tab[i].lettre='a';
       else{
          if(i==26)
             tab[i].lettre=' ';
          else
             tab[i].lettre=tab[i-1].lettre+1;
       }
      tab[i].frequence=0;
   }

Algorithmiquement, c'est un peu horrible de faire une boucle de 0 à 26 et de tester, à chaque tour de boucle, si on est à 0 ou à 26. Il vaut mieux traiter les cas "0" et "26" avant la boucle et boucler de 1 à 25...
 
Sinon, on peut aussi se servir du fait que 'a' est un nombre et l'utiliser tel quel

Code :
  1. //initialisation de mon tableau de structure
  2. for(i=0;i<26;i++)
  3. {
  4.     tab[i].lettre='a' + i;
  5.     tab[i].frequence=0;
  6. }
  7. tab[26].lettre=' ';
  8. tab[26].frequence=0;


 

Zaroastre a écrit :

lecture(mon_amour.txt);

Tu veux plutôt dire

Code :
  1. lecture("mon_amour.txt" );


 
Dernier truc... un commentaire en C c'est soit "/*.......*/" soit "// ......." mais ceci "// ...... //" ne sert à rien...

Reply

Marsh Posté le 28-09-2005 à 03:04:23    

erf...nan je comprend pas, quand on fait: "if(feof(fp))" ca fait un test pour savoir si on est a la fin du fichier pourquoi quand je fait: "while(!feof(fp))" ca marche pas? pour moi ca ve dire tant que "feof" ne m'a pas renvoyé la valeur de fin de fichier alors... c'est pour ca que je comprend pas...
Merci je vous remerci d'avoir corrigé mon code(que je pensai plus ou moins bon a tort...), faut dire que je me concentre sur la creation de l arbre et la c'est beaucoup plus compliqué...a propos si j'ai un tableau te taille fini (dans mon cas 27) si a chaque boucle je veux suprimer la 1er case c'est possible? ou vaut mieux que j'opte pour une liste chainé?
Petite question...est ce que je peux utiliser la fonction "free" si je n'ai jamais utilisé de fonction (du genre malloc) avant dans mon programme et si oui est ce que je peux l'utiliser sur une case d'un tableau (je suppose qu'il faudra créer avant un pointeur de type struct noeud sur mon tableau, et ensuite free(pointeur) ca marche?)
Merci d'avance ++ ;)

Reply

Marsh Posté le 28-09-2005 à 05:53:50    

ok ok !! vu que je patoge dans mon programme cela ma laissé du temps pour lire d'autre sujet et notament celui ou on fait reference aux constructeur/destructeur,et cela m'interesse malheuresement j'ai pas tout compris :$
 

Code :
  1. struct objet * objet_create (void)
  2. {
  3.    struct objet * self = malloc (sizeof *self);
  4.    if (self != NULL)
  5.    {
  6.       /* initialisation a 0 */
  7.       static const struct objet z = {0};
  8.       *self = z;
  9.       /* ajouter ici les eventuels complements...
  10.        * - Autre initialisations
  11.        * - Creation d'objets imbriques etc.
  12.        */
  13.    }
  14.    return self;
  15. }


 
je vois que la fonction return "self" qui est un pointeur de type struct objet, mais si tu place cette fonction dans une boucle je comprend pas ce qui se passe?? quand tu va repasse dans la fonction ca va recreer une struct mais qui aura le meme non que la precedente??y aura conflit? erf je suis perdu, aidez moi s'il vous plait, je pense utiliser ceci dans mon programme (puisque je vais devoir creer des noeud) mais si je le comprend pas c'est pas la peine...
Merci d'avance...

Reply

Marsh Posté le 28-09-2005 à 05:53:50   

Reply

Marsh Posté le 28-09-2005 à 06:18:46    

autre chose, pour le destructeur a la fin ya

Code :
  1. free(self);


 
si j'ai bien compris il est preferable de mettre

Code :
  1. free(self),self=NULL;


 
exact?

Reply

Marsh Posté le 28-09-2005 à 09:00:42    

Zaroastre a écrit :

autre chose, pour le destructeur a la fin ya

Code :
  1. free(self);


si j'ai bien compris il est preferable de mettre

Code :
  1. free(self),self=NULL;


exact?


Oui. Ca ne résout pas tous les problèmes (notamment celui des alias, qu'il faut éviter au maximum), mais au moins, le pointeur 'principal' se retrouve dans le bon état.
 
En fait, puisque tu faisais référence au code du destruteur de l'objet, le fait de forcer le pointeur a NULL après le free() n'a qu'un intérêt local (donc limité, mais peut aider à débugger des objets complexes).
 
Par contre, cette mesure trouve son sens dans le cadre de l'utilisation réelle de l'objet :  


{
   /* creation de l'objet... */
   struct object *p = object_create();
 
   if (p != NULL)
   {
 
      /* utilisation de l'objet... */
 
      /* suppression de l'objet... */
      object_delete (p), p = NULL;
   }
 
   /* Controle de conception. <assert.h> */
   assert (p == NULL);
}


(C'est d'ailleurs quasiment mot pour mot ce qui est indiqué un peu plus loin dans l'article sur les TAD (ADT))
http://mapage.noos.fr/emdel/tad.htm


Message édité par Emmanuel Delahaye le 28-09-2005 à 09:36:18

---------------
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/
Reply

Marsh Posté le 28-09-2005 à 09:11:34    

Zaroastre a écrit :

erf...nan je comprend pas, quand on fait: "if(feof(fp))" ca fait un test pour savoir si on est a la fin du fichier


Qui t'a dit ça ? feof() sert à déterminer si la cause de l'arrêt de la lecture (detectée au préalable en testant le code retourné par la fonction de lecture) est une fin de fichier ou non, de même que ferror() sert à savoir si la cause est une erreur de lecture ou non. Ce genre de détail est rarement important.
 
http://mapage.noos.fr/emdel/notes.htm#fichiers

Citation :


je me concentre sur la creation de l arbre et la c'est beaucoup plus compliqué...a propos si j'ai un tableau te taille fini (dans mon cas 27) si a chaque boucle je veux suprimer la 1er case c'est possible? ou vaut mieux que j'opte pour une liste chainé?


On ne peut pas 'supprimer' une case dans un tableau. On peut événtuellement  la marquer 'vide', soit par une valeur particulière, soit par un état particulier (tableau de structure). Sinon, une liste chainée, oui, pourquoi pas. C'est peut être un peu lourd... A moins que tu disposes d'une bibliothèque de liste chainées génériques... (Moi, je m'en suis fait une... http://mapage.noos.fr/emdel/clib.htm Module GLL )

Citation :


Petite question...est ce que je peux utiliser la fonction "free" si je n'ai jamais utilisé de fonction (du genre malloc) avant dans mon programme


Non. (seul free (NULL) n'est pas dangereux).


---------------
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/
Reply

Marsh Posté le 28-09-2005 à 09:19:32    

Zaroastre a écrit :

ok ok !! vu que je patauge dans mon programme cela ma laissé du temps pour lire d'autre sujet et notament celui ou on fait reference aux constructeur/destructeur,et cela m'interesse malheuresement j'ai pas tout compris :$

Code :
  1. struct objet * objet_create (void)
  2. {
  3.    struct objet * self = malloc (sizeof *self);
  4.    if (self != NULL)
  5.    {
  6.       /* initialisation a 0 */
  7.       static const struct objet z = {0};
  8.       *self = z;
  9.       /* ajouter ici les eventuels complements...
  10.        * - Autre initialisations
  11.        * - Creation d'objets imbriques etc.
  12.        */
  13.    }
  14.    return self;
  15. }


je vois que la fonction return "self" qui est un pointeur de type struct objet, mais si tu place cette fonction dans une boucle je comprend pas ce qui se passe??


Boucle ? Tu veux dire si on appelle plusieurs fois la fonction ? C'est simple. Chaque appel faisant un malloc(), un nouveau bloc est crée, et une nouvelle adresse est retournée. A l'appelant de bien sauvegarder les adresses dans des pointeurs différents.


struct objet * pa = objet_create ();
struct objet * pb = objet_create ();


Citation :


quand tu va repasse dans la fonction ca va recreer une struct mais qui aura le meme non que la precedente??


Tu vois un nom quelque part ? Je ne vois qu'une variable locale 'self' qui contient une valeur (l'adresse du bloc alloué). Cette valeur est retournée à l'appelant qui a en charge de la sauvegarder proprement. (Je me répète ou quoi ?)

Citation :

je pense utiliser ceci dans mon programme (puisque je vais devoir creer des noeud)


Bonne idée. Fait des essais avant d'intégrer le principe dans ton code. Comme toujours, chaque technique nouvelle doit être assimilée et maitrisée avant d'être utilisée.


Message édité par Emmanuel Delahaye le 28-09-2005 à 09:20:32

---------------
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/
Reply

Marsh Posté le 28-09-2005 à 09:23:18    

Zaroastre a écrit :

ok ok !! vu que je patoge dans mon programme cela ma laissé du temps pour lire d'autre sujet et notament celui ou on fait reference aux constructeur/destructeur,et cela m'interesse malheuresement j'ai pas tout compris :$
 

Code :
  1. struct objet * objet_create (void)
  2. {
  3.    struct objet * self = malloc (sizeof *self);
  4.    if (self != NULL)
  5.    {
  6.       /* initialisation a 0 */
  7.       static const struct objet z = {0};
  8.       *self = z;
  9.       /* ajouter ici les eventuels complements...
  10.        * - Autre initialisations
  11.        * - Creation d'objets imbriques etc.
  12.        */
  13.    }
  14.    return self;
  15. }


 
je vois que la fonction return "self" qui est un pointeur de type struct objet, mais si tu place cette fonction dans une boucle je comprend pas ce qui se passe?? quand tu va repasse dans la fonction ca va recreer une struct mais qui aura le meme non que la precedente??y aura conflit? erf je suis perdu, aidez moi s'il vous plait, je pense utiliser ceci dans mon programme (puisque je vais devoir creer des noeud) mais si je le comprend pas c'est pas la peine...
Merci d'avance...


Chaque fois que ton programme utilise "malloc", il alloue une nouvelle zone mémoire qui a donc une adresse différente de la précédente. Le nom importe peu.
 
Donc tu peux utiliser ta fonction "objet_create" autant de fois que tu veux, même dans une boucle, l'important est la valeur renvoyée soit récupée dans des mémoires différentes, par exemple un tableau ou un noeud différent.
 
Ex:

Code :
  1. struct objet *tabObjet[10];          // un tableau de 10 "struct objet*"
  2. int i;
  3. for (i=0; i < 10; i++)
  4.     tabObjet[i]=objet_create();      // Chaque adresse allouée est stockée dans un élément du tableau


 

Reply

Marsh Posté le 01-10-2005 à 18:10:45    

re @ tous!! j'avais pris une pause, en effet le prof nous a donné 2 semaine de plus pour realiser ce programme (plutot logique vu le niveau de la classe), du coup je vais pouvoir prendre mon temps et me pencher sur des nouvelle notion, merci pour vos post ;)
++

Reply

Marsh Posté le 02-10-2005 à 20:02:12    

Salut!!ben malheuresement je me retrouve de nouveau bloqué et cela en prenant mon temp...Le probleme cette fois ci est au niveau de la fonction "free" la compilation est nikel mais a l execution (en fait a la toute fin du programme) ben il me sort que free a foiré (cependant le prog marche mais bon ...). Bon le probleme c'est que mon code est assez long donc je vais ecrire ce qui me semble important pour resoudre le probleme(j'espere :$)
 

Code :
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int compt=0;
  4. struct noeud{
  5.   char lettre;
  6.   int frequence;
  7.   struct noeud *suivant;
  8.   struct noeud *droite;
  9.   struct noeud *gauche;
  10. }*tab;
  11. //il y a normalement 2 fonction (qui marche ^^) qui parcour le fichier et rempli le champs "requence" de mon tableau "tab"
  12. //redimension et tri du tableau de structure
  13. void redim_et_tri(struct noeud *t,int *p){
  14.   //tri a bulle ordre decroissant
  15.     int i=0,j,bool=1;
  16.     struct noeud temp;
  17.     while(bool){
  18.       bool=0;
  19.       for(j=222;j>=i+1;j--){
  20. if (tab[j-1].frequence<tab[j].frequence){
  21.   temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  22.   bool=1;
  23. }
  24.       }
  25.       i=i+1;
  26.     }
  27.     //parcours du tableau a fin de savoir combien d element ont une frequence non nul
  28.     i=0;
  29.     while((tab[i].frequence)!=0){
  30.       compt=compt+1;
  31.       i=i+1;
  32.     }
  33.    
  34.     //redimentionnement du tableau, d ou le tri decroissant pour eliminer toute les case ek frequence 0
  35.     tab=(struct noeud*)realloc(tab,sizeof(compt));  //surement l origine du probleme
  36.     //tri a bule par ordre croissant cette fois-ci et alphabetique
  37.     i=0;
  38.     bool=1;
  39.     while(bool){
  40.       bool=0;
  41.       for(j=compt-1;j>=i+1;j--){
  42. if (tab[j-1].frequence>tab[j].frequence){   //tri par frequence
  43.   temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  44.   bool=1;
  45. }else{
  46.   if(tab[j-1].frequence==tab[j].frequence){ //si frequence egale tri
  47.     if(tab[j-1].lettre>tab[j].lettre){      //tri par lettre
  48.       temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  49.       bool=1;
  50.     }
  51.   }
  52. }
  53.       }
  54.       i=i+1;
  55.     }
  56. }
  57. main(){
  58.  
  59.   typedef struct noeud noeud;
  60.   int i;
  61.  
  62.   //j alloue de l espace memoire a mon tableau pour le redimensionner par la suite en enlevant tout les element ayant 0 pour frequence
  63.  
  64.   tab=(noeud*)calloc(223,sizeof(noeud)); //calloc initialise tout les champs a 0 y compris frequence
  65.   for(i=0;i<223;i++){
  66.     tab[i].lettre=' '+i;
  67.     tab[i].frequence=0;
  68.   }
  69.  
  70.  
  71.   lecture("mon_amour.txt" );
  72.  
  73.   redim_et_tri(tab,&compt);
  74.      
  75.   free(tab),tab=NULL;
  76. }


 
PS: g du declarer "compt" juste aprés l appel des bibliotheques car quand je le declaré dans le "main" il traite pas comme si c'etait une variable global :(  pourtant toute les fonction sont appelé dans le main...g pas tous compris, je pensais que declarer dans "main" c'etait dire que la variable etait une variable global


Message édité par Zaroastre le 02-10-2005 à 20:11:03
Reply

Marsh Posté le 02-10-2005 à 20:17:59    

erf autre chose svp
est ce que calloc (dans mon main) va initialiser les champs contenant des pointeur??ou dois je les initialiser et est ce que c'est important d initialiser a NULL...
De plus comme vous pouvez le constater dans les fonction avant le main j'ai du ecrire "struc noeud" malgré le typedef dans le main...gje doit egalement mettre mon typedef aprés la creation de ma struture(hors du main...)?
merci d'avance car je demande beaucoup de chose...dsl...

Reply

Marsh Posté le 02-10-2005 à 20:25:13    

Oh la la  [:kzimir]  
 
Ton programme est illisible, je ne sais pas par où commencer pour t'aider.
 
Je serais toi, je créerais un nouveau programme, dans lequel je ne m'occuperais que d'allouer un nouveau tableau, l'initialiser avec n'importe quoi (mettons le n° de la case), je l'afficherais, et ensuite je m'occuperais des free().
Commence par ça, déjà. Ensuite seulement occupe-toi de la saisie, puis enfin du tri.
 
Parce que là, vraiment, j'en perds mon latin. :/
 
 

Citation :


g du declarer "compt" juste aprés l appel des bibliotheques car quand je le declaré dans le "main" il traite pas comme si c'etait une variable global :(


 
Une variable déclarée dans le main() n'est pas globale. Quand tu passes ta variable compt à ta fonction, c'est le nom de la variable déclaré dans le prototype de la fonction qu'il faut utiliser, non pas le nom employé dans le main.
 
Exemple :
 

void afficher_entier(int i)
{
   printf("Un entier : %d\\n", i);
}
 
int main(void)
{
   int entier = 10;
 
   afficher_entier(entier);
 
   return 0;
}


Message édité par Elmoricq le 02-10-2005 à 20:26:15
Reply

Marsh Posté le 02-10-2005 à 20:33:33    

Zaroastre a écrit :

est ce que calloc (dans mon main) va initialiser les champs contenant des pointeur??ou dois je les initialiser et est ce que c'est important d initialiser a NULL...


 
Il faut voir ta structure comme un bloc en mémoire d'un seul tenant, délimité en variables.
La fonction calloc() alloue une zone mémoire et l'initialise entièrement à 0, ce qui signifie qu'entiers, flottants, pointeurs, caractères, ... contiennent 0 après un calloc().
 
Et pour un pointeur, zéro équivaut à NULL.
 

Zaroastre a écrit :

De plus comme vous pouvez le constater dans les fonction avant le main j'ai du ecrire "struc noeud" malgré le typedef dans le main...gje doit egalement mettre mon typedef aprés la creation de ma struture(hors du main...)?


 
Ton typedef n'est valable que pour tout ce qui suit cette ligne, ta fonction la précédant, elle n'est pas applicable.
 
A propos de typedef, essaie de choisir des noms de structure plus parlants.
Par exemple :
 

typedef struct noeud {
  char lettre;
  int frequence;
  struct noeud *suivant;
  struct noeud *droite;
  struct noeud *gauche;
} noeud, *pnoeud;

Reply

Marsh Posté le 02-10-2005 à 20:44:24    

Zaroastre a écrit :

est ce que calloc (dans mon main) va initialiser les champs contenant des pointeur??


calloc() va mettre tous les bits à 0 (comme le ferait memset() avec 0). Ce n'est pas forcément la représentation correcte de NULL. Pour être portable (indépendant de l'implémentation), il vaut donc mieux le faire explicitement avec ... = NULL;

Citation :

ou dois je les initialiser et est ce que c'est important d initialiser a NULL...


Oui et oui.

Citation :


De plus comme vous pouvez le constater dans les fonction avant le main j'ai du ecrire "struc noeud" malgré le typedef dans le main...gje doit egalement mettre mon typedef aprés la creation de ma struture(hors du main...)?
merci d'avance car je demande beaucoup de chose...dsl...


Le vrai problème, c'est que tu te lances dans des choses compliquées (Huffman, c'est pas trivial...) alors que tu connais à peine les bases du C que toi seul peut apprendre et expérimenter...


Message édité par Emmanuel Delahaye le 02-10-2005 à 22:36:57

---------------
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/
Reply

Marsh Posté le 02-10-2005 à 20:49:50    

Elmoricq a écrit :

La fonction calloc() alloue une zone mémoire et l'initialise entièrement à 0, ce qui signifie qu'entiers, flottants, pointeurs, caractères, ... contiennent 0 après un calloc().
 
Et pour un pointeur, zéro équivaut à NULL.


Le problème est que calloc() ne met pas la valeur 0 dans un contexte pointeur comme le ferait un brave

char *p = 0;


ou

struct
{
   char *p;
}
s = {0};


mais qu'il travaille à bas niveau en mettant tous les bits à zéro :

memset (s, sizeof s, 0);


ce qui produit un résultat non défini sauf pour les unsigned char.
 
 


---------------
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/
Reply

Marsh Posté le 02-10-2005 à 21:57:32    

Emmanuel Delahaye a écrit :

Le problème est que calloc() ne met pas la valeur 0 dans un contexte pointeur [...] mais qu'il travaille à bas niveau en mettant tous les bits à zéro


 
Tout à fait.  :jap:  
 

Emmanuel Delahaye a écrit :

ce qui produit un résultat non défini sauf pour les unsigned char.


 
Tu veux dire qu'après un calloc(), tester un pointeur par rapport à NULL pourrait ne pas donner le résultat escompté ?  
[:totoz]  
 
J'ai beau y réfléchir, je ne comprends pas pourquoi.  
Je veux dire... quelle différence entre faire un memset() et assigner (void*)0 à un pointeur ?  :??:  
A moins que ce ne soit indéfini par la norme, en prévision de cas particuliers ?
 
Ca me fait peur, ton histoire.

Message cité 1 fois
Message édité par Elmoricq le 02-10-2005 à 22:00:55
Reply

Marsh Posté le 02-10-2005 à 22:11:15    

Bon je vais essayé d etre plus clair :
 
1)je declare une structure que j appel noeud

Code :
  1. struct noeud{
  2.   char lettre;
  3.   int frequence;
  4.   struct noeud *suivant;
  5.   struct noeud *droite;
  6.   struct noeud *gauche;
  7. };


 
2)dans mon "main" je declare un pointeur de type structure noeud

Code :
  1. struct noeud *tab;


 
3)je veux un tableau contenant les caractere ASCII a partir du caractere "espace" c'est dire 223 cases(au dela ya rien d'interressant) d ou :

Code :
  1. tab=(noeud*)calloc(223,sizeof(noeud));
  2. for(i=0;i<223;i++){
  3.     tab[i].lettre=' '+i;
  4.     tab[i].frequence=0;
  5. //apperement je vais devoir initialiser egalement les pointeurs donc "tab[i]->suivant..." (pas sur pour la syntaxe dite moi svp)


 
4)je parcour un fichier caractere par caractere je regarde ou il est dans mon tableau "tab" et rajoute+1 a la frequence, je n affiche pas mes fonction elles sont bonnes
 
5)j'ai fini de lire mon fichier ,le tableau "tab" est donc mis a jour, le probleme c'est qu'il ya des lettre qui ont pour frequence 0 et ca je n en veux pas donc je lance un tri par ordre decroissant des frequences

Code :
  1. int i=0,j,bool=1;
  2.     struct noeud temp;
  3.     while(bool){
  4.       bool=0;
  5.       for(j=222;j>=i+1;j--){
  6. if (tab[j-1].frequence<tab[j].frequence){
  7.   temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  8.   bool=1;
  9. }
  10.       }
  11.       i=i+1;
  12.     }


 
6) les n premiere cases de mon tableau ont une frequence non nul determinons ce "n"(n=compt)

Code :
  1. i=0;
  2.     while((tab[i].frequence)!=0){
  3.       compt=compt+1;
  4.       i=i+1;
  5.     }


 
7) maintenant je veux redimensionner mon tableau de facon a garder que les lettre ayant une frequence non nul

Code :
  1. tab=(struct noeud*)realloc(tab,sizeof(compt));


 
8)pour la suite de l exercice je tri par ordre croissant des frequences et alphabetique si les frequ sont egal

Code :
  1. i=0;
  2.     bool=1;
  3.     while(bool){
  4.       bool=0;
  5.       for(j=compt-1;j>=i+1;j--){
  6. if (tab[j-1].frequence>tab[j].frequence){   //tri par frequence
  7.   temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  8.   bool=1;
  9. }else{
  10.   if(tab[j-1].frequence==tab[j].frequence){ //si frequence egale tri
  11.     if(tab[j-1].lettre>tab[j].lettre){      //tri par lettre
  12.       temp=tab[j-1];tab[j-1]=tab[j];tab[j]=temp;
  13.       bool=1;
  14.     }
  15.   }
  16. }
  17.       }
  18.       i=i+1;
  19.     }


 
8)j ai un tableau trié par odre croissant, disons que mon prog s arrete la ,je libere la memoire alloué a "tab"

Code :
  1. free(tab),tab=NULL;


 
Probleme:
la compilation se fait sans probleme(apparent), lors de l execution tout marche (j'ai mis des printf un peu partout pour voir) mais a la toute fin a la ligne du "free" j'ai un truc du genre:
***gclib*** free pointeur size fast : "un adresse"
 
le truc c'est que si j enleve la ligne avec mon realloc la liberation du pointeur ce fait sans prob donc si quelqu'un a une explication c'est volontier, sachant que mon but est d enlever les cases ou la frequence est nul qu"est ce que je dois faire...
merci d avance...(j espere que c'est plus comprehensible :sweat: )

Reply

Marsh Posté le 02-10-2005 à 22:25:41    

Elmoricq a écrit :


Tu veux dire qu'après un calloc(), tester un pointeur par rapport à NULL pourrait ne pas donner le résultat escompté ?  
J'ai beau y réfléchir, je ne comprends pas pourquoi.  
Je veux dire... quelle différence entre faire un memset() et assigner (void*)0 à un pointeur ?  :??:  
A moins que ce ne soit indéfini par la norme, en prévision de cas particuliers ?


Oui. Sujet trois mille fois débatu sur news:comp.lang.c et news:fr.comp.lang.c ... Le principe est simple. La représentatiion interne des données n'est pas forcément ce qu'on croit. Il y a un niveau d'abstraction qui fait que quand on écrit :

char *p = NULL;


le compilateur voit que p est un pointeur, et qu'on demande de l'affecter avec la valeur 0. Selon la machine, il va positionner les bits de p de façon à former la combinaison qui, sur cette machine, signifie 'adresse invalide'. Ca peut être tout à 0, mais aussi 0x80000000, 0x5555AAAA ou 0xDEADBEEF, qui sait... Ca dépent de l'implémentation, et le langage C ne définit pas ça.
 
Donc si on veut être portable, on ne demande pas au couches de bas niveau de mettre les bits à 0, mais on utilise l'affectation ou l'initialisation.
 
Le même problème existe avec le flottants.  
 
Concernant les types entiers, le langage C (C99) prévoit la possibilité de 'Trap representation', c'est à dire des combinaisons de bits qui signifient 'valeur erronée'. Encore une fois, si on ne connait pas ces détails d'implémentation et qu'on se permet de positionner les bits 'à la main', il peut arriver n'importe quoi.


---------------
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/
Reply

Marsh Posté le 02-10-2005 à 22:33:58    

Zaroastre a écrit :

3)je veux un tableau contenant les caractere ASCII a partir du caractere "espace" c'est dire 223 cases(au dela ya rien d'interressant) d ou :

Code :
  1. tab=(noeud*)calloc(223,sizeof(noeud));
  2. for(i=0;i<223;i++){
  3.     tab.lettre=' '+i;
  4.     tab[i].frequence=0;
  5. //apperement je vais devoir initialiser egalement les pointeurs donc "tab\[i\]->suivant..." (pas sur pour la syntaxe dite moi svp)



 
Si tu initialises le contenu de chaque élément de ta structure, calloc() n'a aucune valeur ajoutée par rapport à malloc(), autant utiliser ce dernier.
 
Dans les deux cas (calloc() ou malloc() ), le cast est inutile, retire-le pour alléger l'écriture.
 
Et pour initialiser "suivant", par exemple, c'est avec :

tab[i].suivant


(la notation "->" est un raccourci, voir un cours pour comprendre comment ça fonctionne)
 
Ah, et avant que je n'oublie : toujours tester le retour des fonctions d'allocation de mémoire.
 

Citation :


4)je parcour un fichier caractere par caractere je regarde ou il est dans mon tableau "tab" et rajoute+1 a la frequence, je n affiche pas mes fonction elles sont bonnes


 
Je ne sais pas si ce morceau de ta phrase reflète la réalité mais si c'est le cas, ta fonction est probablement plus compliquée qu'elle ne devrait.
 

Citation :

6) les n premiere cases de mon tableau ont une frequence non nul determinons ce "n"(n=compt)

Code :
  1. i=0;
  2.     while((tab[i].frequence)!=0){
  3.       compt=compt+1;
  4.       i=i+1;
  5.     }



 
[i]compt ne devrait pas être une variable globale. Les cas où les globales sont réellement utiles ne sont pas très courants (et doivent être maniés avec précaution).
 
 

Citation :

7) maintenant je veux redimensionner mon tableau de facon a garder que les lettre ayant une frequence non nul

Code :
  1. tab=(struct noeud*)realloc(tab,sizeof(compt));



 
Ouh la. Tu demandes à ton programme de réallouer tab pour qu'il fasse la taille d'un... int.
 
En plus realloc() ne s'utilise pas ainsi ; si cette fonction échoue, elle retourne NULL alors que le pointeur d'origine reste valide.
De la manière dont tu l'utilises, tu as un bout de mémoire qui se balade dans la nature après l'appel à cette fonction, si elle échoue. Sans compter le fait que tu ne testes pas que tout se passe sans problème, alors que ce n'est peut-être pas le cas.
 
En plus je ne vois pas l'utilité de modifier la taille du tableau, puisque ta variable compt contient le nombre de cases significatives, les autres pouvant être ignorées.
 
 

Citation :

Probleme:


 
Le problème est que tu veux aller trop vite en besogne, tu utilises des fonctions non triviales alors que tu ne maîtrises pas les bases.
 
Vas-y plus progressivement, parce que là tu cours à la catastrophe.


Message édité par Elmoricq le 02-10-2005 à 22:36:56
Reply

Marsh Posté le 02-10-2005 à 22:35:54    

Emmanuel Delahaye a écrit :

Oui. Sujet trois mille fois débatu sur news:comp.lang.c et news:fr.comp.lang.c ... Le principe est simple. La représentatiion interne des données n'est pas forcément ce qu'on croit. Il y a un niveau d'abstraction qui fait que [...] selon la machine, il va positionner les bits de p de façon à former la combinaison qui, sur cette machine, signifie 'adresse invalide'. Ca peut être tout à 0, mais aussi 0x80000000, 0x5555AAAA ou 0xDEADBEEF, qui sait... Ca dépent de l'implémentation, et le langage C ne définit pas ça.


 
 [:totoz]  
 
Je vais devoir faire le tour de mes programmes alors. J'utilise rarement calloc(), mais quand je le fais, c'est justement dans l'optique du "d'une pierre deux coups".  :sweat:
 
EDIT : si je suis ce raisonnement, tester un pointeur avec : "if ( !pointeur )" est piégeux, alors ?

Message cité 1 fois
Message édité par Elmoricq le 02-10-2005 à 22:41:21
Reply

Marsh Posté le 02-10-2005 à 22:45:55    

Elmoricq a écrit :

[:totoz]  
 
Je vais devoir faire le tour de mes programmes alors. J'utilise rarement calloc(), mais quand je le fais, c'est justement dans l'optique du "d'une pierre deux coups".  :sweat:


Oui, ça m'a fait pareil. Mais c'est vrai qu'il est rare d'utiliser calloc()...

Citation :

EDIT : si je suis ce raisonnement, tester un pointeur avec : "if ( !pointeur )" est piégeux, alors ?


Non, car on est dans un 'contexte pointeur'. L'interprétation de 'pointeur != 0' est faite par le compilateur.


---------------
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/
Reply

Marsh Posté le 02-10-2005 à 23:17:23    

bon tant pis je vais pas me prendre la tete je vais faire un programme bien lourd, plutot que de redimmensionner un tableau je vais en créer d autre qui donnerons ce que je veux...
A propos des mes bases, tu a surement raison mais la fac nous a appris les bases du C en 3 mois (en 1er année) c'est a dire qu'il ne sont jamais allé au fond des choses (ex: "malloc":fonction qui...blablabla + 1 exo bidon dessus et voila). Maintenant en 2ieme anné on fait pas de cour de C (c'est censé etre connu) et on nous balance des TP a remmetre,la huffman et encore c'est que le 1er je sais pas ce qui viendra aprés, voila je fais ce que je peux avec ce que l'on m'a donné, j'ai validé mon info de 1er anné donc on peut meme pas dire que j ai fais l impasse sur les cours...
Bref ce qui est vrai c'est que j'aime bien l info et un programme ecrit simplement sans se preocuper de l optimisation ben ca me gene(je dis pas que mon programme est optimisé, je dis juste qu'il est optimisé pour moi, il va de soit qu'une personne ayant plus de connaissance l optimisera encore plus) tout ca pour dire qu'il est vrai que j'utilise des notions que je ne maitrise pas totalement...
Bon je vais faire un programme basic qui marche et aprés je me pencherai dessus pour essayer de modifier des ligne de codes
merci @ tous ++

Reply

Marsh Posté le 02-10-2005 à 23:27:46    

Citation :

Bref ce qui est vrai c'est que j'aime bien l info et un programme ecrit simplement sans se preocuper de l optimisation ben ca me gene(je dis pas que mon programme est optimisé, je dis juste qu'il est optimisé pour moi, il va de soit qu'une personne ayant plus de connaissance l optimisera encore plus)


 
Mais ton programme ne fonctionne pas, et il est difficilement compréhensible, pourquoi veux-tu "l'optimiser" ?  
As-tu des besoins spécifiques pour une plateforme aux performances restreintes ? Est-il anormalement lent, ou constates-tu qu'il consomme trop de mémoire ?
Avant d'optimiser, il faut d'abord que le programme fonctionne, et je pense que tu devrais pour l'instant t'en tenir à cet unique objectif.
 
Sinon je ne saurais trop te conseiller le livre "Le Langage C", de Kernighan & Ritchie. Ainsi que les nombreux tutoriaux sur le net, comme le site d'Emmanuel qu'il t'a déjà mis en lien, sur ce topic même, et que tu n'as manifestement pas pris la peine de lire.
Ce n'est pas une critique, c'est une constatation. [:spamafote]
 
Un autre truc sympa, c'est "man le_nom_d'une_fonction", soit en commande sur un unixoïde, soit dans Google ça marche aussi, tu auras plein de détails sur une fonction particulière.

Reply

Marsh Posté le 02-10-2005 à 23:32:04    

Zaroastre a écrit :

A propos des mes bases, tu a surement raison mais la fac nous a appris les bases du C en 3 mois (en 1er année) c'est a dire qu'il ne sont jamais allé au fond des choses (ex: "malloc":fonction qui...blablabla + 1 exo bidon dessus et voila).


Le principe de la fac c'est de donner quelques clés de base. Ensuite, c'est 200% de travail personnel. Si il n'a jamais été fait, tu te retrouves devant une montagne de difficultés. Il faut 6 mois à un an de pratique quotidienne pour [auto]former correctement un programmeur C... Et je suppose que tu avais d'autres choses à faire en plus... Mais ne compte pas sur les forums pour résoudre tous tes problèmes...

Citation :


Maintenant en 2ieme anné on fait pas de cour de C (c'est censé etre connu)  


CQFD. L'école c'est fini. Il faut prendre des initiatives d'auto-formation. Personne ne peut le faire à ta place...

Citation :


et on nous balance des TP a remmetre,la huffman et encore c'est que le 1er je sais pas ce qui viendra aprés, voila je fais ce que je peux avec ce que l'on m'a donné,  


C'est là qu'on est censés pleurer sur ton sort ?

Citation :


j'ai validé mon info de 1er anné donc on peut meme pas dire que j ai fais l impasse sur les cours...


Insuffisant. Il manque énormément de travail personnel. L'informatique c'est un truc de passioné. Un vrai geek ne dord pas. Il programme. Il n'a pas de femme, mais une console. Pas d'amis, mais internet etc. Je caricature un peu (à peine...), mais au début, c'est un peu ça. Ensuite ça se tasse...

Citation :


Bref ce qui est vrai c'est que j'aime bien l info et un programme ecrit simplement sans se preocuper de l optimisation ben ca me gene(je dis pas que mon programme est optimisé, je dis juste qu'il est optimisé pour moi, il va de soit qu'une personne ayant plus de connaissance l optimisera encore plus) tout ca pour dire qu'il est vrai que j'utilise des notions que je ne maitrise pas totalement...
Bon je vais faire un programme basic qui marche et aprés je me pencherai dessus pour essayer de modifier des ligne de codes


Bonne démarche. Mais vas-y pas à pas et n'aborde pas une notion nouvelle tant que tu ne maîtrises pas la notion courante. (pédagogie élémentaire, mais pas évidente pour tout le monde...)
 


---------------
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/
Reply

Marsh Posté le 03-10-2005 à 00:00:49    

Si je demande de l aide c'est parce que ce que le prog que j'ai affiché aujourd'hui aussi etonnant que cela puisse vous paraitre il marche!! c'est juste que je n'arrive pas a regler le probleme de mon "free" a la fin de l execution ,si j'etais cochon j'aurai laissé le truc tel qu'elle mais c'est pas le cas d'ou ma requete
Autre chose, j'ai demandé a personne de pleurer sur mon sort, et je n 'ai pas non plus debarqué en disant "quelqu'un peut me donner la solution du codage d huffman?", derniere chose travail personnel ou pas pour ma part je trouvai les TD de 1er anné bidon (c'etait pas le cas de tous le monde) et je dis juste qu'il y a eu un manque de continuiter entre la 1er et 2ime anné quand je fais reference a huffman, le prof s'en est d ailleur rendu compte puisqu'il nous a donné 2 semaine de plus pour faire ce TP et en nous disans que finalement c'est vrai que ce TP n est pas facile et qu'il permettra d'approfondir des notions de 1er année (sous entend que l'on ne l'ai maitrise pas)
merci @++

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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