passage d'un buffer comme parametre

passage d'un buffer comme parametre - C - Programmation

Marsh Posté le 24-11-2005 à 23:47:59    

J'ai un souci pour passer un buffer comme parametre d'une fonction.
Le but de la fonction est d'ouvrir un fichier, de creer un buffer de taille adaptée, d'y copier le contenu du fichier, de fermer le fichier, et de retourner l'adresse de ce buffer.
 
Jusqu'a présent, je faisait ca sans probleme directement dans le main. La, j'ai voulu en faire une fonction, pour reutiliser plus facilement, mais ca ne marche pas.  
 
La messagebox dans la fonction me donne l'affichage correct du contenu du fichier test.txt, par contre la messagebox dans main indique n'importe quoi, et ca plante si on écrit dans le buffer contenu_fichier.
 
Apparement l'adresse n'est pas renvoyée correctement, mais je ne voiss pas pourquoi. Je comprends parfaitement les notions de pointeur, par contre je me mélange un peu avec la notation (suis pas toujours très sur quand il faut mettre juste le nom, ou y rajouter un * ou un &, je sais qui fait quoi, mais ca ne m'empeche pas de me melanger les pinceaux).  
 
A coup sur, il y a une erreur évidente qui devrait me crever les yeux, mais rien n'y fait, je ne la voit pas. Si quelqu'un pouvait m'eclairer !
 
Merci d'avance.
 
-> (win98SE, devcpp 4.9.9.0 )
 
 

Code :
  1. #define _WIN32_WINNT 0x0500
  2. #include <windows.h>
  3. int loadFile ( char *nomFichier, char *buffer )
  4. {
  5.     HANDLE hFichier;
  6.     DWORD dwTailleFichier;
  7.     DWORD dwOctetsLus;
  8.     hFichier = CreateFile ( nomFichier, GENERIC_READ | GENERIC_WRITE,
  9.                             FILE_SHARE_READ, NULL, OPEN_EXISTING,
  10.                             FILE_ATTRIBUTE_NORMAL, NULL ) ;
  11.    
  12.     if(hFichier == INVALID_HANDLE_VALUE) { return 0; }
  13.    
  14.     dwTailleFichier = GetFileSize( hFichier, NULL );
  15.     buffer = (char*) malloc (dwTailleFichier + 1); 
  16.     ReadFile(hFichier, buffer, dwTailleFichier, &dwOctetsLus, NULL);
  17.    
  18.     /////////////////////////////
  19.     // cette messagebox donne le contenu correcte du fichier
  20.    
  21.     MessageBox  // affichage pour controle
  22.         (
  23.         NULL,   // handle of owner window
  24.         buffer, //contenu_fichier  
  25.         "Buffer", // address of title of message box
  26.         MB_OK | MB_ICONINFORMATION
  27.         ); 
  28.    
  29.     CloseHandle(hFichier);   
  30.     return 1; // Tout s'est bien passé  
  31.    
  32. }    // fin load file
  33. /////////////////////////////////////////////////////
  34. //                                                 //
  35. //       MAIN                                      //
  36. //                                                 //
  37. /////////////////////////////////////////////////////
  38. int STDCALL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
  39. {
  40.     char nom_fichier [] = "D:\\test\\TEST.txt";
  41. //// ouvrir le fichier et le charger
  42. //         
  43.     char *contenu_fichier;
  44.     loadFile ( nom_fichier, contenu_fichier ); 
  45.    
  46.     /////////////////////////////
  47.     // cette messagebox donne un affichage bizarre (du genre ^K;*  ) cad n'importe quoi
  48.     // en plus le programme plante si on essaye d'ecrire dans le buffer contenu_fichier
  49.    
  50.     MessageBox  // affichage du contenu
  51.         (
  52.         NULL,   // handle of owner window
  53.         contenu_fichier, //contenu_fichier,           // address of text in message box
  54.         "Contenu du Fichier", // address of title of message box
  55.         MB_OK | MB_ICONINFORMATION           // style of message box
  56.         );
  57.    
  58. } // fin main


 
note au modos : dsl si jamais le message apparait deux fois, mais le premier coup je l'ai pas vu apparaiter dans la liste.

Reply

Marsh Posté le 24-11-2005 à 23:47:59   

Reply

Marsh Posté le 25-11-2005 à 05:20:37    

Il faut soit que ta fonction loadFile prennent en argument un char ** et que tu l'appelles avec  loadFile(nom_fichier, &contenu_fichier), soit qu'elle retourne le char * (je ferais plutôt comme ça). Parce que dans ton code, loadFile ne met pas contenu_fichier à jour dans l'appelant.

Reply

Marsh Posté le 25-11-2005 à 05:21:23    

carabin a écrit :

J'ai un souci pour passer un buffer comme parametre d'une fonction.
Le but de la fonction est d'ouvrir un fichier, de creer un buffer de taille adaptée, d'y copier le contenu du fichier, de fermer le fichier, et de retourner l'adresse de ce buffer.


Hum... si tu parles de la fonction "loadfile" moi je la vois renvoyer un "int" avec ce commentaire "Tout s'est bien passé".
Et pour moi, un "int" n'est pas une adresse !!!
 

carabin a écrit :

Apparement l'adresse n'est pas renvoyée correctement, mais je ne vois pas pourquoi.


Cf remarque ci-dessus. Je rajouterai que si ta fonction "loadfile" est sensée renvoyer une adresse, il serait bien de récupérer cette adresse dans le main avec une instruction du style "var=loadfile(...)".
Maintenant, pourquoi ton "main" passe la variable "contenu_fichier"  à la fonction "loadfile" vu que la fonction est sensée créer la zone (malloc) et renvoyer la zone créée ? Elle n'utilise pas la valeur qu'elle reçoit du main puisqu'elle l'écrase d'entrée avec un malloc !!!
 

carabin a écrit :

Je comprends parfaitement les notions de pointeur, par contre je me mélange un peu avec la notation (suis pas toujours très sur quand il faut mettre juste le nom, ou y rajouter un * ou un &, je sais qui fait quoi, mais ca ne m'empeche pas de me melanger les pinceaux).


C'est parce que tu ne visualises pas réellement le type de ce qui est attendu par les fonctions que tu vas utiliser !!!
 
Quand tu déclares "char *pt", tu déclares une variable nommée "pt" de type "char étoile". Et accessoirement, la valeur "*pt" (ce qu'il y a au bout de "pt" ) est de type "char" (avec un dessin ce serait plus parlant).
 
Maintenant, tu as une fonction "void f(int *pt)". La fonction attend un paramètre de type "int étoile". Il faut donc lui passer un paramètre de type "int étoile". Tu remarqueras que si je prends la peine d'écrire le mot "étoile", c'est que ce mot est important. Une variable de type "int" n'est pas de type "int étoile". Et une variable de type "int étoile" n'est pas de type "int étoile étoile". Chaque étoile a son importance...
 
Donc tu dois lui passer un paramètre de type "int étoile". Et tu as, dans la fonction appelante, une variable "int *toto". Là, le débutant se dit "ma fonction attend un int étoile, je lui passe "*toto" => f(*toto)
Eh bien c'est faux ! "*toto" est de type "int" et ce n'est pas ce que la fonction attend
Dans "int *toto" quelle est la variable de type "int étoile" ? Eh bien c'est "toto". Tu appelles "f(toto)" et la fonction "f" reçoit bien un "int étoile"
 
Autre cas: tu as maintenant un paramètre de type "int titi". Et tu veux appeler "f". Il faut encore lui passer un "int étoile". Eh bien on peut utiliser le truc suivant:

  • comme l'étoile et le "&" s'annulent, on peut dire que "titi" <=> "*&titi"
  • "*&titi" est de type "int" donc on peut dire que "&titi" est de type "int *" (si j'enlève l'étoile d'un coté de la phrase, je le remets de l'autre coté)

Donc on passe "&titi" à la fonction... qui reçoit bien un "int étoile"
 
Exemple illustratif

Code :
  1. // Fonction n° 2
  2. void fonction2(int *pt)
  3. {
  4.        // Je modifie ce qui est pointé
  5.        *pt=123;
  6. }
  7. // Fonction n° 1
  8. void fonction1(int *pt)
  9. {
  10.        // Je passe mon pointeur à la fonction 2
  11.        fonction2(pt);            // Elle reçoit bien un "int étoile"
  12. }
  13. int main(void)
  14. {
  15.     int valeur;
  16.     // Je passe ma valeur à ma fonction 1 pour qu'elle la passe à ma fonction 2
  17.     fonction1(&valeur);       // Elle reçoit bien un "int étoile"
  18.     // Affichage de la valeur
  19.     printf("valeur=%d\n", valeur);
  20. }



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

Marsh Posté le 25-11-2005 à 09:15:34    

carabin a écrit :

J'ai un souci pour passer un buffer comme parametre d'une fonction.


C'est quoi un 'buffer' ? Tu veux dire un tableau ?
 
http://mapage.noos.fr/emdel/notes.htm#param_tab
 
Maintenant, si tu crées un tableau dynamiquement dans une fonction, tu dois retourner son adresse. Soit par return
pseudocode


char *f()
{
   char *p = malloc(...)
 
   return p
}


soit
pseudocode


f(char **pp)
{
   char *p = malloc(...)
 
   if (pp != NULL)
   {
      *pp = p;
   }
}

Message cité 1 fois
Message édité par Emmanuel Delahaye le 25-11-2005 à 09:18:42

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 25-11-2005 à 09:24:14    

Emmanuel Delahaye a écrit :


pseudocode


char *f()
{
   char *p = malloc(...)
 
   return p
}



Et en l'utilisant de cette façon :
pseudocode


int main()
{
   char *buffer;
 
   buffer=f();
}


 

Emmanuel Delahaye a écrit :

soit
pseudocode


f(char **pp)
{
   char *p = malloc(...)
 
   if (pp != NULL)
   {
      *pp = p;
   }
}



Et en l'utilisant de cette façon :
pseudocode


int main()
{
   char *buffer;
 
   f(&buffer);      // "&buffer" est bien de type "char étoile étoile"
}


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

Marsh Posté le 25-11-2005 à 23:42:33    

Tout dabord, merci a tous pour vos réponses. Après avoir posté, j'ai passé encore au moins une heure à chercher mon erreur, puis j'en ai eu marre, ai eteint le Pc et suit allé me coucher ---> et c'est à ce moment la que j'ai compris le problème. Moralité, il faut de temps en temps décoller le nez de son écran !!!
 
Ce que j'ai fait ne me permets que de modidier le contenu de buffer, par contre pour renvoyer son adresse a main, il me manquait betement un niveau de pointeur. Donc il fallait que je mette un pointeur SUR le pointeur SUR buffer pour modifier/attribuer l'adresse donnée par malloc  (--> comme le disait donc matafan )
 
En fait, la ou je m'embrouille generalement avec les pointeurs, c'est lors d'un passage de parametres. Le fait de devoir rajouter un niveau d'indirection à le don de me foutre dedans !
 
Emannuel --> oui, buffer = tableau  
 
Sve@r --> desolé, je n'ai peut etre pas ete super clair dans mes propos. Je ne cherche pas à renvoyer l'adresse par le return, mais par les arguments. Le return me sert pour faire un test au retour de la fonction (même si je ne l'utilise pas encore) , pour savoir si tout s'est bien passé. Le but de la manoeuvre, c'est que main envoit un pointeur non attribué "contenu_fichier" (que j'ai d'ailleurs oublié de mettre à NULL) à la fonction, et que la fonction modifie ce pointeur pour qu'il adresse la zone attribuée par malloc. Ce qui ferais qu'avant l'appel de la fonction, "contenu_fichier" ne pointe sur rien, et qu'au retour, elle pointe sur la fameuse zone mémoire créé dans la fonction (avec le contenu du fichier, oeuf corse).
 
En fait ce que je cherchais à faire est la même chose que dans le deuxième exemple donné par Emmanuel et complete par Sve@r. D'ailleurs, merci pour ce bout de code, auquel j'ai put comparer ma correction et voir qu'elle etait bonne. Par contre, je vois que j'ai aussi oublié de tester le retour de mon malloc !
 
Et pis surtout, même si j'apprécie votre aide, je suis super content d'avoir réussi à comprendre par moi-même (suis pas si con en fin de compte )
 
Ci dessous mon code corrigé (qui marche enfin comme je le souhaite )
 
HS : Sve@r, il faut le prononcer comment ? Sveor, Svear, SveATr ? autre ?
 

Code :
  1. #define _WIN32_WINNT 0x0500
  2. #include <windows.h>
  3. int loadFile ( char *nomFichier, char **buffer )
  4. {
  5.     HANDLE hFichier;
  6.     DWORD dwTailleFichier;
  7.     DWORD dwOctetsLus;
  8.     hFichier = CreateFile ( nomFichier, GENERIC_READ | GENERIC_WRITE,
  9.                             FILE_SHARE_READ, NULL, OPEN_EXISTING,
  10.                             FILE_ATTRIBUTE_NORMAL, NULL ) ;
  11.    
  12.     if(hFichier == INVALID_HANDLE_VALUE) { return 0; }
  13.    
  14.     dwTailleFichier = GetFileSize( hFichier, NULL );
  15.     *buffer = (char*) malloc (dwTailleFichier + 1);
  16.    
  17.     if (*buffer == NULL ) { return 0; }
  18.    
  19.     ReadFile(hFichier, *buffer, dwTailleFichier, &dwOctetsLus, NULL);
  20.    
  21.     /////////////////////////////
  22.     // cette messagebox donne le contenu correcte du fichier
  23.    
  24.     MessageBox  // affichage pour controle
  25.         (
  26.         NULL,   // handle of owner window
  27.         *buffer, //contenu_fichier  
  28.         "Buffer", // address of title of message box
  29.         MB_OK | MB_ICONINFORMATION
  30.         ); 
  31.    
  32.     CloseHandle(hFichier);   
  33.     return 1; // Tout s'est bien passé  
  34.    
  35. }    // fin load file
  36. /////////////////////////////////////////////////////
  37. //                                                 //
  38. //       MAIN                                      //
  39. //                                                 //
  40. /////////////////////////////////////////////////////
  41. int STDCALL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
  42. {
  43.     char nom_fichier [] = "D:\\test\\TEST.txt";
  44. //// ouvrir le fichier et le charger
  45. //         
  46.     char *contenu_fichier = NULL ;
  47.     loadFile ( nom_fichier, &contenu_fichier ); 
  48.    
  49.     /////////////////////////////
  50.     // maintenant cette messagebox donne un affichage correct
  51.     // du contenu du fichier
  52.    
  53.     MessageBox  // affichage du contenu
  54.         (
  55.         NULL,   // handle of owner window
  56.         contenu_fichier, //contenu_fichier,           // address of text in message box
  57.         "Contenu du Fichier", // address of title of message box
  58.         MB_OK | MB_ICONINFORMATION           // style of message box
  59.         );
  60.    
  61. // maintenant, plus qu'a lire ecrire modifier mon tableau contenu_fichier
  62. // et après, je l'enverrais à la fonction inverse (a faire) unloadFile qui
  63. // reecrira le fichier modifié sur le disque !!
  64. } // fin main

Message cité 2 fois
Message édité par carabin le 25-11-2005 à 23:47:24
Reply

Marsh Posté le 26-11-2005 à 10:01:44    

carabin a écrit :

Sve@r --> desolé, je n'ai peut etre pas ete super clair dans mes propos. Je ne cherche pas à renvoyer l'adresse par le return, mais par les arguments.


Exact, t'étais pas super clair et même là tes propos sont encore flous. On ne peut renvoyer de valeur que par un "return". On ne renvoie pas de valeur par les arguments.
Ce que tu cherchais à faire, c'est modifier une variable de la fonction appelante dans la fonction appelée. Dans ce cas, le seul moyen est de passer l'adresse de cette variable à la fonction appelée. Et quand la variable est de type "<type>", la fonction reçoit un "<type> étoile". Dans ton cas, la variable étant de type "char étoile", la fonction reçoit un "char étoile étoile"
 

carabin a écrit :

En fait ce que je cherchais à faire est la même chose que dans le deuxième exemple donné par Emmanuel et complete par Sve@r.


C'est un cas d'école
 

carabin a écrit :

Et pis surtout, même si j'apprécie votre aide, je suis super content d'avoir réussi à comprendre par moi-même


C'est le plus important - Les choses qu'on arrive à comprendre tout seul sont celles qui restent...
 

carabin a écrit :

HS : Sve@r, il faut le prononcer comment ? Sveor, Svear, SveATr ? autre ?


J'en n'ai aucune idée. Il me fallait un pseudo et je me suis souvenu des aventures de Thorgal. A un moment, il rencontre "Darek le Svear" aux alentours de l'album "la forteresse invisible". Et voilà mon pseudo. Sur DoD quand on joue en équipe avec la voix, les gars de ma team prononcent à l'américaine "Sveire"... :)  


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

Marsh Posté le 26-11-2005 à 11:02:43    

carabin a écrit :

Tout dabord, merci a tous pour vos réponses. Après avoir posté, j'ai passé encore au moins une heure à chercher mon erreur, puis j'en ai eu marre, ai eteint le Pc et suit allé me coucher ---> et c'est à ce moment la que j'ai compris le problème. Moralité, il faut de temps en temps décoller le nez de son écran !!!


Exact. Je ne compte plus les solutions trouvées au lit, en voiture ou sur le trone...

Citation :


Et pis surtout, même si j'apprécie votre aide, je suis super content d'avoir réussi à comprendre par moi-même (suis pas si con en fin de compte )


C'est le but !


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

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