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 :

Problème lecture fichier dans structure


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut Problème lecture fichier dans structure
    Bonjour à tous,

    je suis en train de faire une application sous Linux en C en utilisant GTK pour l'interface graphique.
    Mon problème concerne la lecture d'un fichier banal contenant des valeurs numériques (N lignes sur 2 ou 3 colonnes) dans une structure NODE.
    Cela marche parfaitement si je mets ce code dans le main.c mais ne fonctionne plus lorsque je le déplace à l'intérieur d'une fonction callback.
    Je ne pense pas que ce soit une erreur avec GTK c'est pourquoi j'ai mis la discussion dans le forum C.
    Il doit y avoir un truc évident mais je ne le vois pas.
    Voici quelques éléments de code.

    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
     
    // structures dans fichier variables.h
    struct NODE {
    	double x;
    	double y;
            double z;
    };
     
    struct DATA {
    	struct NODE *pnodes;
    	struct WIDGET pwidgets;
    	int dime;
    	int Nnodes;
    	int Nelems;
    };
     
    // connection signal du clic dans le main.c
    struct DATA pdata;
    pdata.pnodes = NULL;
    pdata.dime = 2;
    pdata.Nnodes = 0;
    g_signal_connect(G_OBJECT(pdata.pwidgets.m_ouvrir), "activate", G_CALLBACK(callback_ouvrir_clic), &pdata);
     
    // fonction qui gère l'évènement du clic
    void callback_ouvrir_clic(GtkWidget *w, gpointer user_data) {
    	struct DATA *pdata = (struct DATA*)user_data;
    	pdata->pnodes = ouvrir_fichier_points(&pdata->dime, &pdata->Nnodes);
    }
     
    // fonction pour lire le fichier dans structure NODE
    struct NODE* ouvrir_fichier_points(int *dime, int *Nnodes) {
     
    int Npts = 0;
    struct NODE *p = NULL;
     
    FILE *file = fopen("./exemple_maillage/points.txt","r");
    if (file == NULL) {
    	printf("Erreur chargement fichier grille de points .txt");
    	exit(EXIT_FAILURE);
    }
    else {
    	// compter nombre de points (= lignes)
    	char *line = NULL;
    	size_t bufsize = 0;
    	while (getline(&line, &bufsize, file) != -1) Npts++;
    	free(line);
    	printf("%d\n", Npts);
    	// allocation mémoire tableau de noeuds
    	p = (struct NODE*)malloc(Npts * sizeof(struct NODE));
    	// retour début du fichier
    	fseek(file, 0, SEEK_SET);
    	// remplissage tableau de noeuds
    	for (int i = 0; i < Npts; i++) {
    		switch (*dime) {
    			case 2:
    				fscanf(file, "%lf %lf", &p[i].x, &p[i].y);
    			break;
    			case 3:
    				fscanf(file, "%lf %lf %lf", &p[i].x, &p[i].y, &p[i].z);
    			break;
    		}
    	}
    }
    fclose(file);
     
    FILE *fis = fopen("./exemple_maillage/grille.txt","w");
    for (int i = 0; i < Npts; i++) {
    	fprintf(fis, "%lf %lf\n", p[i].x, p[i].y);
    }
    fclose(fis);
     
    *Nnodes = Npts;
    return p;
    }
    Merci d'avance

  2. #2
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut
    Pour compléter un peu plus, le fichier que je réécris après la lecture (qui est sensé être identique à celui qui est lu) ne comporte que des zéros séparés par des virgules (0,0000) et parfois des nan.

    Merci

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Je n'ai pas vu de problème particulier dans ton code.
    Mais tu parles de virgules, le séparateur décimal est par défaut (dans la locale "C") le point. Si ton code s'attend à des virgules et qu'il trouve des points (ou inversement) tes nombres ne sont pas lisibles.

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut
    Merci pour ta réponse.

    C'est bien le problème, d'où sortent ces virgules ? Dans le fichier d'origine, ce sont bien des points qui sont les séparateurs décimaux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // fichier d'origine : points.txt
    0. 0.
    1. 0.
    2. 0.
    3. 0.
    4. 0.
    // fichier de sortie : grille.txt
    0,000000 0,000000
    0,000000 0,000000
    0,000000 0,000000
    0,000000 0,000000
    Encore une fois, si je mets le code dans le main, aucun problème : le fichier de sortie est identique à celui d'entrée.

    Il y a vraiment un truc qui m'échappe...

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut
    Je viens d'essayer avec d'autres fichiers et le résultat est identique.

    Lorsque je mets la fonction ailleurs que dans le callback, ça fonctionne. Mais j'ai vraiment du mal en comprendre en quoi le callback peut interférer dans la lecture d'un fichier ???

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Quelque chose doit changer la locale entre ton main() et ta callback.
    Essaie d'ajouter en début de callback setlocale(LC_ALL, "C"); pour remettre la locale "C".

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par js_naka Voir le message
    Lorsque je mets la fonction ailleurs que dans le callback, ça fonctionne.
    Alors ça fonctionne mais il y a quelques trucs qui me chiffonnent: déjà cette boucle sur getline(). Chaque boucle alloue de la mémoire pour stocker la ligne lue mais tu ne libères que la dernière allocation. Et toutes les autres lignes allouées ?
    Donc soit tu fais le free() dans la boucle, soit tu utilises une autre méthode pour compter les lignes (par exemple boucker sur fgetc() et ne compter que les '\n')

    Ensuite la fonction reçoit un pointeur "int *dime" représentant la dimension attendue (2D/3D). Mais pourquoi un pointeur ??? Ce n'est pas grave en soi sauf que tu ne pourras pas appeler la fonction en lui passant simplement "2" ou "3" comme ce serait le cas avec un simple int. Et vu que tu ne modifies pas le pointé, le pointeur ne sert en fait pas à grand chose.

    Citation Envoyé par js_naka Voir le message
    Mais j'ai vraiment du mal en comprendre en quoi le callback peut interférer dans la lecture d'un fichier ???
    Ca ne peut venir que de la façon dont il appelle la fonction.
    Donc lui il reçoit en paramètre un gpointer user_data (ça ressemble fort à un pointeur dont l'étoile est masquée derrière un type, ce qui est super dangereux !!!), adresse qui est alors copiée dans un pointeur struct DATA. Ca veut dire que tu considères que cette adresse "user_data" que le callback reçoit est donc l'adresse d'un truc bel et bien formaté comme un "struct DATA". Parce que si ce n'est pas le cas, ce n'est pas un cast qui va changer cela.
    Ensuite tu appelles "ouvrir_fichier()" (un nom de fonction bien peu en adéquation avec le travail qu'elle fait) en lui passant en entrée ce fameux pointeur sur un int censé valoir "2" ou "3". As-tu vérifié si c'était bien le cas ?
    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]

  8. #8
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut
    Incroyable, je viens de faire ce que tu me conseillais dalfab et ça fonctionne. Le fichier de sortie est bien identique à celui d'entrée.
    Même si le problème est résolu, j'aimerais savoir ce qui est susceptible de provoquer un changement de la locale ?

    Pour te répondre Sve@r, en fait, je souhaite passer un pointeur int car je vais ensuite modifier le code pour détecter si le fichier a 2 ou 3 colonnes et pouvoir modifier la valeur de dime automatiquement sachant que je ne peux pas la retourner vu que je retourne déjà le pointeur struct NODE*.
    Concernant la potentielle dangerosité de gpointer user_data, ce n'est pas moi mais GTK qui impose que si on veut passer un argument à un callback, ça passe par gpointer qui est un void* si je me souviens bien.
    Pour ta remarque concernant le getline et l'allocation qui n'est pas vidée pendant la boucle, peut-être mais j'ai vu pas mal d'exemples d'utilisation de cette fonction qui libéraient après la boucle genre ici qui a raison ?

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par js_naka Voir le message
    Même si le problème est résolu, j'aimerais savoir ce qui est susceptible de provoquer un changement de la locale ?
    A tout hasard, la callback doit récupérer la locale de gtk, ce qui n'arrive pas quand tu appelles ta fonction direct.

    Citation Envoyé par js_naka Voir le message
    Pour ta remarque concernant le getline et l'allocation qui n'est pas vidée pendant la boucle, peut-être mais j'ai vu pas mal d'exemples d'utilisation de cette fonction qui libéraient après la boucle genre ici qui a raison ?
    Ah oui, j'avais zappé. Effectivement getline fait du realloc et non du malloc à répétition. Ok, le free final est suffisant.
    Toutefois, les opérations realloc peuvent être coûteuses en temps (sans compter que "normalement" il faut tester ce genre d'opération). Si c'est juste pour compter les lignes, tu peux passer par un buffer via fread() et compter les '\n'.
    Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char buffer[SZ];
    while ((n=fread(buffer, sizeof(char), SZ, file)) > 0) {
    	char *pt;
    	size_t i;
    	for (i=0, pt=buffer; i < n; i++, pt++) {
    		if (*pt == '\n') Npts++;
    	}
    }
    Puis tu mets ça dans une fonction dédiée et si elle prend soin de
    • mémoriser la position courante
    • se déplacer au début du fichier pour compter
    • revenir à la position mémorisée en fin de fonction

    elle pourra alors être appelée dans toutes les situations.

    Ah, au fait, à cet endroit pas besoin de "else" puisque tu sors si le fichier n'a pas été ouvert (tu gagnes un niveau d'indentation).
    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]

  10. #10
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2015
    Messages : 42
    Par défaut
    A tout hasard, la callback doit récupérer la locale de gtk, ce qui n'arrive pas quand tu appelles ta fonction direct.
    Ok, je vais regarder de ce côté là.

    Merci pour tes conseils et le petit bout de code. Je vais implémenter ça.

    Merci à vous deux Sve@r et dalfab pour votre aide.

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

Discussions similaires

  1. Problème lecture fichier dans une arborescence de dossiers
    Par africanwinners dans le forum Langage
    Réponses: 5
    Dernier message: 05/12/2014, 12h59
  2. problème lecture fichier avec structures de données
    Par hannibal007 dans le forum Débuter
    Réponses: 3
    Dernier message: 09/04/2013, 19h51
  3. Problème lecture colonne dans un fichier .prn
    Par nilsmatlab dans le forum MATLAB
    Réponses: 2
    Dernier message: 07/07/2011, 16h57
  4. [D6] Problème lecture fichier AVI dans TAnimate
    Par Lung dans le forum Composants VCL
    Réponses: 9
    Dernier message: 21/01/2010, 15h02
  5. [PERL] Problème lecture/écriture dans un fichier
    Par LE NEINDRE dans le forum Langage
    Réponses: 4
    Dernier message: 17/08/2005, 13h15

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