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 :

Stocker un enregistrement dans un fichier


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    Août 2009
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 69
    Points : 35
    Points
    35
    Par défaut Stocker un enregistrement dans un fichier
    Bonjour ou Bonsoir à tous.

    Je sollicite votre aide technique.

    Problème : D'abord, récupérer des éléments (des entiers) saisis par l'utilisateur dans un vecteur (tableau à une dimension) [1]. Ensuite, regrouper ces éléments par couples consécutifs et les numéroter [2]. Enfin, stocker chaque couple avec son numéro dans un fichier [3].
    Le fichier obtenu sera recopié dans un autre programme, où il sera exploité.

    Exemple et simulation : L'utilisateur saisit consécutivement les nombres 3; 7 et 5. Ces nombres sont récupérés dans un vecteur de taille 3. Le programme devra constituer 2 couples d'entiers suivis de leurs numéros respectifs : (3 ; 7) 1 et (7 ; 5) 2. Ce sont ces 2 couples d'entiers suivis de leurs numéros respectifs que le programme devra stocker dans un fichier.

    Ma proposition : J'ai écrit un programme modulaire
    Afin de mieux comprendre le programme, il faut savoir que : un graphe est constitué de nœuds ; un nœud est représenté par un nombre entier ; un lien (ou couple) est représenté par deux nœuds consécutifs.

    De plus : avec n nombres dans un vecteur, on forme (n-1) couples consécutifs. Par exemple : avec le vecteur (5; 8; 6; 7) => 3 couples consécutifs (5; 8), (8; 6) et (6; 7) avec leurs numéros respectifs allant de 1 à 3.

    *** le programme principal
    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
    #define TAILLE_MAX_VECTEUR 24
     
    int main()
    {
        int V[TAILLE_MAX_VECTEUR];
        struct lien L[TAILLE_MAX_VECTEUR - 1];
        int nombre, nombre_liens;
        char reponse;
     
        do
        {
            system("cls");
            printf("\n\n\t\tFORMATION DE LIENS NUMEROTES D'UN GRAPHE\n\n");
            nombre = saisirNombreNoeud(TAILLE_MAX_VECTEUR);
            system("cls");
            printf("\n\n\t\tFORMATION DE LIENS NUMEROTES D'UN GRAPHE\n\n");
            printf("\t\t *** Saisie des %d noeuds du graphe ***\n", nombre);
            saisirVecteur(V, nombre);
            printf("\n\n");
            printf("\t\t *** Affichage des %d noeuds ***\n\n", nombre);
            afficherVecteur(V, nombre);
            nombre_liens = nombre - 1;
            printf("\n\n\t\t *** Affichage des %d liens du graphe avec leurs numeros ***\n\n", nombre_liens);
            numeroterLien_Sans_Stockage(V, nombre, L, nombre_liens); //génération, numérotation, affichage des liens du graphe
            numeroterLien_Avec_Stockage(V, nombre, L, nombre_liens); //stockage des liens numérotés du graphe dans un fichier
            printf("\n\n");
            do
            {
                printf("Voulez-vous traiter un autre graphe (O/N)? : ");
                fflush(stdin);
                scanf("%c", &reponse);
            }
            while((reponse != 'o')&&(reponse != 'O')&&(reponse != 'n')&&(reponse != 'N'));
        }
        while((reponse != 'n')&&(reponse != 'N'));
     
        return 0;
    }

    *** les headers regroupés dans le fichier init_prog
    Code C : 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
    #ifndef INIT_PROG_H_INCLUDED
    #define INIT_PROG_H_INCLUDED
     
    struct lien
    {
        int compo1;
        int compo2;
        int numerolien;
    };
    int saisirNombreNoeud();
    void saisirVecteur(int T[], int nbre);
    void afficherVecteur(int T[], int nbre);
    void numeroterLien_Sans_Stockage(int T[], int nbre, struct lien K[], int nbre_liens);
    void numeroterLien_Avec_Stockage(int T[], int nbre, struct lien K[], int nbre_liens);
     
    #endif // INIT_PROG_H_INCLUDED

    *** fonction saisirNombreNoeud
    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
     
    int saisirNombreNoeud(int maximum)
    {
        int n;
        do
        {
            printf("Nombre de noeuds du graphe : ");
            scanf("%d", &n);
        }
        while((n < 2)||(n > maximum));
     
        return (n);
    }

    *** fonction saisirVecteur
    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
     
    void saisirVecteur(int T[], int nbre)
    {
        int i;
        for(i=0; i<nbre; i++)
        {
            do
            {
                printf("Donnez le noeud numero %d : ", (i+1));
                scanf("%d", &T[i]);
            }
            while(T[i]<0);
        }
    }

    *** fonction afficherVecteur
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
     
    void afficherVecteur(int T[], int nbre)
    {
        int i;
        for(i=0; i<nbre; i++)
        {
            printf("\t%d", T[i]);
        }
    }

    *** fonction numeroterLien_Sans_Stockage
    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
     
    void numeroterLien_Sans_Stockage(int T[], int nbre, struct lien K[], int nbre_liens)
    {
        int i=0, numlien=1;
        //génération et numérotation des liens du graphe
        while(i<nbre_liens)
        {
            K[i].compo1 = T[i];
            K[i].compo2 = T[i+1];
            K[i].numerolien = numlien;
            i++;
            numlien++;
        }
        //affichage des liens du graphe
        for(i=0; i<nbre_liens; i++)
        {
            printf("(%d ; %d) => lien %d\n", K[i].compo1, K[i].compo2, K[i].numerolien);
        }
    }

    *** fonction numeroterLien_Avec_Stockage
    Code C : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include "init_prog.h"
     
    void numeroterLien_Avec_Stockage(int T[], int nbre, struct lien K[], int nbre_liens)
    {
        FILE * fichier_graphe;
        int i=0, numlien=1;
        fichier_graphe = fopen("dossier/graphe.txt", "w+");
        if(fichier_graphe == NULL)
        {
            printf("ERREUR D'OUVERTURE DU FICHIER graphe.txt\n\n");
        }
        while(i<nbre_liens)
        {
            K[i].compo1 = T[i];
            K[i].compo2 = T[i+1];
            K[i].numerolien = numlien;
            i++;
            numlien++;
            fprintf(fichier_graphe, "%d %d %d\n", K[i].compo1, K[i].compo2, K[i].numerolien);
        }
        fclose(fichier_graphe);
    }

    A l'exécution :
    Il n'y a aucune erreur ni avertissement. Seule la fonction numeroterLien_Avec_Stockage donne pas le résultat attendu.
    Elle ne stocke pas correctement les couples avec leurs numéros dans le fichier. En effet, à l'ouverture ''manuelle" du fichier, on constate que le premier couple n'est pas stocké tandis que les suivants sont stockés, et le fichier se termine par une suite de chiffres "inconnus".

    Pourquoi ce dysfonctionnement ? Comment le résoudre ?
    Merci de m'aider.
    A bas Covid-19.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    En réalité c'est ultra trivial et l'erreur est

    Déjà 2 remarques (et je ne parlerai pas du côté modulaire qui me semble un peu moisi - 1 fichier pour 1 fonction de 10 lignes )
    1) Pourquoi tu utilises une boucle while ? Tu peux faire plusieurs incrémentations avec l'opérateur virgule dans une boucle for ... tout comme avec les initialisations.

    2) À quoi sert ton tableau de liens K/ L ? Tu stockes une valeur et immédiatement après tu l'affiches/ l'écris dans le fichier.

    Bonus) le passage tableau [] est dégradé en passage pointeur ... surtout lorsque les fonctions sont dans un autre fichier

    As-tu remarqué où se trouve l’incrémentation de ta variable numlien ? justement entre le stockage de ta valeur et l'écriture dans le fichier.
    Le méchant copié-collé de la fonction numeroterLien_Sans_Stockage en supprimant la boucle for parce que justement ton tableau de liens K/ L ne sert pas à grand chose.
    Et en plus avec une boucle for, tu n'aurais pas eu de problème (puisque l’incrémentation se fait à la fin de la boucle)

  3. #3
    Nouveau membre du Club
    Inscrit en
    Août 2009
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 69
    Points : 35
    Points
    35
    Par défaut Fiat lux et Eurêka
    Citation Envoyé par foetus Voir le message
    As-tu remarqué où se trouve l’incrémentation de ta variable numlien ? justement entre le stockage de ta valeur et l'écriture dans le fichier.
    Merci pour cet éclaircissement, foetus.
    Effectivement, dans la fonction numeroterLien_Avec_Stockage, la copie dans le fichier doit se faire avant l'incrémentation de la variable numlien.

    Concernant les autres remarques
    J'ai fortement décomposé pour que le programme soit le plus clair possible, pour moi-même et aussi pour mes sauveteurs qui souhaiteraient exécuter sur machine.
    Le "tableau de liens K/L" est d'une très grande importance. C'est un vecteur d'enregistrements dont j'ai besoin pour résoudre un problème de graphes dans un réseau.

    Merci beaucoup.

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par iks37 Voir le message
    Effectivement, dans la fonction numeroterLien_Avec_Stockage, la copie dans le fichier doit se faire avant l'incrémentation de la variable numlien.
    Accessoirement, c'est bien de vérifier si le fichier n'a pas été ouvert (le test if(fichier_graphe == NULL)) mais faut alors coder des conséquences un peu plus intelligentes qu'un bête affichage. Par exemple réfléchir dans ce cas au devenir des écritures et de la fermeture codées juste en dessous.

    Citation Envoyé par iks37 Voir le message
    J'ai fortement décomposé pour que le programme soit le plus clair possible, pour moi-même et aussi pour mes sauveteurs qui souhaiteraient exécuter sur machine.
    Le trop est l'ennemi du bien. Décomposer oui, mais décomposer avec finesse. Tu as deux niveaux de décomposition possibles : la décomposition en fonctions et la décomposition en fichiers ; chaque niveau permettant de hiérarchiser les abstractions. Si tu utilises les deux niveaux pour découper deux fois la même chose, non seulement tu perds une possibilité de niveau mais en plus tu complexifies ton projet par la multiplications de sources inutiles.
    Tu pourrais utiliser la décomposition par fichiers pour les grandes notions de ton projet (le source qui gère tout ce qui est lecture/écriture fichier, le source qui gère tout ce qui est saisie/affichage, etc), et bien entendu garder la décomposition par fonctions pour les actions élémentaires dont peuvent avoir besoin ces grandes notions).
    Et puis décomposer oui mais ne pas oublier quand-même de réfléchir à sa décomposition. Par exemple tu ne sens pas intuitivement que "numeroterLien_Avec_Stockage" et "numeroterLien_Sans_Stockage" c'est fondamentalement la même chose et que ça pourrait donc être regroupé dans une unique fonction "numeroterLienPrincipalToutSeulCommeUnGrand" dans laquelle le facteur avec/sans stockage serait un paramètre comme par exemple le nom du fichier où stocker (nom vide=sans stockage) ???

    Ah et sinon on ne flushe jamais stdin. Déjà c'est une attitude de faiblesse que de se dire "oh là là je ne sais pas ce que j'ai dans mon clavier donc pour plus de sûreté je vais le vider" parce que tu es sensé justement maitriser ton clavier à chaque instant et qu'un programme codé ainsi ne peut plus alors être employé dans une commande pipée (monde Unix/Linux) et surtout donc comme c'est une pratique à ne pas faire, la fonction fflush() (dont le but à la base est de finaliser les écritures en attente pour les flux sortants) n'est donc pas prévue pour traiter un flux entrant ce qui entraine un comportement indéterminé (ça peut marcher, ça peut ne pas marcher, ça peut marcher les jours pairs et ne pas marcher les jours impairs, et entre les deux ça peut faire n'importe quoi jusqu'à te formater ton disque dur => sens littéral de l'expression "comportement in dé ter mi né").
    Donc (et c'est probablement la cause de ton souci principal), chaque fois que tu fais saisir autre chose qu'une string (donc pour tout scanf autre que "%s") tu rajoutes en dessous getchar(). Ca supprimera de stdin le '\n' issu de ton <return> que tu tapes pour valider ta saisie et qui, n'étant pas récupéré, reste là planté comme un rosier et vient ensuite te polluer ta saisie suivante. C'est pas la solution la plus élégante mais c'est la plus simple et dans l'immédiat ça devrait résoudre ton souci.

    Et accessoirement on ne mélange pas la notation "snake case" (ma_variable_qui_fait_tout_toute_seule) avec la notation "camel case" (maVariableQuiFaitToutTouteSeule) mais là ce n'est que de l'effet typographique.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. comment ne pas enregistrer dans le fichier log?
    Par trotters213 dans le forum MS SQL Server
    Réponses: 14
    Dernier message: 21/03/2005, 14h56
  2. [LG]Enregistrements dans un fichier
    Par ticoude dans le forum Langage
    Réponses: 1
    Dernier message: 26/11/2004, 18h33
  3. [LG]supprimer un enregistrement dans un fichier
    Par Marcus2211 dans le forum Langage
    Réponses: 10
    Dernier message: 17/11/2003, 00h59
  4. Stocker un record dans un fichier
    Par ushu dans le forum Langage
    Réponses: 7
    Dernier message: 13/12/2002, 15h51
  5. enregistrer dans un fichier avec une appli mdi
    Par ferrari dans le forum C++Builder
    Réponses: 4
    Dernier message: 05/05/2002, 15h17

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