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 :

Fonctions,structures,lecture de fichier


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut Fonctions,structures,lecture de fichier
    Salut à tous,

    Voila j'ai partiel bientôt je m’entraîne à refaire mes TD cependant j'ai pas la correction donc je vais poster ici mes réponses afin que vous puissiez me corriger et m'aider si possible (c'est pas très compliqué .. juste j'ai du mal )

    Merci.

    Je code en C.

    Exercice 1 : Carnet d'adresses. On souhaite écrire un programme qui puisse gérer un carnet d'adresses.


    1. Définir la structure fiche_t d'une personne qui contient :

    - Un nom, un prénom (chaînes de caractères dont la longueur n'est pas définie)
    - Une année de naissance, un code postal (entiers)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct fiche_s{
     char *nom;
     char *prenom;
     int annee;
     int cp;
    };
    typedef struct fiche_s fiche_t;
    2. Ecrire la fonction ficher_creer qui prend en entrée un nom, un prénom, une année de naissance et un code postal et renvoie un pointeur sur une structure fiche_t.

    Rappel :
    - la fonction int strlen(const char* s) ; prend en entrée une chaînes de caractères et renvoie la longueur.
    - la fonction void strcpy(char * dest,char * src); copie la chaîne de caractères pointée par src à l'adresse pointée par dest.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    fiche_t * fiche_creer(char *nom, char *prenom, int annee, int cp)
    {
       fiche_t *res = (fiche_t*)malloc(sizeof(fiche_t));
       res -> nom = (char *) malloc((strlen(nom) + 1) * sizeof(char));
       res -> prenom = (char *) malloc((strlen(prenom) + 1) * sizeof(char));
       res -> annee = annee;
       res -> cp = cp;
       return res;
    }
    3. Ecrire la fonction fiche_detruire qui prend en entrée un pointeur sur une fiche_t et libère la mémoire allouée dans un fiche_creer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void fiche_detruire(fiche_t *fiche)
    {
          fiche_t *res =(fiche_t*) malloc(sizeof(fiche_t));
          free(res);
          return;
    }
    4. Ecrire la fonction fiche_cmp qui prend entrée deux structures fiche_t et renvoie 1 si les noms, prenoms et années de naissance sont les mêmes; et 0 sinon.

    Rappel :
    - La fonction int strcmp(char * s1, char* s2) renvoie 0 si les deux chaines de caractères s1 et s2 sont identiques.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1.nom, s2.nom) == 0)
          return 1;
       return 0;
       if (strcmp(s1.prenom, s2.prenom) == 0)
          return 1;
       return 0;
    }
    5. Ecrire la fonction fiche_affiche qui prend en entrée une structure fiche_t et affiche son contenu.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    void fiche_affiche (fiche_t f)
    {
       printf("Nom : %s\n", f.n);
       printf("Prenom : %s\n", f.p);
       printf("Année de naissance : %d\n", f.annee);
       printf("Code Postal : %d\n", f.cp);
    }

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Salut,

    Puisque c'est un exercice est le but est que tu apprennes, je ne te donnerai pas de réponses complètes pour le moment, juste des éléments pour te faire réfléchir

    1) Nomme tes variables complètement, ça ne coûte rien ! p --> prenom, n --> nom, etc.
    Je ne vois pas de chaines de caractères moi.... Je vois juste deux fois 1 caractère.

    2) Je ne vois pas deux chaines de caractères en paramètre de cette fonction. Voir 1), c'est lié. Tu ne respectes même pas le prototype donné par le prof !!!
    Pour faire ce que tu fais, il existe une fonction appelée strdup(). D'un point de vue apprentissage, mieux vaut comprendre le malloc() (avec le +1 pour le terminateur de chaine ) et qu'on copie ensuite la chaine d'origine dans la chaine de destination. Oh tiens d'ailleurs, la copie ? Encore une fois, on en parle dans la consigne :o

    3) Allez, soyons fous ! free() alors que ce ne sont pas des pointeurs :o Pourquoi faire un while ? Et surtout, quand fiche est-il mis à NULL ?

    4) strcmp() ne compare pas des structures mais des chaines de caractères....

    Au boulot :p

  3. #3
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Djiinw Voir le message
    Je code en C.

    Exercice 1 : Carnet d'adresses. On souhaite écrire un programme qui puisse gérer un carnet d'adresses.


    1. Définir la structure fiche_t d'une personne qui contient :

    - Un nom, un prénom (chaînes de caractères dont la longueur n'est pas définie)
    - Une année de naissance, un code postal (entiers)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct fiche_s{
     char n;
     char p;
     int annee;
     int cp;
    };
    typedef struct fiche_s fiche_t;
    Une chaîne de caractère dont la longueur n'est pas définie a priori est implémentée en C avec un tableau de caractères. Une variable de type char ne peut contenir qu'un seul objet de type char (tout comme un int ne contient qu'un seul entier) : tes champs n et p n'ont donc pas le bon type et ont un nom peu précis. Tu aurais pu les appeler nom et prenom pour les rendre plus explicites.
    Donc pour une chaîne de longueur non prédéfinie il te faut un pointeur sur le premier caractère -> char *, il faudra allouer dynamiquement suffisamment de place (le nombre de caractères de ta chaîne + 1 pour le \0 terminal) et ne pas oublier de libérer cet espace quand tu n'en auras plus besoin.



    Citation Envoyé par Djiinw Voir le message
    2. Ecrire la fonction ficher_creer qui prend en entrée un nom, un prénom, une année de naissance et un code postal et renvoie un pointeur sur une structure fiche_t.

    Rappel :
    - la fonction int strlen(const char* s) ; prend en entrée une chaînes de caractères et renvoie la longueur.
    - la fonction void strcpy(char * dest,char * src); copie la chaîne de caractères pointée par src à l'adresse pointée par dest.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    fiche_t * fiche_creer(char n, char p, int annee, int cp)
    {
       fiche_t *res = (fiche_t*)malloc(sizeof(fiche_t));
       res -> n = (char *) malloc((strlen(n) + 1) * sizeof(char));
       res -> p = (char *) malloc((strlen(p) + 1) * sizeof(char));
       res -> annee = annee;
       res -> cp = cp;
       return res;
    }
    Même remarque que précédemment (pas de char mais char * pour les chaines en C).
    Ensuite tu alloues le mémoire (-> c'est bien), mais à moins que ton professeur ne t'y oblige, il n'est pas nécessaire de caster le retour du malloc. Allouer c'est bien .... mais il faut aussi copier les chaines que tu as en paramètres dans tla structure que tu viens d'allouer, on te donne une indication pour savoir quelle fonction utiliser ...
    À noter : l'allocation (le malloc) peut échouer, il faut toujours vérifier que malloc ne renvoie pas NULL, auquel cas il faut gérer l'erreur (en général un message d'erreur qui signale qu'il n'y a pas assez de mémoire disponibles et arrêter le programme).


    Citation Envoyé par Djiinw Voir le message
    3. Ecrire la fonction fiche_detruire qui prend en entrée un pointeur sur une fiche_t et libère la mémoire allouée dans un fiche_creer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    void fiche_detruire(fiche_t *fiche)
    {
       While ( *fiche != NULL)
        {
          fiche_t *res = *fiche;
          free(res->n);
          free(res->p);
          free(res->annee);
          free(res->cp);
          free(res);
        }
          return res;
    }
    Alors une règle d'or : pour chaque malloc tu feras toujours un free et un seul.
    Tu as alloué quoi que ce soit pour res->annee ??? id. res->cp ??? sont-ce seulement des pointeurs ???

    Une autre règle d'or : C est un langage qui est sensible à la casse
    While c'est pas un mot clé de C, contrairement à while ...

    Une fonction dont le type de retour est void ne retourne rien. Tu essayes de renvoyer une valeur, pourquoi ?
    Une variable possède un scope, ici entre autre la variable res n'existe que dans le bloc while et pas en dehors ... c'était juste une remarque général. Limiter le scope est bien. Utiliser en dehors du scope est mal


    Citation Envoyé par Djiinw Voir le message
    4. Ecrire la fonction fiche_cmp qui prend entrée deux structures fiche_t et renvoie 1 si les noms, prenoms et années de naissance sont les mêmes; et 0 sinon.

    Rappel :
    - La fonction int strcmp(char * s1, char* s2) renvoie 0 si les deux chaines de caractères s1 et s2 sont identiques.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1, s2) == 0)
          return 1;
       return 0; 
    }
    Là c'est vraiment pas bon ... on te rappelle que strcmp sert à comparer des chaines et tu lui donne des fiche_t en pramètre ... il y a comme une grosse incompréhension ...

    Ce que tu aurais du faire est comparer les deux fiches champ à champ ... utilise strcmp sur les nom et prénoms, une simple égalité sur les entiers ...

    Citation Envoyé par Djiinw Voir le message
    5. Ecrire la fonction fiche_affiche qui prend en entrée une structure fiche_t et affiche son contenu.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    void fiche_affiche (fiche_t f)
    {
       printf("Nom : %s\n", f.n);
       printf("Prenom : %s\n", f.p);
       printf("Année de naissance : %d\n", f.annee);
       printf("Code Postal : %d\n", f.cp);
    }
    Au détail près de l'erreur de type (cf question 1, 2, ...) ça me semble correct.


    EDIT: grilled ! Heureusement on dit la même chose

  4. #4
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Merci pour vos deux réponses cela m'a aidé en effet voici les corrections :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct fiche_s{
     char *nom;
     char *prenom;
     int annee;
     int cp;
    };
    typedef struct fiche_s fiche_t;
    J'ai donc rajouter le fameux "*". Et renommer mes champs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    fiche_t * fiche_creer(char *nom, char *prenom, int annee, int cp)
    {
       fiche_t *res = (fiche_t*)malloc(sizeof(fiche_t));
       res -> nom = (char *) malloc((strlen(nom) + 1) * sizeof(char));
       res -> prenom = (char *) malloc((strlen(prenom) + 1) * sizeof(char));
       res -> annee = annee;
       res -> cp = cp;
       return res;
    }
    De même pour cette fonction j'ai ajouter "*" j'avais vraiment le doute.
    Par contre pour strcpy je ne sais pas comment ça fonctionne même si j'ai le rappel .. :/

    edit : peut être comme ceci
    strncpy(res.nom,nom);
    strcpy(res.prenom,prenom);

    Pour cmp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1.nom, s2.nom) == 0)
          return 1;
       return 0;
       if (strcmp(s1.prenom, s2.prenom) == 0)
          return 1;
       return 0;
    }
    C'est vrai qu'il y a eu une erreur de compréhension de ma part.. d'habitude je fais comme ceci !

    Enfin le fichier_detruire je n'arrive toujours pas a corriger .. mais j'ai tenter un truc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void fiche_detruire(fiche_t *fiche)
    {
     
          fiche_t *res =(fiche_t*) malloc(sizeof(fiche_t));
          free(res);
          return;
    }
    codeblock ne m'affiche plus d'erreur ..

  5. #5
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Djiinw Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    fiche_t * fiche_creer(char *nom, char *prenom, int annee, int cp)
    {
       fiche_t *res = (fiche_t*)malloc(sizeof(fiche_t));
       res -> nom = (char *) malloc((strlen(nom) + 1) * sizeof(char));
       res -> prenom = (char *) malloc((strlen(prenom) + 1) * sizeof(char));
       res -> annee = annee;
       res -> cp = cp;
       return res;
    }
    Avant d'utiliser res il faut vérifier que malloc n'a pas renvoyé NULLAprès avoir alloué une chaîne il faut la remplir, par exemple avec strcpy. Le prototype de cette fonction est char* strcpy(char *destination, char *source) et copie la chaine source dans destination -> consulte la man page strcpy

    Citation Envoyé par Djiinw Voir le message
    De même pour cette fonction j'ai ajouter "*" j'avais vraiment le doute.
    Par contre pour strcpy je ne sais pas comment ça fonctionne même si j'ai le rappel .. :/

    Pour cmp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1.nom, s2.nom) == 0)
          return 1;
       return 0;
       if (strcmp(s1.prenom, s2.prenom) == 0)
          return 1;
       return 0;
    }
    C'est vrai qu'il y a eu une erreur de compréhension de ma part.. d'habitude je fais comme ceci !
    En français ce que tu dois faire est :
    si les deux fiches ont le même prénom ET le même nom ET la même année ET le même code postal alors tu renvoies vrai , sinon tu renvoies faux.


    Citation Envoyé par Djiinw Voir le message

    Enfin le fichier_detruire je n'arrive toujours pas a corriger .. mais j'ai tenter un truc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void fiche_detruire(fiche_t *fiche)
    {
     
          fiche_t *res =(fiche_t*) malloc(sizeof(fiche_t));
          free(res);
          return;
    }
    codeblock ne m'affiche plus d'erreur ..
    Alors là tu alloues res puis tu le libères tout de suite : ça ne sert à rien car c'est le paramètre fiche que tu dois libérer.

    Pour ce faire il faut commencer par libérer les champs de fiche que tu as alloués dynamiquement (donc les chaines), et ensuite libérer ficher (le sens inverse des allocations).
    Tu n'as pas besoin de mettre return à la fin.

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Déja pour la fonction cmp

    je dois donc mettre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1.nom, s2.nom) && strcmp(s1.prenom, s2.prenom) && strcmp(s1.annee, s2.annee) && strcmp(s1.cp, s2.cp)  == 0)
          return 1;
       return 0;
     
    }

  7. #7
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Non.
    Tu compares les noms avec strcmp(s1.nom, s2.nom)==0 car s1.nom et s2.nom sont des chaines de caractères (string en anglais, strcmp -> STRing CoMPare).
    Tu compares les entiers avec un ==.

    Tu mets chaque comparaison entre parenthèses et les comaparaisons sont chainées avec des &&, comme la phrase en français.

  8. #8
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Hum.. j'ai essayer ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int fiche_cmp (fiche_t s1, fiche_t s2)
    {
       if (strcmp(s1.nom, s2.nom) && strcmp(s1.prenom, s2.prenom) && (s1.annee == s2.annee) && (s1.cp == s2.cp)  == 0)
          return 1;
       return 0;
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void fiche_detruire(fiche_t *fiche)
    {
        free(fiche->nom);
        free(fiche->prenom);
        free(fiche);
     
    }

  9. #9
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    On va essayer autrement ...
    Comment ferais-tu avec plusieurs if ?
    Disons pour traduire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    si s1 et s2 ont le même nom alors
      si s1 et s2 ont le même prenom alors
        si s1 et s2 ont la même année alors
          si s1 et s2 ont le même code postal alors
            je renvois VRAI
          fin si
        fin si
      fin si
    fin si
     
    je renvois FAUX

  10. #10
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if (strcmp(s1.nom, s2.nom) == 0)
       if (strcmp(s1.prenom, s2.prenom) == 0)
        if (s1.annee == s2.annee) 
          if (s1.cp == s2.cp )
           return 1;
    else
           return 0;

  11. #11
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Oui c'est ça (enfin sauf pour le else mais ce n'est pas grave pour l'instant) ...
    Pour n'avoir plus qu'un if tu prends toutes tes conditions et tu les relies avec des && .... tout simplement en n'oubliant pas d'entourer le tout avec une paire de parenthèses :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if (  (strcmp(s1.nom, s2.nom) == 0)
       && (strcmp(s1.prenom, s2.prenom) == 0)
       && (s1.annee == s2.annee) 
       && (s1.cp == s2.cp ) )
           return 1;
    else
           return 0;
    Bon c'est une indentation possible ... ensuite tu prends celle qui te semble la plus lisible. Je ne peux te conseiller que de mettre trop de parenthèses au départ ... cela t'évitera dans un premier temps de trop penser aux priorités des opérateurs ou ce genre de choses, en plus ça ne mage pas de pain.

  12. #12
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Ha merci je vais garder ton exemple !

    ensuite j'ai rectifié comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void fiche_detruire(fiche_t *fiche)
    {
        free(fiche->nom);
        free(fiche->prenom);
        free(fiche);
     
    }

  13. #13
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Ça me semble correct.

    Tu as tout compilé et essayé avec un programme de test ?

  14. #14
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Quand je compile sur ideone.com j'ai cette erreur

    /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o: In function `_start':
    (.text+0x18): undefined reference to `main'
    collect2: error: ld returned 1 exit status
    et sur code block
    c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libmingw32.a(main.o):main.c.text.startup+0xa7)||undefined reference to `WinMain@16'|

  15. #15
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    quand tu crées une application il faut écrire un main

  16. #16
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Ha oui lol.

    Justement le main.c j'y arrive jamais .. je sais que "fichier.h" contient les déclarations de fonction le "fichier.c" la définition des fonctions et le "main.c" sert à "tester" nos fonctions .. mais je ne sais pas comment l'utiliser !

  17. #17
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Dans main.c, tu écris la fonction main() dans lequel tu utilises des fonctions qui sont définis ailleurs. Ils font donc connaitre le prototype de ces fonctions. Cela se fait avec les fichiers d'en-tête tel que fichier.h (s'il est bien fait !).

    :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "fichier.h"
    //# include de surement stdio.h et peut etre stdlib.h
     
    int main(void)
    {
        // appeler des fonctions dont le protoype m'est donné par fichier.h
        return 0; // ou autre chose si cela te sert a qq chose mais 0 est bien pour ce genre de programme d'études
    }

  18. #18
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    J'aimerai attirer ton attention sur un "détail".
    Ta fiche contient des chaines de caractères.
    Comme ce sont des pointeurs, je te recommande d'utiliser des chaines de caractères constants.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct fiche_s{
        const char *nom;
        const char *prenom;
        int annee;
        int cp;
    };
    typedef struct fiche_s fiche_t;
    Ca t'évitera de nombreux déboires.
    Dans le cas contraire, tu peux tomber sur des problèmes d'accès mémoire interdit (la fameuse segmentation fault)

    Regarde le fragment de code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main() {
        char* mot;
        mot = "message";
        mot[4]='i';
        return 0;
    }
    L'idée est de changer le 'a' de message en 'i'.
    Le seul problème, c'est que la constante "message" est écrite dans le binaire lui-même, et donc n'est pas dans de la mémoire modifiable (un peu comme celle pointé par NULL)
    Du coup, à l'exécution, mot[4]='i'; provoque une segmentation fault.

    Cela dit, puisque tu fais une allocation manuelle et un strcpy, cela ne te pose pas de problème.

    Je te l'explique, parce que j'ai eu un jour un mois de débug sur une application complexe à cause de ce problème.
    En fait, j'avais une série de fonctions qui se passaient une chaine en argument, la dernière la modifiant, alors que l'argument initial était une telle constante.

    Le fait de placer des const autant que possible tend à te protéger de cela, et donc permet d'utiliser les constantes de chaines sans risque.

    Les compilateurs ont une option pour se afficher un warning à ce sujet. (avec gcc, utilise donc le triplet -Wall -Wextra -Werror)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  19. #19
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 13
    Points : 3
    Points
    3
    Par défaut
    Merci pour vos réponses.

    Je dois donc définir const seulement dans la structure c'est bien ça ? En tout cas c'est bon à savoir !

    (en cours on a jamais vu ça enfaîte..)

    Pour le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "fichier.h"
     
    int main(void)
    {
        fiche_t * fiche_creer(char *nom, char *prenom, int annee, int cp);
        void fiche_detruire(fiche_t *fiche);
        int fiche_cmp (fiche_t s1, fiche_t s2);
        void fiche_affiche (fiche_t f);
        return 0; 
    }
    J'ai jamais compris comment faire appel a mes fonctions ..

    edit : j'aimerai revenir sur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void fiche_detruire(fiche_t *fiche)
    {
        free(fiche->nom);
        free(fiche->prenom);
        free(fiche);
     
    }
    Comment ça ce fait qu'on a utiliser free sur nom et prenom et pas les autres champs ?
    C'est parce que dans fiche_creer on a allouer de l'espace pour les char ?

    edit 2 :

    Et pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    fiche_t * fiche_creer(char *nom, char *prenom, int annee, int cp)
    {
       fiche_t *res = (fiche_t*)malloc(sizeof(fiche_t));
       res -> nom = (char *) malloc((strlen(nom) + 1) * sizeof(char));
       res -> prenom = (char *) malloc((strlen(prenom) + 1) * sizeof(char));
       res -> annee = annee;
       res -> cp = cp;
       return res;
    }
    est-il nécessaire d'utiliser strcpy ?

  20. #20
    Membre averti
    Homme Profil pro
    Cadre informatique
    Inscrit en
    Avril 2013
    Messages
    183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Cadre informatique

    Informations forums :
    Inscription : Avril 2013
    Messages : 183
    Points : 435
    Points
    435
    Par défaut
    Pour le free, je peux te répondre.
    Pourquoi seulement sur ces 2 là, te dis-tu, regarde bien ce qu'il y a entre le type et le nom de ta variable
    Tu alloues la mémoire donc tu dois la rendre. Les autres sont en "dures" qui seront effacées en fin de programme.

    En gros, toute allocation doit etre libérée par tes soins sinon sa peut planter.
    J'essaye de me forcer à prendre cette habitude et c'est pas gagné encore

Discussions similaires

  1. Fonction de lecture de fichier (variable)
    Par virtuadrack dans le forum C++
    Réponses: 2
    Dernier message: 23/01/2009, 20h17
  2. Lecture de fichiers .wav et fonction random
    Par Pedrozito dans le forum Interfaces Graphiques
    Réponses: 9
    Dernier message: 22/04/2008, 16h23
  3. Réponses: 5
    Dernier message: 26/03/2007, 01h30
  4. Fonction de lecture de fichier
    Par parisjohn dans le forum C
    Réponses: 6
    Dernier message: 24/11/2006, 14h29
  5. Réponses: 12
    Dernier message: 14/06/2004, 13h06

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