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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    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
    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
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    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 : 52
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    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
    Membre habitué
    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
    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 : 52
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    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
    Membre habitué
    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
    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 : 52
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    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.

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