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 de lecture fichier


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 116
    Points : 49
    Points
    49
    Par défaut Problème de lecture fichier
    Bonjour,

    J’ai besoin d’écrire un programme en c permettant de lire un fichier .txt. Les données dans le fichier sont présentées à l’intérieur sont présentées de la manière suivante :

    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
     
    0      0               0
    1      -90.618         299.859 
    2      -480.287        -366.363
    3      -106.647        -202.037
    4      -134.373        -364.665
    5      -196.116        -43.097
    6      455.724         -383.012
    7      -232.731        -467.685
    8      -138.385        -61.276
    9       247.014        -461.857
    10      74.257         373.238
    11      -95.265        164.968
    12      -211.651       -147.830
    13      -265.178       499.830
    14      -126.376       330.654
    15      -267.075       499.830
    16      -486.620       56.890
    17      -368.762       -466.753
    18      66.033         -456.440
    19      234.876         57.177
    20      22.466          -236.939
    21      349.490         -205.735
    22        302.043         -70.028
    23        23.194          432.094
    24       384.468          11.208
    Ensuite je dois effectuer une opération de calcul et afficher les résulats sur l’écran.

    Voici le code que j’ai fait.
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    #include<stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
     
    typedef struct
    {
    	int x;	//abscisse
    	int y; //ordonnée
     
    }Client;
     
     
    Client donnees_clients[24];
    int main()
    {
     
    	FILE *file = NULL;
    	int i, j; 
     
    double distance[24][24];
     
     
     
     
    	if((file = fopen("D:\\calcul_distance_euclidienne\\calcul_distance_euclidienne\\donnees.txt", "r")) == NULL)/*ouverture du fichier en lecture*/
    		printf("Error: impossible d'ouvrir fichier donnees.txt\n");
     
    	else//non
    	{
     
    		while(fgetc(file)!='\n'); 
    		for(i=0;i<24;i++)
    		{
     
     
    			j=fscanf(file,"%i %i %i\n",&i,&donnees_clients[i].x,&donnees_clients[i].y);
    			if(j==EOF)
    			{
    			printf("fin de fichier !\n");
    			break;
    			}
     
     
    			printf("donnees_clients[%i]\n\tx=%i\n\ty=%i\n", i, donnees_clients[i].x,donnees_clients[i].y);
    		}
     
     
     
     
    			for(i=0; i<24; i++)
    			{
    				for(j=0;j<i+1;j++)
    				{
    					if(i==j)
    					{
    						distance [i][j]= 0;
     
    					}
     
    					else
    					{
    						for(i=0; i<24; i++)
    						{
    							for(j=0;j<i+1;j++)
    							{			
    								distance [i][j] = distance [j][i];
    								distance[i][j]= sqrt((donnees_clients[i].x - donnees_clients[j].x)*(donnees_clients[i].x - donnees_clients[j].x)+(donnees_clients[i].y - donnees_clients[j].y)*(donnees_clients[i].y - donnees_clients[j].y));
    							}
    						}
     
    					}
    				}
    			  }
    			for(i=0; i<24; i++)
    			{
    				for(j=0;j<24;j++)
    				{
    					printf("distance[%i][%i] = %4.2lf\n\n ",i, j, distance[i][j]);
    				}
    			}
     
     
     
    	fclose(file);
    	printf("\n fin de lecture\n");
    	}
     
      getchar(); 
    return(0);
    }
    Le programme se compile. Toutefois, il ne donne pas les bons résultats. Je crois que lors de l'écriture il lit que la première ligne et le premier caractére. Il ne passe pas au caractère suivant pour le lire. Je ne parviens pas à corriger celà

    Quelqu’un pourrait-il m’aider ?
    Merci.

  2. #2
    Membre actif
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juillet 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 121
    Points : 217
    Points
    217
    Par défaut
    Bonjour,

    Si je peux me permette une petite remarque.

    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j=fscanf(file,"%i %i %i\n",&i,&donnees_clients[i].x,&donnees_clients[i].y);
    tu demandes a fscanf de lire 3 entiers.

    et si on regarde ton fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    0      0               0
    1      -90.618         299.859

    seule ta premiere ligne contient des entiers la deuxieme serait plutot
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j=fscanf(file,"%i %f %f\n",&i,&donnees_clients[i].x,&donnees_clients[i].y);
    A voir peut etre deja de ce coté

    Et sinon pour ta condition de sortie du while, j'aurais plutot vu un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    while(!feof(file)){
     
    blabla
    }
    Cordialement
    Je connais des gens qui ne sont pas aware, il ne sont pas qu courant. il ne sont pas a l'attention de savoir qu'ils existent.
    "J-C Van dam"

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Le plus simple, c'est de lire la ligne courante avec fgets (il faut se servir de l'adresse retournée et la comparer à NULL pour savoir si la fin du fichier est atteinte ou si une erreur s'est produite), puis d'utiliser par exemple strtol pour le premier champs puis strtod pour les deux suivants. Tout ceci dans une boucle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while ( fgets (...) != NULL )
    {
    ...
    }
    strtod : http://www.linux-kheops.com/doc/man/.../strtod.3.html
    strtol : http://www.linux-kheops.com/doc/man/.../strtol.3.html
    fgets : http://www.linux-kheops.com/doc/man/...ets.3.txt.html

    Et sinon pour ta condition de sortie du while, j'aurais plutot vu un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    while(!feof(file)){
     
    blabla
    }
    feof ne fait pas ce que l'on croit. Lorsque (par exemple) fgets renvoie NULL, on peut ensuite utiliser la fonction feof pour s'assurer que NULL a été renvoyé à cause de la fin de fichier atteinte et non à cause de quelque chose d'autre.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 116
    Points : 49
    Points
    49
    Par défaut
    Voici ce que j'ai arrivé à faire.
    J'ai ré-ecris un petit programme qui pemet de lire de chaine de caractères dans un fichier de format ci-haut et afficher ses données.
    Toutefois, ce dernier ne se compile pas. Je ne vois pas où il est le problème?

    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
    #include<stdio.h>
    #include <stdlib.h>
     
     
     
     struct Client
    {
    	double x;	//abscisse
    	double y; //ordonnée
     
    };
     
     
    struct Client k[24];
    int main()
    {
     
    	FILE *file = NULL;
    	int i; 
     
    	if((file = fopen("D:\\donnees.txt", "r") == NULL)/*ouverture du fichier en lecture*/
    		printf("Error: impossible d'ouvrir fichier donnees.txt\n");
     
    	else//non
     
     
    	{
    		while(fgets(struct Client, 25, file)!= NULL)
     
    			printf("%ld %ld",k[i].x,k[i].y);
     
     
    		fclose(file);
    	}
     
     
     
    getchar(); 
    return(0);
    }
     
     
     
     
    }
    Par ailleurs, je ne sais pas comment utiliser la fonction strtol.

    Merci par avance de vos aides.

  5. #5
    Membre actif Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Points : 223
    Points
    223
    Par défaut
    La fonction fgets() attend en premier paramètre un char*, tu ne peux donc mettre un struct Client.
    Autre petite remarque, i n'est pas initialisé, ton programme va donc très certainement donner des résulats "amusants".
    Pour utiliser strtol le plus simplement du monde:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int mon_nombre;
    mon_nombre=strtol(ma_chaine,NULL,10);

  6. #6
    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
    Citation Envoyé par laureat Voir le message
    Toutefois, ce dernier ne se compile pas. Je ne vois pas où il est le problème?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(fgets(struct Client, 25, file)!= NULL)
    En dehors de la remarque de quetzacoatl sur le type attedu par fgets, struct Client est un type, pas une variable. Où as-tu vu qu'on passait à une fonction un type comme paramètre ?
    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]

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 116
    Points : 49
    Points
    49
    Par défaut
    Citation Envoyé par quetzacoatl Voir le message
    La fonction fgets() attend en premier paramètre un char*, tu ne peux donc mettre un struct Client.
    Autre petite remarque, i n'est pas initialisé, ton programme va donc très certainement donner des résulats "amusants".
    Pour utiliser strtol le plus simplement du monde:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int mon_nombre;
    mon_nombre=strtol(ma_chaine,NULL,10);
    ouh!
    Vous avez raison.


    J'ai utilisé le fscanf là.
    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
    #include<stdio.h>
    #include <stdlib.h>
     
     
     
     struct Client
    {
    	int num;
    	double x;	//abscisse
    	double y; //ordonnée
     
     
    };
     
     
    struct Client k[25];
    int main()
    {
     
    	FILE *file = NULL;
    	int i=0; 
     
    	if((file = fopen("D:\\donnees.txt", "r")) == NULL)/*ouverture du fichier en lecture*/
    	{
    		printf("Error: impossible d'ouvrir fichier donnees.txt\n");
    	}
     
    	else//non
     
     
    	{
     
    		while(fscanf(file, "%d % f %f\n", &k[i].num,&k[i].x,&k[i].x)== 25);//lecture de données types doubles
     
    		fclose(file);
    	}
     
    			printf("%d%f%f\n",k[i].num, k[i].x,k[i].y);
    			i++;
     
     
     
     
     
    getchar(); 
    return 0;
    }
    Ca se compile mais j'obtiens ceci
    num = 0
    k[0].x = 0
    k[0].y = 0

    Il ne passe pas aux valeurs suivants!

    Merci d'avance de vos indices.

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( ( file = fopen("D:\\donnees.txt", "r") ) == NULL)
    Attention à la priorité des opérateurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fgets(struct Client, 25, file)
    Cela n'a aucun sens. Le premier paramètre, c'est le buffer. Donner un type n'a aucun sens.

    Par ailleurs, je ne sais pas comment utiliser la fonction strtol.
    J'ai donné le lien du man dans mon précédent message.

    * Le premier paramètre correspond à la chaine contenant le nombre à convertir.
    * Le second paramètre est l'adresse d'un pointeur sur "char", ce qui permet à la fonction de modifier sa valeur et qui permet de (pour notre cas) :
    1) savoir si la fonction a réussi la conversion
    2) de bien se positionner dans la chaine pour les conversions suivantes
    * Le troisième paramètre correspond à la base, ici 10 (base décimale).

    Si la fonction échoue, "endptr" vaut "nptr". C'est bien pratique.

    Grosso modo, on peut faire quelque chose du style :
    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
    char tab[256];
    char *pchaine;
    char *endptr;
    int valeur1;
     
    ...
     
    while ( fgets(tab,256,fichier) != NULL )
    {
    	pchaine = tab ;
     
    	valeur1 = strtol( pchaine , &endptr , 10 );
    	if ( pchaine == endptr ) /* erreur : conversion echouee */
    	{
    		printf("erreur\n");
    		continue;
    	}
     
    	pchaine = endptr; /* permet de se positionner dans la chaine pour convertir le deuxième nombre */
     
    	...
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int mon_nombre;
    mon_nombre=strtol(ma_chaine,NULL,10);
    Le problème, c'est qu'avec NULL, on ne peut pas savoir si la conversion a réussi et on ne peut pas savoir où se positionner dans la chaine pour convertir le nombre suivant.

    @ laureat :
    Si tu peines avec ma méthode, tu peux malgré tout utiliser la méthode fgets/sscanf et oublier les fonction strto*, ce qui a l'avantage de se coder en très peu de lignes. (Je n'aime pas trop *scanf en fait). Mais surtout n'oublie pas de vérifier si toutes les conversions ont réussi (la fonction renvoie 3 dans ce cas, car 3 valeurs par lignes).
    Choisis la méthode que tu préfères. Soit la mienne, soit celle-ci. Les goûts et les couleurs...

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    116
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 116
    Points : 49
    Points
    49
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    En dehors de la remarque de quetzacoatl sur le type attedu par fgets, struct Client est un type, pas une variable. Où as-tu vu qu'on passait à une fonction un type comme paramètre ?
    Je l'ai vu dans un exemple avec la fonction fread
    D'ailleurs j'ai essayé avec cette fonction mais ca ne donne pas les bons résultats.
    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
    #include<stdio.h>
    #include <stdlib.h>
     
     
     
     struct Client
    {
    	int num;
    	double x;	//abscisse
    	double y; //ordonnée
     
     
    };
     
     
    struct Client k[25];
    int main()
    {
     
    	FILE *file = NULL;
    	int i=0; 
     
    	if((file = fopen("D:\\donnees.txt", "r")) == NULL)/*ouverture du fichier en lecture*/
    	{
    		printf("Error: impossible d'ouvrir fichier donnees.txt\n");
    	}
     
    	else//non
     
     
    	{
     
    		fread(k, sizeof(struct Client), 25, file);//lecture de données types doubles
     
    		fclose(file);
    	}
     
    			printf("%d%f%f\n",k[i].num, k[i].x,k[i].y);
    			i++;
     
     
     
     
     
    getchar(); 
    return 0;
    }

  10. #10
    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
    Citation Envoyé par laureat Voir le message
    Je l'ai vu dans un exemple avec la fonction fread
    D'ailleurs j'ai essayé avec cette fonction mais ca ne donne pas les bons résultats.
    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
    #include<stdio.h>
    #include <stdlib.h>
     
     
     
     struct Client
    {
    	int num;
    	double x;	//abscisse
    	double y; //ordonnée
     
     
    };
     
     
    struct Client k[25];
    int main()
    {
     
    	FILE *file = NULL;
    	int i=0; 
     
    	if((file = fopen("D:\\donnees.txt", "r")) == NULL)/*ouverture du fichier en lecture*/
    	{
    		printf("Error: impossible d'ouvrir fichier donnees.txt\n");
    	}
     
    	else//non
     
     
    	{
     
    		fread(k, sizeof(struct Client), 25, file);//lecture de données types doubles
     
    		fclose(file);
    	}
     
    			printf("%d%f%f\n",k[i].num, k[i].x,k[i].y);
    			i++;
     
     
     
     
     
    getchar(); 
    return 0;
    }
    C'est normal que fread ne marche pas. fread est fait pour des fichiers binaires. C'est à dire des fichiers qui contiennent leurs datas sous forme binaire (au format lisible par la machine). Tu cherches un int et 2 doubles donc fread() ira lire 4 + 8 + 8 = 20 octets et stockera ces octets direct live dans ta structure.

    Or ton fichier n'est pas binaire mais ascii. Il est dans un format lisible par un humain. C'est à dire que s'il y est écrit "5 12.5 24.25" cela fait 12 caractères (plus le return de fin de ligne) soit 13 octets.

    Si tu veux pouvoir utiliser ta ligne pour remplir ta structure, il te faut
    1) lire la ligne avec fgets() => fgets() lit le fichier texte jusqu'au return
    2) utiliser la ligne lue via sscanf() pour remplir ta structure => sscanf() lit la chaine entrée et en extrait les infos comme si elles venaient du clavier pour remplir les variables

    Il y a d'autres méthodes bien sûr. Tu peux utiliser strtok() qui découpe ta chaine en "tokens" (éléments identifiés) que tu peux ensuite convertir en int ou double via strtoul() ou strtod(). Mais la base, c'est fgets()...
    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]

Discussions similaires

  1. problème de lecture fichier
    Par Fahmi06 dans le forum Qt
    Réponses: 1
    Dernier message: 29/10/2007, 09h20
  2. Problème de lecture fichier texte
    Par Draconic dans le forum Visual C++
    Réponses: 1
    Dernier message: 05/08/2007, 18h00
  3. Problème STL lecture fichier texte
    Par Bourrine dans le forum VC++ .NET
    Réponses: 4
    Dernier message: 03/04/2007, 11h57
  4. [C#-XML] - Problème de lecture fichier XML
    Par Gloups dans le forum Windows Forms
    Réponses: 9
    Dernier message: 08/08/2006, 00h40
  5. problème de lecture fichier
    Par Polo40 dans le forum C
    Réponses: 8
    Dernier message: 30/03/2006, 10h58

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