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 :

Impossibilité de lire un fichier texte créé


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut Impossibilité de lire un fichier texte créé
    Bonjour!
    Je suis sous Linux et j'utilise Code::Blocks pour compiler mes programmes.
    Je débute en C et je fais les quelques exercices qu'il y a dans le livre de Delannoy mais j'ai un problème avec un exercice.
    C'est un exercice pour utiliser les commandes de création et d'écriture séquentielle d'un fichier.
    Le problème étant qu'une fois le fichier créé, s'il a été rempli via le programme, impossible de le lire.

    Voici mon programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #include <stdio.h>
    #include <string.h>
     
    main()
    {
        struct infos {char nom[21]; char prenom[16]; int age; char tel[10];};
        struct infos personne;
        char nomfich[21];
        FILE * sortie;
     
        printf("Donnez un nom à votre fichier : ");
        scanf("%20s", nomfich); getchar();
        sortie = fopen(nomfich, "w");
     
        while (1)
        {
            printf("\n");
            printf("Nom : "); gets(personne.nom);
            if(!strlen(personne.nom)) break;
     
            printf("Prénom : "); gets(personne.prenom);
     
            printf("Age : "); scanf("%3d", &personne.age); getchar();
     
            printf("Numéro de téléphone : "); gets(personne.tel);
     
            fwrite(&personne, sizeof(personne), 1, sortie);
        }
        fclose(sortie);
    }
    Et voici la solution donné par Delannoy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include <stdio.h>
    #include <string.h>
    #define LGNOM 20
    #define LGPRENOM 15
    #define LGTEL 11
     
    main()
    {
        char nomfich[21];
        FILE * sortie;
        struct { char nom[LGNOM+1];
                 char prenom[LGPRENOM+1];
                 int age;
                 char tel[LGTEL+1];
                } bloc;
     
        printf("Donnez le nom du fichier à créer : ");
        gets(nomfich);
        sortie = fopen(nomfich, "w");
        printf("----- pour finir la saisie, donnez un nom vide -----\n");
        while(printf("Nom : "), gets(bloc.nom),strlen(bloc.nom))
        {
            printf("Prénom :");
            gets(bloc.prenom);
            printf("Age : ");
            scanf("%d", &bloc.age); getchar();
            printf("Téléphone : ");
            gets(bloc.tel);
            fwrite(&bloc, sizeof(bloc), 1, sortie);
        }
        fclose(sortie);
    }
    Ca bloque à partir du moment ou le tampon est écrit dans le fichier via la commande 'fclose' et en fait soit j'ai un fichier qu iest pris pour un fichier image masi impossible de le lire soit un fichier qui est strictement illisible, aucun programme n'est en mesure de me le lire...

    Merci de m'aider!

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    Voici mon programme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       char nomfich[21];
     
       scanf ("%20s", nomfich);
       getchar ();
    Correct, mais un peu 'bidouilleux'... En cas de dépassement, le flux n'est pas vidé, ce qui provoque une instabilité :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Donnez un nom Ó votre fichier : aaaaaaaaaaaaaaaaaaaaaaaaaa
     
    Nom : PrÚnom :
    Eviter les accentuées, ce n'est pas portable... Pour un exercice, on a pas besoin d'une présentation parfaite.
    Avec une bonne purge, ça va déjà mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Donnez un nom a votre fichier : aaaaaaaaaaaaaaaaaaaaaaa
     
    Nom :
    attention, fopen() peut échouer. Il faut tester la valeur retournée avant de l'utiliser (NULL = problème).

    Non. On utilise pas gets(). C'est un bug. Il n'y a aucun moyen de limiter le nombre de caractères entrés, et il y a donc un risque permanent de débordement de tableau.

    Tu avais pourtant bien commencé avec un usage plutôt correct de scanf() (ce qui est suffisamment rare pour être souligné...). Continue sur cette lancée, sauf si on t'a expressément demandé de saisir des lignes avec des espaces, dans ce cas, il faut utiliser fgets().

    Au fait, pour la 'ligne vide', il n'y pas le choix, il faut utiliser fgets(). Ni gets() ni scanf() ne fonctionnent sur une ligne vide.

    Pour fgets() qui prend aussi le '\n', il y a une petite manip de nettoyage à faire avant (voir la fonction 'communautaire' fclean(), maintes fois publiée sur le forum)... Je conseille par contre l'usage exclusif de fgets() pour toutes les saisies. Faire les conversion en numérique si nécessaire...

    Citation Envoyé par sdumasp Voir le message
    Et voici la solution donné par Delannoy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        gets(nomfich);
     
        while(printf("Nom : "), gets(bloc.nom),strlen(bloc.nom))
     
            gets(bloc.prenom);
     
            gets(bloc.tel);
    }
    Voilà, entre autres, pourquoi je ne recommande pas les livres de C.Delannoy.

  3. #3
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    • comment faire pour purger correctement le tampon de scanf après récupération d'une saisie? il y a une commande spéciale?
    • en ce qui concerne la commande 'gets' c'est que j'ai pas mal retouché mon programme de départ histoire qu'il ressembleà celui de Delannoy (malheureusement aucun des deux ne fonctionnent...) et habituellement j'utilise fgets qui me permet de controller parfaitement la saisie et d'éviter des lignes de code supplémentaire pour vérifier s'il y a pas dépassement (parfois j'utilise gets+sscanf, je l'avoue , pour vérifier si le type saisi est correct)
    • les instructions dans les conditions de boucles?
      moi j'aime pas trop parce que j'arrive plus à lire mon code après alors j'évite et je préfère détailler à l'intérieur de la boucle



    (petite question subsidiaire qui n'a aucun rapport, comment inclure les libraires GTK et GTK+ à Code::Blocks? il veut pas me compiler mon truc quand j'inclus gtk/gtk+.h...)

  4. #4
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    comment faire pour purger correctement le tampon de scanf après récupération d'une saisie? il y a une commande spéciale?
    Non. On doit faire ceci :
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void purge (void)
    {
       int c;
       while ((c = getchar ()) != '\n' && c != EOF)
       {
       }
    }
    en ce qui concerne la commande 'gets' c'est que j'ai pas mal retouché mon programme de départ histoire qu'il ressembleà celui de Delannoy (malheureusement aucun des deux ne fonctionnent...) et habituellement j'utilise fgets qui me permet de controller parfaitement la saisie et d'éviter des lignes de code supplémentaire pour vérifier s'il y a pas dépassement (parfois j'utilise gets+sscanf, je l'avoue , pour vérifier si le type saisi est correct)
    Je supose que tu veux dire "fgets() + sscanf()". Tu as raison, continue comme ça. Laisse tomber gets() (bug) et scanf() est trop fort pour toi, moi, ... et Delannoy !
    les instructions dans les conditions de boucles?
    moi j'aime pas trop parce que j'arrive plus à lire mon code après alors j'évite et je préfère détailler à l'intérieur de la boucle
    C'est carrément laid et illisible (Qui fait quoi ? Quand ?)
    (petite question subsidiaire qui n'a aucun rapport, comment inclure les libraires GTK et GTK+ à Code::Blocks? il veut pas me compiler mon truc quand j'inclus gtk/gtk+.h...)
    Il y a une procédure décrite dans la section GTK+.

  5. #5
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    oui oui pardon, je parlais de 'fgets()' et 'sscanf()'!!

    merci pour les explications et les astuces, ça permet d'être rigoureux et de faire des trucs lisibles et fonctionnels!
    cependant je ne pense pas que le problème vienne du programme vu que celui de Delannoy ne fonctionne pas non plus (à noter qu'il manque l'inclusion de string.h dans la correction!); je pense que ça vient plutôt de l'OS.

    quand au GTK+ la procédure est pour Windows et je suis sous Linux (Ubuntu) et je trouve rien de bien nulle part...

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    cependant je ne pense pas que le problème vienne du programme vu que celui de Delannoy ne fonctionne pas non plus (à noter qu'il manque l'inclusion de string.h dans la correction!); je pense que ça vient plutôt de l'OS.
    Je ne pense pas. Comment as-tu quitté le programme puisque la manip prévue (strlen(...)) ne fonctionne pas ?

    Si tu as fais un ctrl-break, il est possible que le fichier ne soit pas fermé correctement et qu'il soit donc de taille nulle.

    Je pense qu'un recodage à base de fgets() corrigera le problème.

    Sinon, problèmes de droits, de propriétaire etc. Effectivement, c'est l'OS.

  7. #7
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    le programme se terminait correctement quand je rentrais un nom vide puisque le type de fichier changeait dès que la fonction 'fclose(sortie);' était exécutée.
    tant que c'est dans le tampon, mon fichier est lisible mais évidemment il n'y a rien dedans... après ça ne fonctionne plus!

    je vais tenter de reformuler tout ça en bonne et due forme

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    J'ai bien peur, hélas, que tu puisses jeter ton livre:
    1. main() retourne un int. Toujours.
    2. La fonction gets() ne doit pas être utilisée. Jamais.
    3. Le code ne vérifie pas si le fopen() a fonctionné. Zéro.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

  9. #9
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    Bon j'ai refait ça plus proprement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #include <stdio.h>
    #include <string.h>
     
    int main()
    {
        void fclean(char *);
        struct {char nom[21]; char prenom[16]; int age; char tel[11];} personne;
        char nomfich[21];
        FILE * sortie;
     
        printf("Donnez un nom à votre fichier : ");
        fgets(nomfich, 20, stdin); fclean(nomfich);
        while( (sortie = fopen(nomfich, "w")) == NULL);
     
        while(1)
        {
            printf("\nNom : ");
            fgets(personne.nom, 20, stdin);
            fclean(personne.nom);
     
            printf("Prénom : ");
            fgets(personne.prenom, 15, stdin);
            fclean(personne.prenom);
     
            printf("Age : "); scanf("%3d", &personne.age);
            getchar();
            if(personne.age==100) break;
     
            printf("Numéro de téléphone : ");
            fgets(personne.tel, 10, stdin);
            fclean(personne.tel);
     
            if( ( fwrite(&personne, sizeof(personne), 1, sortie) ) !=1) printf("--- Erreur d'écriture ---");
        }
        fclose(sortie);
    }
     
    void fclean (char *s_buffer)
    {
        char *nl = strchr(s_buffer, '\n');
     
        if (nl != NULL) *nl = '\0';
        else
        {
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
        }
    }
    mais toujours rien... en plus j'arrive pas à trouver de sortie adaptable à personne.nom pour sortir dès le début de la saisie plutôt que de se taper deux champs de saisie d'abord...

    et plutôt que de mettre un getchar après 'scanf()' pour avoir un int, vu que la fonction purge est inclue dans ma fonction fclean, y-a-t'il moyen de lancer fclean sans argument?! ou alors je la lance simplement avec une chapine déjà purgée en argument?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Dans sa version actuelle, tu peux l'appeler avec une chaîne déjà purgée, ou une chaîne vide.
    Mais adapter la fonction pour qu'elle accepte NULL serait en effet plus pratique...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

  11. #11
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    sinon trop tard j'ai presque fini de lire le bouquin il doit me rester deux chapitres

    Je sais d'où vient l'erreur!!
    Il y a un problème avec la déclaration de la taille de l'objet à écrire.
    Si je garde exactement le même source en remplaçant 'sizeof(personne)' par 'sizeof(char)' dans la fonction 'fwrite()', j'arrive à obtenir dans mon fichier texte la première lettre de la première saisie (du nom en l'occurence).

    donc où est le problème dans cette fonction?!
    pourtant c'est la méthode utilisée par Delannoy dans so ncorrigé et ça a pas eu l'air de vous choquer dans la rédaction...

    EDIT : j'ai tenté ça 'for(int i=0; i<21; i++) fwrite(&personne.nom[i], sizeof(char), 1, sortie);' ne serait-ce que pour écrire le nom vori sic'était ça le problème masi ça ne change rien...

  12. #12
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    Bon j'ai refait ça plus proprement :
    <...>
    mais toujours rien... en plus j'arrive pas à trouver de sortie adaptable à personne.nom pour sortir dès le début de la saisie plutôt que de se taper deux champs de saisie d'abord...
    Voilà ton code au propre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    static void clean (char *s_buffer)
    {
       char *nl = strchr (s_buffer, '\n');
     
       if (nl != NULL)
       {
          *nl = 0;
       }
       else
       {
          int c;
          while ((c = getchar ()) != '\n' && c != EOF)
          {
          }
       }
    }
     
    int main (void)
    {
       char nomfich[21];
     
       printf ("Donnez un nom a votre fichier : ");
       fgets (nomfich, sizeof nomfich, stdin);
       clean (nomfich);
       FILE *sortie = fopen (nomfich, "wb");
       if (sortie != NULL)
       {
          while (1)
          {
             struct
             {
                char nom[21];
                char prenom[16];
                int age;
                char tel[11];
             }
             personne;
     
             printf ("\nNom ( <enter> pour quitter) : ");
             fgets (personne.nom, sizeof personne.nom, stdin);
             clean (personne.nom);
             if (*personne.nom == 0)
             {
                break;
             }
             printf ("Prenom : ");
             fgets (personne.prenom, sizeof personne.prenom, stdin);
             clean (personne.prenom);
     
             printf ("Age : ");
             {
                char s[4];
                fgets (s, sizeof s, stdin);
                clean (s);
     
                personne.age = (int) strtol (s, NULL, 10);
             }
     
             printf ("Numero de telephone : ");
             fgets (personne.tel, sizeof personne.tel, stdin);
             clean (personne.tel);
     
             if ((fwrite (&personne, sizeof personne, 1, sortie)) != 1)
             {
                printf ("--- Erreur d'ecriture ---");
             }
          }
          fclose (sortie);
       }
       return 0;
    }
    Pose des questions si tu ne comprends pas.

    NOTA. Pour être cohérent : fclean() est générique : FILE *fp, clean() est fait pour stdin...

    En principe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int clean(char *s)
    {
       return fclean (s, stdin);
    }
    Ma version de fclean() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    #include "fclean.h"
     
    #include <string.h>
     
    int fclean (char *s_buffer, FILE * stream)
    {
       int err = 0;
       if (s_buffer != NULL && stream != NULL)
       {
          char *pc = strchr (s_buffer, '\n');
     
          if (pc != NULL)           /* La saisie n'a pas ete tronquee */
          {
             /* On remplace '\n' par le caractere nul '\0' */
             *pc = 0;
          }
          else
          {
             /* La saisie a ete tronquee, on purge le flux d'entree */
             int c;
             while ((c = fgetc (stream)) != '\n' && c != EOF)
             {
             }
             err = 1;
          }
       }
       return err;
    }
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    #ifndef H_ED_FCLEAN_20070915175800
    #define H_ED_FCLEAN_20070915175800
     
    #ifdef __cplusplus
    extern "C"
    {
    #endif
     
    /* fclean.h */
     
    #include <stdio.h>
     
    /* made from 100% recycled bits */
       int fclean (char *s_buffer, FILE * stream);
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif                          /* guard */
     
    /* Guards added by GUARD (c) ED 2000-2005 Jan 17 2005 Ver. 1.7 */
    Avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Donnez un nom a votre fichier : data.txt
     
    Nom ( <enter> pour quitter) : Delahaye
    Prenom : Emmanuel
    Age : 51
    Numero de telephone : 0123456789
     
    Nom ( <enter> pour quitter) :
     
    Press ENTER to continue.
    Comment sais-tu que le fichier produit n'est pas conforme ? Es-tu bien conscient que c'est un 'mapping mémoire' binaire et qu'il n'est donc pas lisible par un éditeur de texte. Par contre, en mode hexa, on a bien ce qu'il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    00000000h: 44 65 6C 61 68 61 79 65 00 00 BF 77 00 00 3D 00 ; Delahaye..¿w..=.
    00000010h: 00 00 00 00 E3 45 6D 6D 61 6E 75 65 6C 00 00 00 ; ....ãEmmanuel...
    00000020h: 58 23 24 00 94 5C C0 77 33 00 00 00 30 31 32 33 ; X#$.”\Àw3...0123
    00000030h: 34 35 36 37 38 39 00 00                         ; 456789..
    Il y a un peu de 'garbage'. Je conseille de nettoyer la structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
             struct
             {
                char nom[21];
                char prenom[16];
                int age;
                char tel[11];
             }
             personne = {"", "", 0, ""};
    Ca a tout de suite une meilleure tronche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    00000000h: 44 65 6C 61 68 61 79 65 00 00 00 00 00 00 00 00 ; Delahaye........
    00000010h: 00 00 00 00 00 45 6D 6D 61 6E 75 65 6C 00 00 00 ; .....Emmanuel...
    00000020h: 00 00 00 00 00 00 00 00 33 00 00 00 30 31 32 33 ; ........3...0123
    00000030h: 34 35 36 37 38 39 00 00                         ; 456789..
    Mais ça reste toujours non-visible correctement par un éditeur (le mien passe en héxa direct, à cause des 0).

    Si tu veux créer un fichier texte, il faut spécifier un format (CSV etc.) et s'y conformer.

  13. #13
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    ah ben tout s'explique alors si c'est pas un fichier texte qui est créé!
    mais dans ce cas comment ça se fait que je puisse lirem on fichier texte si je n'écris qu'une seule lettre (comme la première du nom)?

    Sinon j'ai quelques questions sur tout ça :
    • pourquoi mettre "wb" dans 'fwrite()', on ne peut pas créer un fichier texte en mettant simplemetn "wb"? il faut forcément totue la procédure que tu as citée?
    • pourquoi déclarer une variable locale au bloc du if? et si c'est un peu 'garbage' c'est parce qu'étant donné qu'elle est déclarée en locale, il faut l'initialiser à 0??
    • si tu récupères l'age via des caractères avant de les convertir en entier c'est pour éviter à tout prix 'scanf()'?
    • et enfin, pour la méthode de purge je ne comprend pas bien le deuxième fichier, celui qui vient de chez guards, j'ai l'impression que c'est le fclean.h?!
    • et y-a-t'il un moyen de se créer un fichier personne lde ce type pour simplement en faire l'inclusion en début de programme plutôt que de réécrire la fonction à chaque fois? parce que si je veux vraiment être rigoureux comme tu le fais, il va falloir que j'utilise bien tous ces petits trucs pour la saisie!


    Merci!

  14. #14
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    ah ben tout s'explique alors si c'est pas un fichier texte qui est créé!
    mais dans ce cas comment ça se fait que je puisse lirem on fichier texte si je n'écris qu'une seule lettre (comme la première du nom)?
    Le premier champ est un champ texte terminé par un 0. Il est donc 'affichable' si l'éditeur de texte ou le 'visualiseur' (cat, type) ne plante pas quand il voit un 0 dans un fichier ouvert en mode texte. Mais je le répète, le fichier n'étant pas au format texte,(il y a des 0), le comportement est indéterminé si on l'ouvre avec un logiciel prévu pour le mode texte. (éditeur etc.).
    pourquoi mettre "wb" dans 'fwrite()', on ne peut pas créer un fichier texte en mettant simplemetn "wb"? il faut forcément totue la procédure que tu as citée?
    Pour être cohérent avec le format des données enregistrées dans le fichier est de type 'binaire'. En réalité ça signifie tout simplement 'raw', (cru ou brut), c'est à dire sans aucune interprétation. Ce qui est en mémoire est strictement reproduit dans le fichier.
    pourquoi déclarer une variable locale au bloc du if?
    Principe de réduction de la portée des objets et fonctions au minimum.
    et si c'est un peu 'garbage' c'est parce qu'étant donné qu'elle est déclarée en locale, il faut l'initialiser à 0??
    Oui, et comme elle est 'bien placée' (au début du bloc de la boucle), l'initialisation de fait 'naturellement' à chaque tour, ce qui est exactement ce que je voulais.

    Il n'y a pas de hasard en informatique. Les Bonnes Pratiques sont issues de la logique et du bon sens, et elles se traduisent souvent par du code plus simple et plus robuste...
    si tu récupères l'age via des caractères avant de les convertir en entier c'est pour éviter à tout prix 'scanf()'?
    Absolument. Principe d'homogénéité. fgets() ou rien.
    et enfin, pour la méthode de purge je ne comprend pas bien le deuxième fichier, celui qui vient de chez guards, j'ai l'impression que c'est le fclean.h?!
    C'est bien fclean.h. C'est l'interface de fclean.c. (Prototypes et protections 'réglementaires' contre les inclusions multiples dans la même unité de compilation : guards).

    Nota 'guard' est un programme maison qui génère les 'guards', c'est à dire les protections d'un header (.h). C'est une application du principe 'ce qui est répétitif est automatisable'. Le 'ED' qui apparait dans les constantes de protection est ma signature. Tu es censé mettre autre chose si tu développes ton propre code...
    et y-a-t'il un moyen de se créer un fichier personnel de ce type pour simplement en faire l'inclusion en début de programme plutôt que de réécrire la fonction à chaque fois? parce que si je veux vraiment être rigoureux comme tu le fais, il va falloir que j'utilise bien tous ces petits trucs pour la saisie!
    Oui, bien sûr. C'est pour ça que j'ai publié fclean.h et fclean.c. Tu les ajoutes au projet, tu inclues "fclean.h" dans les fchiers sources qui en ont besoin et c'est réglé. Après, si tu préfères, tu verras comment en faire une bibliothèque :

    http://emmanuel-delahaye.developpez....m#bibliotheque

  15. #15
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    merci pour ce petit cours de rigueur c'est vrai que le code en est d'autant plus simple, plus compréhensible et surtout plus efficace!

    je vais essayer d'appliquer ça parce que c'est vrai que parfois le cours de Delannoy (ou tout du moins les corrigés qu'il propose) manquent un peu de rigueur notamment avec les instructions dans les conditions de boucles etc...

    sais-tu ou je pourrais trouver plus d'informations sur la rigueur et la bonne utilisation des fonctions ou des possibilités du C?!
    peut-être sur ton site, je vais jeter un coup d'oeil!

  16. #16
    Candidat au Club
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 2
    Par défaut
    wi c une bonne question parceque jé trouvé le méme soucis . alors essayé avec un chemin trés court du féchier

    ex c:\le nom du fichier

  17. #17
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    ah! je viens de réussir à inclure "fclean.h" au main d'un projet.
    je faisais pas mes programmes par projet avant mais c'est vrai que c'est beaucoup plus simple! décidément je manque pas mal de rigueur!

  18. #18
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par emsist86 Voir le message
    wi c une bonne question parceque je trouvé le méme soucis . alors essayé de ne po un chemin trés long du féchier

    ex c:\lenom du fichier
    Tu peux le refaire en français ? Faut quand même pas exagérer là...

    J'ai modifié le code pour qu'il tienne compte automatiquement de la taille de
    Il suffit maintenent de l'agrandir,
    et de recompiler...
    Attention, si il y a des espaces dans le nom du fichier, il faut penser à encadrer le nom avec des " " :

    "mon fichier"

  19. #19
    Membre averti
    Profil pro
    Lycéen
    Inscrit en
    Décembre 2007
    Messages
    37
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Décembre 2007
    Messages : 37
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    J'ai modifié le code pour qu'il tienne compte automatiquement de la taille de
    je ne comprend pas bien quel code a été modifié?!

    sinon même si le fichier n'est pas lisible directement par éditeur de texte, il l'est séquentiellement ou directement via un autre programme que je viens de faire.

    j'ai une petite question, dans un programme, une fois les fichiers fclean.h et fclean.c rajoutés au projet, y-a-t'il un moyen de m'éviter de me taper tout le chemin dans l'inclusion?
    je suis obligé de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #include "/home/sdumasp/Programmation/fclean.h"

  20. #20
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 69
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par sdumasp Voir le message
    je ne comprend pas bien quel code a été modifié?!
    http://www.developpez.net/forums/sho...7&postcount=12

    j'ai une petite question, dans un programme, une fois les fichiers fclean.h et fclean.c rajoutés au projet, y-a-t'il un moyen de m'éviter de me taper tout le chemin dans l'inclusion?
    je suis obligé de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #include "/home/sdumasp/Programmation/fclean.h"
    Ce n'est plus un problème de langage C mais d'outil.

    A toi de passer la bonne option :

    [gcc] : -I"./"

    détails dans la doc de gcc. Je conseille l'usage de make avec un fichier makefile.

    Si tu utilises un IDE comme Code::Blocks, il faut préciser ./ dans les chemins des 'includes'.

    Settings > Directories > Compiler etc.

    http://emmanuel-delahaye.developpez.com/make.htm

    Je suis sous Linux et j'utilise Code::Blocks pour compiler mes programmes.
    Apparemment, j'ai bien visé...

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/12/2005, 15h57
  2. [Applet] lire un fichier texte
    Par lebesnec dans le forum Applets
    Réponses: 2
    Dernier message: 07/07/2005, 10h09
  3. Réponses: 1
    Dernier message: 24/11/2004, 16h54
  4. [Fichier] Lire un fichier texte long
    Par _Eric_ dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 18/08/2004, 15h22
  5. Réponses: 2
    Dernier message: 26/05/2004, 17h53

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