Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
879 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [Résolu] Pointeurs et fonctions

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu] Pointeurs et fonctions

n°1499899
exhortae
Membre du Cartel des Médecins
Posté le 07-01-2007 à 12:06:22  profilanswer
 

Bonjour,
 
voilà je suis tjs avec mes problèmes de pointeurs  :sarcastic:  et là j'en ai un que j'arrive pas à résoudre:
 
je dois faire une fonction qui lit les élements d'un tableau, avec comme paramètre un nombre maximum d'elements, si le nombre d'éléments saisis est > au nbre d'elements max autorisé la fonction doit me permettre de changer le nombre d'elements saisie (que j'utiliserais ensuite dans le main pour afficher les éléments)
 
le soucis c'est au niveau de l'allocation mémoire du tableau, quand je la fait en dynamique j'ai n'importe quoi qui sort dans l'affichage  :heink:  
 

Code :
  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. void lire_tab (int *t, int *n, int nmax)
  5. {
  6. int i;
  7. while (nmax < *n)
  8. {
  9.  printf ("Dimension du tableau : " );
  10.  scanf ("%d", n);
  11. }
  12.     t = (int*)  malloc ((*n) * sizeof (int));
  13. for (i = 0; i < *n; i++)
  14. {
  15.  printf ("Element[%d] : ", i + 1);
  16.  scanf ("%d", &t[i]);
  17. }
  18. }
  19. int main (void)
  20. {
  21. int *t, n, i;
  22. printf ("Dimension du tableau : " );
  23. scanf ("%d", &n);
  24. lire_tab (t, &n, 10);
  25. printf ("\n\n" );
  26. for (i = 0; i < n; i++)
  27.  printf ("element[%d] : %d\n", i + 1, t[i]);
  28. getch ();
  29. return 0;
  30. }

Message cité 2 fois
Message édité par exhortae le 11-01-2007 à 18:40:50
mood
Publicité
Posté le 07-01-2007 à 12:06:22  profilanswer
 

n°1499905
Emmanuel D​elahaye
C is a sharp tool
Posté le 07-01-2007 à 12:23:58  profilanswer
 

exhortae a écrit :

voilà je suis tjs avec mes problèmes de pointeurs <...> le soucis c'est au niveau de l'allocation mémoire du tableau, quand je la fait en dynamique j'ai n'importe quoi qui sort dans l'affichage


C'est normal. Ceci :

Project   : Forums
Compiler  : GNU GCC Compiler (called directly)
Directory : C:\dev\forums2\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.c
main.c: In function `main':
main.c:26: warning: 't' might be used uninitialized in this function
Linking console executable: console.exe
Process terminated with status 0 (0 minutes, 6 seconds)
0 errors, 1 warnings


Révèle un problème de conception :

 

En effet, tu passes une valeur non initialisée à une fonction. Je rappelle qu'en C, les passages de paramètres se font exclusivement par copie de la valeur, et que modifier la valeur d'un paramètre n'affecte pas la valeur initiale.

 

Si tu veux qu'une fonction modifie la valeur d'une variable, il y a 2 solutions :

 

- Passer l'adresse de la variable
- Retourner la valeur et la stocker dans la variable.

 

NOTA : Si ton compilateur de dit rien, c'est qu'il est probablement mal réglé :

 

http://mapage.noos.fr/emdel/codage.htm#cfg_compilo

Message cité 1 fois
Message édité par Emmanuel Delahaye le 07-01-2007 à 12:25:08

---------------
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/
n°1500489
Sve@r
Posté le 08-01-2007 à 18:53:57  profilanswer
 

exhortae a écrit :

Code :
  1. void lire_tab (int *t, int *n, int nmax)
  2. {
  3.    ...
  4.     t = (int*)  malloc ((*n) * sizeof (int));
  5. }
  6. int main (void)
  7. {
  8. int *t, n, i;
  9. ...
  10. lire_tab (t, &n, 10);
  11. }



 
Emmanuel a bien résumé la chose, voire peut-être de façon trop sybilline pour un débutant...
En fait, tu passes à "lire_tab" une copie de "t", c'est à dire une copie de ton pointeur. Cette copie est modifiée dans la fonction "lire_tab" et récupère l'adresse allouée puis la copie est effacée une fois la fonction finie et quand tu reviens dans le "main", "t" n'a jamais été modifié (et ne contient certainement pas l'adresse allouée qui a été perdue)
2 solutions

  • tu passes à ta fonction "lire_tab" l'adresse de "t". Cette fonction recevant une adresse (de type "int **" puisque "t" est de type "int*" ) pourra aller modifier l'élément pointé ("*t=malloc(...)" ) => pour résumer, t'as parfaitement compris que comme "n" sera modifié dans "lire_tab" (lors du "scanf()" ) il faut lui passer l'adresse de "n" dans le "main"; donc tu dois appliquer le même raisonnement pour "t" => tu peux aussi te rappeler que dans "lire_tab()" tu peux nommer tes paramètres avec un nom différent des variables du "main()" et tu réaliseras qu'il n'y a aucun rapport avec le "t" du main() et le "t" de lire_tab()


  • tu fais renvoyer par "lire_tab" le pointeur de la zone allouée (renvoyé lui-même par malloc) et, dans ton main, tu écrits "t=lire_tab(...)" => dans ce cas plus la peine de passer "t" à "lire_tab" car il sera modifié par l'affectation de retour

Message cité 1 fois
Message édité par Sve@r le 08-01-2007 à 19:33:55

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1500518
exhortae
Membre du Cartel des Médecins
Posté le 08-01-2007 à 19:58:48  profilanswer
 

Emmanuel Delahaye a écrit :


 
 Je rappelle qu'en C, les passages de paramètres se font exclusivement par copie de la valeur, et que modifier la valeur d'un paramètre n'affecte pas la valeur initiale.
 
Si tu veux qu'une fonction modifie la valeur d'une variable, il y a 2 solutions :
 
- Passer l'adresse de la variable
- Retourner la valeur et la stocker dans la variable.
 


 
Oui en faite le pointeur que je passais comme paramètre dans la fonction m'a induit en erreur, j'ai pas pensé qu'il fallait passer comme paramètre un pointeur sur un pointeur.
 

Sve@r a écrit :

Emmanuel a bien résumé la chose, voire peut-être de façon trop sybilline pour un débutant...
En fait, tu passes à "lire_tab" une copie de "t", c'est à dire une copie de ton pointeur. Cette copie est modifiée dans la fonction "lire_tab" et récupère l'adresse allouée puis la copie est effacée une fois la fonction finie et quand tu reviens dans le "main", "t" n'a jamais été modifié (et ne contient certainement pas l'adresse allouée qui a été perdue)
2 solutions

  • tu passes à ta fonction "lire_tab" l'adresse de "t". Cette fonction recevant une adresse (de type "int **" puisque "t" est de type "int*" ) pourra aller modifier l'élément pointé ("*t=malloc(...)" ) => pour résumer, t'as parfaitement compris que comme "n" sera modifié dans "lire_tab" (lors du "scanf()" ) il faut lui passer l'adresse de "n" dans le "main"; donc tu dois appliquer le même raisonnement pour "t" => tu peux aussi te rappeler que dans "lire_tab()" tu peux nommer tes paramètres avec un nom différent des variables du "main()" et tu réaliseras qu'il n'y a aucun rapport avec le "t" du main() et le "t" de lire_tab()


  • tu fais renvoyer par "lire_tab" le pointeur de la zone allouée (renvoyé lui-même par malloc) et, dans ton main, tu écrits "t=lire_tab(...)" => dans ce cas plus la peine de passer "t" à "lire_tab" car il sera modifié par l'affectation de retour


Merci grâce à ça j'ai pu comprendre mon erreur
 
voilà le programme modifié
 

Code :
  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. void lire_tab (int **t1, int *n, int nmax)
  5. {
  6. int i;
  7. while (nmax < *n)
  8. {
  9.  printf ("Dimension du tableau : " );
  10.  scanf ("%d", n);
  11. }
  12.     *t1 = (int*)  malloc ((*n) * sizeof (int));
  13. for (i = 0; i < *n; i++)
  14. {
  15.  printf ("Element[%d] : ", i + 1);
  16.  scanf ("%d", *t1 + i);
  17. }
  18. }
  19. int main (void)
  20. {
  21. int *t, n, i;
  22. printf ("Dimension du tableau : " );
  23. scanf ("%d", &n);
  24. lire_tab (&t, &n, 10);
  25. printf ("\n\n" );
  26. for (i = 0; i < n; i++)
  27.  printf ("element[%d] : %d\n", i + 1, t[i]);
  28. getch ();
  29. return 0;
  30. }


 
 
si tu pouvais me dire si maintenant il est correct (chez moi il tourne mais je suis pas sur pour la partie du scanf), ça me permettra ensuite d'expliquer ce que j'ai compris pour voir si je ne me trompe pas.
 
Merci à vous deux
 
PS : je viens de voir que t'as editer ton post pour ajouter une précision, mais j'avais trouver avant (cherché pendant 5 bonnes minutes quand même :D)

Message cité 1 fois
Message édité par exhortae le 08-01-2007 à 20:03:58
n°1500529
Sve@r
Posté le 08-01-2007 à 21:09:50  profilanswer
 

exhortae a écrit :

voilà le programme modifié
 

Code :
  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. void lire_tab (int **t1, int *n, int nmax)
  5. {
  6. int i;
  7. while (nmax < *n)
  8. {
  9.  printf ("Dimension du tableau : " );
  10.  scanf ("%d", n);
  11. }
  12.     *t1 = (int*)  malloc ((*n) * sizeof (int));
  13. for (i = 0; i < *n; i++)
  14. {
  15.  printf ("Element[%d] : ", i + 1);
  16.  scanf ("%d", *t1 + i);
  17. }
  18. }
  19. int main (void)
  20. {
  21. int *t, n, i;
  22. printf ("Dimension du tableau : " );
  23. scanf ("%d", &n);
  24. lire_tab (&t, &n, 10);
  25. printf ("\n\n" );
  26. for (i = 0; i < n; i++)
  27.  printf ("element[%d] : %d\n", i + 1, t[i]);
  28. getch ();
  29. return 0;
  30. }


 
si tu pouvais me dire si maintenant il est correct (chez moi il tourne mais je suis pas sur pour la partie du scanf


D'un point de vue "C", tes scanf sont excellents. T'as parfaitement maîtrisé la relation d'égalité entre "&t[i]" et "t + i" qu'on retrouve aussi entre "t[i]" et "*(t + i)".
 
Cependant, d'un point de vue "humain", utiliser un "scanf" pour faire saisir qqchose à une personne c'est horrible. Car "scanf" sous-entend que l'entrée est formatée alors que ce que tape le type derrière son clavier est tout sauf formaté. Que se passe-t-il si le type tape "azerty" là où on lui demande un nombre ? 1) ton nombre est à 0 et 2) le buffer d'entrée reste chargé avec "azerty" => à la saisie suivante d'une chaîne, c'est "azerty" qui sera utilisé
 
La meilleure solution utilisable est de tout accepter via fgets() car au-moins ton buffer est toujours clean et ensuite de traiter ton entrée via sscanf().
 
Exemple: remplacer

int i;
scanf("%d", &i);


 
Par

int i;
char saisie[1024];
fgets(saisie, 1024, stdin);
sscanf(saisie, "%d", &i);


Pour plus de détail, aller voir http://forum.hardware.fr/hfr/Progr [...] 9666_1.htm
 
Ensuite, étant donné que ton tableau "t" est intrinsèquement lié à "n", tu peux regrouper les deux éléments dans une structure. Tu passes ensuite l'adresse de la structure à la fonction qui peut grâce, à cet unique paramètre, aller taper dans le tableau "t" ou le nombre "n" comme elle a envie.
1) ça t'économise un paramètre
2) ça t'évite de jongler avec les "*t + i" et "*n"
 
Enfin ne pas oublier de  
1) vérifier que le malloc a réussi sinon ce n'est pas la peine de continuer
2) libérer "t" en fin d'utilisation


Message édité par Sve@r le 08-01-2007 à 21:15:34

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1500547
exhortae
Membre du Cartel des Médecins
Posté le 08-01-2007 à 21:57:26  profilanswer
 

Pour la saisie on m'a fait la remarque plusieurs fois, le soucis c'est que en cours on utilise les scanf, et le jour ou j'ai essayé d'utiliser les fgets, strtol ... je me suis senti en déphasage par rapport au cours, donc pour l'instant (et malgré moi) j'utilise ce que l'ont fait en cours avec dans l'idée de corriger ces erreurs de saisie pendant les grandes vacances (j'ai déjà achetéle livre de ritchie et kernighan pour y arriver).
 
pour les structures je note ;)
 
quand à la vérification de l'allocation et à la liberation, oui c'est un oubli de ma part.
 
Merci :)


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [Résolu] Pointeurs et fonctions

 

Sujets relatifs
[résolu][Flash]>>appel d'un .swf avec son AS[Résolu] Envoyer par mail le résultat d'un formulaire fait en html
[résolu] passage d'excel 2003 à excel 2000[Résolu]Intégration d'une carte google sur mon site
[Résolu] Exécuter une action en fonction du choix dans un menu[Résolu] Enregistrer des données modifiables dans un fichiers.
[RESOLU] VBS : Problème de redéfinition de variableClasses, fonctions, comment décrire leur syntaxe ?
[Ruby On Rails] [Resolu] Routing error[résolu et amélioré !!]Problème avec math.h
Plus de sujets relatifs à : [Résolu] Pointeurs et fonctions


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR