[Résolu]Ouverture de fichiers et fonctions

Ouverture de fichiers et fonctions [Résolu] - C - Programmation

Marsh Posté le 19-05-2009 à 16:03:53    

Bonjour,  :jap:  
 
cette situation traine dans ma tête depuis trop longtemps, sans succès je n'ai pu la résoudre.
Je souhaite ouvrir un fichier et dédier une fonction à l'ouverture de ce fichier.
On balance l'emplacement du fichier dans la fonction et celle ci s'occupe d'ouvrir le fichier.
On reste simple, on considère qu'il existe et qu'il contient des données, l'emplacement est valable aussi.
Donc :  

Code :
  1. FILE* ouvre_fichier(char * adresse)
  2. {
  3.     FILE * fichier = NULL;
  4.     if ((fichier = fopen(adresse,'r')) != NULL)
  5.     {
  6.         printf("All good.\n" );
  7.         return fichier;
  8.     }
  9.     else
  10.     {
  11.        printf("Erreur ouverture fichier\n" );
  12.        return NULL; //On peut forcer l'arret du programme aussi...
  13.     }
  14. }


 
Cette fonction sera donc appelée à chaque fois que je souhaite ouvrir un fichier.
(Je souhaite déclarer un pointeur localement puis agrandir sa portée)
A l'exécution, des erreurs de violation d'accès sont signalés.
 
Il y a effectivement un problème de portée du pointeur fichier.
Les mots clés extern ou static peuvent-ils venir à mon aide???


Message édité par kheel le 19-05-2009 à 22:55:04
Reply

Marsh Posté le 19-05-2009 à 16:03:53   

Reply

Marsh Posté le 19-05-2009 à 17:09:52    

l'exemple que tu donnes a l'air correct, donne un exemple complet de code qui te pose problème.


---------------
last.fm
Reply

Marsh Posté le 19-05-2009 à 17:23:07    

man fopen
 
les arguments ne sont pas bons.

Reply

Marsh Posté le 19-05-2009 à 17:49:49    

Contexte : je souhaite ouvrir un fichier, le copier dans un buffer et afficher ce buffer sur la console.
Pour cela voici le main ()

Code :
  1. int main (int argc, char *argv[])
  2. {
  3.     char adr[TAILLE_MAX];
  4.     fgets (adr, TAILLE_MAX, stdin);
  5.     retire_chariot (adr);
  6.     printf ("length : %d\n\n", strlen (adr));
  7.     affiche_fichier (adr);
  8.     return 0;
  9. }
 

Fonctions:

  • void retire_chariot (char*); ==> retire '\n' à la fin de la chaine saisie par l'utilisateur
  • int affiche_fichier (char *); ==> ouvre le fichier, le copie dans un buffer et l'affiche sur la console.
  • FILE* ouvre_fichier(char * adresse); ==> ouvre le fichier et renvoie le pointeur fichier associé au fichier ouvert.


Ci joint les sources.

 

Le problème n'existerai pas si j'utiliserais fopen() directement dans affiche_fichier(...), je souhaite comprendre pourquoi le prog plante...

 

Edit: effectivement pour fopen, c'est corrigé mais cette erreur n'est pas à l'origine du plantage.


Message édité par kheel le 19-05-2009 à 17:53:44
Reply

Marsh Posté le 19-05-2009 à 18:40:51    

comme l'a fait judicieusement remarquer Taz, tu as une erreur au niveau des arguments que tu envoies à fopen dans ta fonction ouvre_fichier.


---------------
last.fm
Reply

Marsh Posté le 19-05-2009 à 19:32:20    

Edit: [:matleflou] Ouah, j'ai cliqué sur éditer au lieu de répondre (et sur le mauvais message en plus).
 
Bah, chais pas ce que tu fais. Mais le programme suivant, récupérer de ton lien et corriger de deux ou trois erreurs, marche_chez_moi™ (WinXP, mais il n'y aucune raison que ça marche par ailleurs):
 
Bref, défini ce que tu appelles "plantage". Vois-tu un SIGSEGV ou SIGTRAP en lançant le programme dans un debugger ? Arrêt brutal au milieu du code ? Si tu as valgrind, y a t-il des warnings particuliers ?
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define TAILLE_MAX 512
  5. int affiche_fichier (char *);
  6. void retire_chariot (char*);
  7. FILE* ouvre_fichier(char *);
  8. /*Juste pour tester*/
  9. int main (int argc, char *argv[])
  10. {
  11.     char adr[TAILLE_MAX];
  12.     fgets (adr, TAILLE_MAX, stdin);
  13.     retire_chariot (adr);
  14.     printf ("length : %d\n\n", strlen (adr));
  15.     affiche_fichier (adr);
  16.     return 0;
  17. }
  18. /** Ouvre le fichier **/
  19. /** déclare un FILE* et le renvoie **/
  20. /** c'est ici que le problème se pose **/
  21. FILE* ouvre_fichier(char * adresse)
  22. {
  23.     FILE * fichier = NULL;
  24.     if ((fichier = fopen(adresse,"r" )) != NULL)
  25.     {
  26.         printf("All good.\n" );
  27.         return fichier;
  28.     }
  29.     else
  30.     {
  31.         printf("Erreur ouverture fichier\n" );
  32.         exit(1);
  33.     }
  34.     return NULL;
  35. }
  36. /** Ouvre et affiche le contenu du fichier,l'adresse est donnée en paramètres**/
  37. int affiche_fichier (char * adresse)
  38. {
  39.     FILE * fichier = NULL;
  40.     char buffer[TAILLE_MAX];
  41.     //fichier = fopen (adresse, "r" ); //tout le problème se pose si on décommente cette ligne...
  42.     fichier=ouvre_fichier(adresse);
  43.     if (fichier != NULL)
  44.     {
  45.         printf ("Fichier_ouvert\n" );
  46.         while (fgets (buffer, TAILLE_MAX, fichier) != NULL)
  47.         {
  48.             printf("%s", buffer);
  49.         }
  50.         fclose (fichier);
  51.     }
  52.     else
  53.     {
  54.         printf ("Erreur ouverture fichier" );
  55.     }
  56.     return 0;
  57. }
  58. /** Retire le retour charriot de la chaine entrée, **/
  59. void retire_chariot (char * ligne)
  60. {
  61.     int i=0;
  62.     if (ligne != NULL)
  63.         while (ligne[i++] != '\n');
  64.     ligne[i - 1] = '\0';
  65. }


Message édité par tpierron le 19-05-2009 à 20:22:41
Reply

Marsh Posté le 19-05-2009 à 20:02:59    

J'ai rajouté exit au dernier moment, ce n'est pas la cause du plantage, commentez le pour voir.
Pour fopen, oui il y a une erreur dans le 2eme argument mais ce n'est pas la cause du plantage. (Cf. post précédent.)
De toute façon, le fichier à ouvrir existe et le programme fonctionne parfaitement en utilisant fopen() au sein de affiche_fichier().
C'est le passage de fopen (et de la déclaration de FILE * fichier;) dans une fonction a part (ouvrir_fichier()) qui pose problème.
 
Je ré-explique le problème :  

  • chaque variable "vit" dans le bloc où elle a été déclarée, ceci est aussi valable pour un pointeur.
  • même si j'arrive à appeler ce pointeur hors de son bloc, l'appel amènera à une exception.


En considérant ces deux énoncés est-il possible d'appeler un pointeur en dehors de son bloc sans utiliser de variables globales.
Dans ce cas là pouvez-vous m'expliquer le fonctionnement de fonctions qui créent et renvoient un pointeur (fopen, fgets, ...).

Reply

Marsh Posté le 19-05-2009 à 20:16:58    

kheel a écrit :


Je ré-explique le problème :  

  • chaque variable "vit" dans le bloc où elle a été déclarée, ceci est aussi valable pour un pointeur.

Oui... mais le pointeur pointe (d'où son nom) vers une zone mémoire accessible de partout (sauf si t'as commis l'erreur de le faire pointer vers une autre variable locale)
 

kheel a écrit :

En considérant ces deux énoncés est-il possible d'appeler un pointeur en dehors de son bloc sans utiliser de variables globales.


Le pointeur non. La variable qui stockait l'adresse a disparu. Mais si cette adresse est stockée dans une seconde variable (ou renvoyée par la fonction), tu peux toujours aller toper ce qui est pointé car ça, ça n'a pas disparu !!!
 
Un exemple tout simple

Code :
  1. void modif(int*);
  2.  
  3. int main()
  4. {
  5.    int i=10;           // Je déclare un int
  6.    printf("i=%d\n", i);    // Je l'affiche pour voir
  7.  
  8.    modif(&i);               // Je passe l'adresse de ce int à une fonction
  9.    printf("i=%d\n", i);    // Je l'affiche pour voir
  10.    return 0;
  11. }
  12.  
  13. void modif(int* pt)
  14. {
  15.    // La fonction a reçu l'adresse d'un int. Elle stocke cette adresse dans une variable de type "int étoile"
  16.    // Pourquoi "int étoile" ? Parce que "ce qu'il y a au bout de pt" (donc *pt) est de type "int".
  17.    // Et donc si "*pt" est de type "int", alors "pt" est de type "int... étoile" (comme pour une équation, si le mot "étoile" disparait de la phrase d'un coté alors je la remets de l'autre coté)
  18.    // On est d'accord: pt est local
  19.  
  20.    (*pt)=500;        // Je rentre 500 dans la case pointée par pt.
  21.  
  22.  
  23. }  // Fin de la fonction: pt a disparu... mais pas ce qu'il y avait à "étoile pt" !!!


 
L'exemple inverse... mais qui foire

Code :
  1. int *modif();
  2.  
  3. int main()
  4. {
  5.    int *pt;           // Je déclare un pointeur destiné à recevoir un int
  6.  
  7.    pt=modif();               // Je récupère dans pt ce que me renvoie ma fonction
  8.    printf("*pt=%d\n", *pt);    // Je l'affiche pour voir
  9.    return 0;
  10. }
  11.  
  12. int* modif()
  13. {
  14.     int i;                // Je déclare i (local)
  15.  
  16.     i=500;             // Pas de pb
  17.  
  18.    return(&i);        // Je renvoie l'adresse de ma variable... alors que celle-ci va disparaitre !!!
  19. }
  20. // Fin de la fonction: i a disparu, sera réutilisé par le compilo pour autre chose mais j'ai récupéré son adresse
  21. // Cette adresse ne correspond à plus rien de valide !!!


 
Le 3° comme le 2° mais qui fonctionne

Code :
  1. int *modif();
  2.  
  3. int main()
  4. {
  5.    int *pt;           // Je déclare un pointeur destiné à recevoir un int
  6.  
  7.    pt=modif();               // Je récupère dans pt ce que me renvoie ma fonctionfonction
  8.    printf("*pt=%d\n", *pt);    // Je l'affiche pour voir
  9.    return 0;
  10. }
  11.  
  12. int* modif()
  13. {
  14.     int *pt;            // Je déclare un pointeur (local)
  15.  
  16.     pt=malloc(sizeof(int));    // J'y alloue de la mémoire pour stocker un int
  17.     // Cette allocation est prise dans la mémoire globale du programme et pas dans la mémoire locale de la fonction
  18.  
  19.     (*pt)=500;             // Pas de pb
  20.  
  21.    return(pt);        // Je renvoie l'adresse de la zone allouée - Cette zone ne disparaitra pas (même si pt disparait) !!!
  22. }


 

kheel a écrit :

Dans ce cas là pouvez-vous m'expliquer le fonctionnement de fonctions qui créent et renvoient un pointeur (fopen, fgets, ...).


1) quand tu fais fp=fopen("...", "r/w/a" )
a) la fonction commence par allouer une zone mémoire suffisante pour y stocker les outils de manipulation du fichier
b) la fonction y stocke lesdits outils. On pourra y trouver par exemple l'endroit du fichier où tu te trouves, la taille du fichier, le mode d'accès (r/w), bref divers outils quoi
c) la fonction te renvoie l'adresse de cette zone mémoire (qui se trouve dans la mémoire du programme donc accessible de partout)
 
2) quand tu fais du fgets(..., ..., fp) => la fonction fgets() récupère cette zone mémoire donc peut aller utiliser les outils qui y sont pour lire le fichier et te renvoyer les data
 
3) quand tu fais fclose(fp) => la fonction fclose libère la zone mémoire


Message édité par Sve@r le 19-05-2009 à 20:35:15

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 19-05-2009 à 22:54:35    

Merci de m'avoir éclaircit sur ces points.
Effectivement la déclaration d'un pointeur restait locale au bloc en cours mais la zone allouée reste disponible globalement, pour peu qu'on ai son adresse.
 
 
Problème résolu.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed