Opérations matrices problème structure pointeur - C - Programmation
Marsh Posté le 13-01-2007 à 00:08:41
ngkreator a écrit : Salut à tous Ne soyez pas effrayé par la longueur du post: je pose juste une toute petite question de syntaxe à la fin
En fait le compilateur me dit "subscripted value is neither array nor pointer" Donc j'ai du faire une erreur au niveau de l'affectation (c'est cette affectation qui est surlignée en rouge dans DEV). |
Ben pour la syntaxe vu le type de MatA et MatB, c'est :
Code :
|
mais passer une structure par valeur, c'est des plus crades...
http://www.siteduzero.com/forum-83 [...] ml#r955806
A part ça, c'est pas fini...
|
Marsh Posté le 13-01-2007 à 00:12:26
Emmanuel Delahaye a écrit : Ben pour la syntaxe vu le type de MatA et MatB, c'est :
|
Ah oui c'est vrai j'ai oublié de remplacer matA par matA.matrice
Sinon quand tu me disais que passer une structure par valeur c'était crade, tu me parlais du 1er code où j'avais plein d'arguments dans chaque fonction?
Je vais voir ton lien et je vais modifier ça, merci pour ton aide
Edit1:
Emmanuel Delahaye a écrit : Ben pour la syntaxe vu le type de MatA et MatB, c'est :
|
C'est ce que tu as obtenu en le compilant? Ah ben oui! Il y avait d'autres étourderies en fait:
Code :
|
Bon maitenant le programme se lance mais le résultat des matrices laisse à désirer. Je vais voir ça
Edit2: ah ben si les multiplications marchent très bien, mais le programme se ferme lors des additions
Marsh Posté le 15-01-2007 à 12:23:53
C'est bon tout fonctionne Merci beaucoup pour ton aide
Voilà ce que j'obtiens:
Code :
|
J'ai rajouté un message d'erreur si on essaye d'additionner 2 matrices de dimensions différentes. Apparemment c'est possible d'additionner 2 matrices de dimensions différentes, mais pour l'instant je ne le prends pas en compte.
Bon maintenant je vais pouvoir m'amuser à améliorer tout ça
Marsh Posté le 15-01-2007 à 13:14:04
Tiens, tu devrais commencer par ameliorer ce petit bout de code:
Code :
|
Marsh Posté le 15-01-2007 à 16:05:23
breizhbugs a écrit : Tiens, tu devrais commencer par ameliorer ce petit bout de code:
|
C'est une blague?
Marsh Posté le 15-01-2007 à 17:09:04
Non! (malheureusement!)
Que se passe t il si tu essaie d'initialiser une matrice en indiquant dans la fonction "initialiser" une taille de ligne ou de colonne > M ?
Marsh Posté le 15-01-2007 à 20:27:51
breizhbugs a écrit : Non! (malheureusement!) |
Ah non je pensais que tu disais qu'il fallait que je refasse tout le code (que c'était de la merde quoi ). Parce que t'a mis les [...] à la fin, donc je pensais que tu avais cité le code entier.
Sinon oui. C'est un problème que j'ai pas réussi à résoudre (la taille max). Je peux demander la valeur max à l'utilisateur, mais je trouve pas ça pratique justement: on doit savoir à l'avance la taille des matrices. Dans ce cas ça ne pose pas de problème, il n'y a que 2 matrices. Mais ensuite quand il y aura plusieurs matrice ça ne sera pas pratique.
Je peux définir M à 100, c'est barbare, et de toutes manières il y aurait toujours une limite (certes assez grande ).
Donc au final j'ai mis 4 pour mes tests
Maintenant je ne vois vraiment pas comment faire. Y a-t-il une technique utilisée d'habitude pour ce genre de cas?
Marsh Posté le 15-01-2007 à 21:41:26
ngkreator a écrit : Maintenant je ne vois vraiment pas comment faire. Y a-t-il une technique utilisée d'habitude pour ce genre de cas? |
Tu veux dire "comment faire pour avoir une matrice dont la taille n'est pas connue du programmeur et dépendra de l'utilisateur ?"
Pas de pb => malloc
typedef struct { |
Bon, évidemment, pour bien faire faut tester chaque malloc et si l'un deux rate, faut tout arrêter. Là, c'était juste la version simplifiée...
Marsh Posté le 15-01-2007 à 22:16:02
Ah merci beaucoup Sve@r. J'avais déjà vu cette fonction malloc() quelque part, mais je voyais pas à quoi elle pouvait servir
Marsh Posté le 15-01-2007 à 22:23:12
Ne pas oublier la fonction free() egalement qui sert a liberer une zone allouée par malloc.
Cela s'appelle de l'allocation dynamique de memoire.
Marsh Posté le 15-01-2007 à 22:57:00
Ok je verrai tout ça
Marsh Posté le 16-01-2007 à 07:13:14
ngkreator a écrit : Ah merci beaucoup Sve@r. J'avais déjà vu cette fonction malloc() quelque part, mais je voyais pas à quoi elle pouvait servir |
MemoryALLOCate => Elle sert à te donner un bloc de mémoire contiguë (ça c'est très important) et te renvoie un pointeur sur le bloc alloué. Comme t'as un pointeur sur le premier octet et que le bloc est contiguë, tu peux accéder à tout le bloc simplement en utilisant la notation "tableau"
Ex:
char *tab; |
Marsh Posté le 27-01-2007 à 00:37:27
Voilà j'ai modifié tout ça en suivant vos conseils:
La nouvelle structure où je déclare juste le pointeur de pointeur:
Code :
|
J'ai crée une nouvelle fonction qui renvoie un pointeur avec l'espace mémoire dédiée demandé:
Code :
|
Donc voilà en gros c'est presque tout ce que j'avais à modifier. Le plus dur était de comprendre comment ça marchait. Il ne me restait plus qu'a demander aux fonctions qui créent les matrices, initialiser() et zero(),de réserver de l'espace mémoire la matrice crée par ces fonctions justement. J'ai donc ajouter la ligne qu'il fallait à la ligne 8:
Code :
|
Et à la ligne 4 ici:
Code :
|
Et voilà donc au final c'était pas grand chose, j'ai mit plus de temps à comprendre le vrai fonctionnement des tableaux à 2 dimensions qu'a écrire ces quelques lignes. Ca fait bizzare de ne pas mettre de taille max et de tout faire en dynamique Mais c'est mieux!
Sinon j'ai 2 questions toutes simples.
Et pour accéder au conteur pointé par le pointeur je devrai taper: structure->*pointeur
Apparemment ça fonctionne mais je voudrai être sûr
Merci
Le code final:
Code :
|
Marsh Posté le 27-01-2007 à 10:59:45
ngkreator a écrit :
|
D'un point de vue "organisationnel", il n'y a aucune raison d'inclure la fonction "alloueEspace()" dans la fonction de réinit car les deux ne vont pas forcément ensemble. La preuve, tu pourrais avoir envie de réinitaliser une matrice déjà allouée. Mis à part ce détail, t'as pensé à "memset()" ???
Code :
|
ngkreator a écrit : Sinon j'ai 2 questions toutes simples.
|
Pas tout à fait. En fait, "structure->pointeur" contient une adresse et tu cherches à aller à la case mémoire pointée par cette adresse donc la bonne syntaxe est "*structure->pointeur"
ngkreator a écrit :
|
A libérer l'espace mémoire réservé par ton programme. Dans les systèmes types Unix ce n'est pas obligatoire car en général un programme qui se termine voit ses ressources libérées par le système (mais vaut mieux programmer "propre" que "sale", on a tout à y gagner). En revanche, dans un monde comme Windows, tu fais un "malloc() sans "free()" et tu lances ton pgm ben windows garde la mémoire et tu n'y a plus jamais accès => reboot.
Par ailleurs, imagine une fonction qui fait du malloc sans free et qui est appelée dans une boucle...
Dernier détail: Essaye de ne pas utiliser le terme "mat" dans ta structure car ça embrouille avec ta variable "matrice". Tu peux utiliser par exemple "carré" ou "rectangle" ou simplement "data"...
Marsh Posté le 27-01-2007 à 11:35:11
Sve@r a écrit : En revanche, dans un monde comme Windows, tu fais un "malloc() sans "free()" et tu lances ton pgm ben windows garde la mémoire et tu n'y a plus jamais accès => reboot. |
Windows a évolué tu sais ...
Marsh Posté le 27-01-2007 à 11:54:08
++fab a écrit : Windows a évolué tu sais ... |
Rien que le fait qu'il ait été comme je le décris ne serait-ce qu'un seul jour est déjà impardonnable...
Marsh Posté le 27-01-2007 à 12:18:26
Merci pour tes conseils!
Tu as raison il n'était pas logique de mettre la fonction alloueEspace() dans la fonction zero(). Je l'ai donc mis dans les fonctions multiplier(), additionner() et initialiser(), en prenant soin de libérer la matrice avant. En fait si je ne libère pas la matrice, la fonction alloueEspace() va affecter une autre plage mémoire au pointeur tout en gardant l'ancien espace inaccessible si j'ai bien compris.
Voilà ce que j'ai rajouté dans les fonctions (ici pour la matrice resultat):
Code :
|
Donc maintenant même si je refais plusieurs calculs les espaces mémoires seront libérés à chaque fois.
La fonction memset() je peux l'utiliser sur chaque pointeur de ligne pour initialiser tous les valeurs à 0. Donc j'ai remplacé la fonction zero(resultat) par la ligne
Code :
|
Ca marche très bien et je n'ai plus besoin de la fonction zero()
Edit: ah j'avais pas vu le code où tu décris comment utiliser la fonction memset() Donc au final ça répond à ma question c'est bien comme ça qu'on peut faire. J'ai juste choisi de ne plus le faire dans la fonction zero. C'est à voir... Sinon pour la 2ème méthode qui aide à comprendre le fonctionnement des pointeurs j'ai bien compris. En fait avant d'utiliser les fonction d'allocation dynamique je me suis amusé à manipuler les pointeurs de pointeurs dans tous les sens pour voir si j'avais bien compris.
Sinon j'ai changé toutes les structures appelées mat en data et c'est beaucoup plus clair. En fait je ne voyais pas quoi mettre à part matrice donc j'avais laissé mat mais data est mieux. J'ai aussi rajouté les fonctions free() à la fin.
Mais maintenant Windows libère la mémoire quand le programme se ferme alors?
Marsh Posté le 27-01-2007 à 13:31:11
ngkreator a écrit : En fait si je ne libère pas la matrice, la fonction alloueEspace() va affecter une autre plage mémoire au pointeur tout en gardant l'ancien espace inaccessible si j'ai bien compris. |
T'as bien compris. Et en plus c'est tout à fait naturel. Ex:
Code :
|
ngkreator a écrit :
|
Pourquoi libérer l'espace de ta matrice pour le réallouer et le remplir de zéros ? T'as qu'à la remettre à zéro chaque fois que t'en as besoin sans t'embêter à libérer la mémoire pour en redemander...
Sinon un petit détail: Avant de libérer l'espace de ta matrice, il faut d'abord libérer chaque ligne. En fait, à chaque "malloc" doit correspondre un "free". Donc t'as créé une fonction pour allouer toute la matrice, tu peux aussi créer une fonction qui te libère toute la matrice sur le même schéma
ngkreator a écrit : La fonction memset() je peux l'utiliser sur chaque pointeur de ligne pour initialiser tous les valeurs à 0. Donc j'ai remplacé la fonction zero(resultat) par la ligne
|
Ben une fonction a pour but de regrouper un groupe d'instruction correspondant à une action jugée "élémentaire" pour ton algo. Créer une fonction "zero" ou "init" pour ta matrice était une bonne idée car tu pouvais l'appeler dès que t'avais besoin de la réinitialiser. A toi de voir. Plus tard, si tu te mets au C++, tu pourras associer aux objets des fonctions particulières pour les traiter (méthodes) et en revenant au C tu auras mieux l'habitude de découper ton algo en plein de petites fonctions élémentaires que tu pourras ensuite appeler à volonté...
ngkreator a écrit : Mais maintenant Windows libère la mémoire quand le programme se ferme alors? |
Ca n'empêche pas de bien programmer. Si tu prends l'habitude de fermer ce que tu ouvres, de libérer ce que tu réserves (comme les poupées russes) t'auras jamais d'ennui et t'auras jamais à t'occuper de "comment réagira le système"...
Marsh Posté le 27-01-2007 à 14:22:24
Sve@r a écrit : T'as bien compris. Et en plus c'est tout à fait naturel. Ex:
|
En fait si j'alloue un nouvel espace mémoire à resultat, l'ancien espace mémoire alloué à résultat va rester indisponible (ou même si il devient disponible c'est plus propre pour la programmation)?
Sve@r a écrit : |
C'est noté.
Sve@r a écrit : |
D'accord, je ne me suis pas rendu compte de l'utilité d'une fonction étant donné que le programme est petit.
Sve@r a écrit : |
Ok
Marsh Posté le 27-01-2007 à 15:08:27
ngkreator a écrit : En fait si j'alloue un nouvel espace mémoire à resultat, l'ancien espace mémoire alloué à résultat va rester indisponible |
Le système t'a réservé de l'espace donc l'espace devient indisponible pour un autre (définition du verbe "réserver" )
Il te donne le pointeur sur l'espace réservé => si tu perds le pointeur tu perds l'espace mais le système ne le récupère pas pour autant (il ne sait pas que t'as perdu le pointeur)...
Marsh Posté le 27-01-2007 à 15:09:24
En suivant tes conseils voilà le code que j'obtiens pour le fichier des fonctions:
Code :
|
J'ai juste un problème quand j'utilise la fonction memset() dans la fonction zero() Je vais faire des tests pour voir où je me suis trompé.
Et le fichier main:
Code :
|
Le fichier qui contient les prototypes (on y voit plus clair)
Code :
|
J'en ai profité pour commencer à apprendre à utiliser plusieurs fichiers pour clarifier le tout.
Marsh Posté le 27-01-2007 à 16:32:55
ngkreator a écrit : En suivant tes conseils voilà le code que j'obtiens pour le fichier des fonctions:
|
C'est un petit peu "brouillon" et ça peut encore grandement s'améliorer
1) on ne passe jamais une structure à une fonction par son nom, car il y a recopie de toute la structure dans la fonction (heureusement que dans ton cas ta structure ne contient en fait qu'une adresse...)
On lui passe l'adresse et la fonction reçoit un pointeur sur la structure
2) si une fonction ne peut pas accomplir son travail (style additionner des matrices différentes), c'est bien de lui faire renvoyer une valeur particulière comme ça la fonction appelante a moyen de détecter qu'il y a eu un pb
3) ta fonction "alloueEspace" n'est pas obligée de renvoyer l'espace alloué. Elle peut très bien recevoir un pointeur sur ta structure et allouer elle-même le contenu mais c'est du détail
4) quand jai parlé du token "data", dans ma tête c'était pour identifier les données de la matrice, c.a.d. les nombres (dans la structure). Toi tu l'as utilisé comme nom de variable. Bon, on s'est mal compris mais c'est ton programme et pas le mien
5) la bonne façon de procéder est de
Ca sera plus rapide que de
Pour chaque opération
6) utiliser "scanf" pour une saisie clavier c'est pas top. Bon ça conviendra parfaitement pour toi qui répond à ton programme mais jamais pour un programme destiné au public => tu peux pas contrôler ce que saisi le public
la bonne façon de faire saisir un nombre est de
ngkreator a écrit : J'ai juste un problème quand j'utilise la fonction memset() dans la fonction zero() Je vais faire des tests pour voir où je me suis trompé. |
C'est totalement ma faute. memset() bosse en octets et toi tu remplis un tableau de "int". J'ai pas réfléchi !!!
Code :
|
ngkreator a écrit : J'en ai profité pour commencer à apprendre à utiliser plusieurs fichiers pour clarifier le tout. |
http://fr.lang.free.fr/cours/Gener [...] t_v1.0.pdf
Marsh Posté le 27-01-2007 à 16:58:46
Sve@r a écrit : C'est un petit peu "brouillon" et ça peut encore grandement s'améliorer
Ca sera plus rapide que de
Pour chaque opération |
Merci encore de consacrer un peu de ton temps pour m'aider à faire du travail propre.
Marsh Posté le 27-01-2007 à 20:30:31
ngkreator a écrit : Tu veux dire que je dois toujours avoir une fonction de la forme: void maFonction(struture_type *structure) |
Pas forcément de type "void" mais effectivement, si tu passes à ta fonction une structure de 8M, il y aura recopie des 8M dans la fonction. Si tu passes une adresse de 4 octets, il y aura recopie de 4 octets et l'adresse permettra de retrouver la structure.
ngkreator a écrit : 3) ta fonction "alloueEspace" n'est pas obligée de renvoyer l'espace alloué. Elle peut très bien recevoir un pointeur sur ta structure et allouer elle-même le contenu mais c'est du détail |
C'est pas vraiment une histoire d'avantage ou d'inconvénient, c'est plus une habitude qui te vient quand tu fais du C++. En C++, tu encapsules tes éléments dans une structure comme en C sauf que ça porte le nom d'objet. Et comme tu peux y rajouter des fonctions pour traiter ces objets, tu prends vite l'habitude de toujours passer par ces fonctions pour manipuler leur contenu. Et quand tu reviens au C, tu gardes cette habitude.
En fait, si un jour tu distribues ta fonction à des tiers, dans le premier cas ils seront obligés de faire
Code :
|
donc les tiers ont un accès direct à l'élément "matrice" qui est sensé rester "interne" à la structure. Et si, plus tard, tu veux modifier ce nom en "data" ou autre, tous ceux qui utilisent ta matrice devront aussi modifier leur programme.
Dans le second cas, ils feront
Code :
|
Ils ne verront de ta matrice que sa coquille extèrieure, coquille contenant diverses portes d'entrée mais les tiers n'auront pas à connaître la structure interne de "matrice_type" pour utiliser tes outils et tu pourras modifier la structure interne sans te soucier des tiers...
ngkreator a écrit : Donc entre autre je pourrais utiliser la fonction realloc() pour redimensionner une matrice? |
Le pb de ta fonction "addition" (et les autres) est que tu commences par libérer "resultat" pour le réallouer. Mais t'as pas pensé qu'au premier appel, ta matrice "resultat" n'avait jamais été allouée !!!
Tu pourrais allouer "resultat" avant d'appeler "addition" mais tu ne connais pas à l'avance la taille de "resultat". Donc t'as que 2 solutions:
1) ta fonction "addition" commence par tester si "resultat" a déjà été alloué avant de le libérer
2) ta fonction "addition" ne reçoit que les matrices à additionner et renvoie un pointeur sur la matrice résultat, pointeur alloué dans la fonction
Pas évident de "bien" écrire du C...
PS: T'as remarqué que les types du systèmes étaient tous sous la forme "qqchose_t" (ex: off_t, size_t, etc...) ?
En fait, les conventions indiquent de nommer ses types "t_qqchose" (le suffixe "_t" étant réservé au système). Essaye de renommer tes types "t_matrice". Tu verras ton écriture de code s'allègera....
Marsh Posté le 27-01-2007 à 20:51:00
Sve@r a écrit : PS: T'as remarqué que les types du systèmes étaient tous sous la forme "qqchose_t" (ex: off_t, size_t, etc...) ?En fait, les conventions indiquent de nommer ses types "t_qqchose" (le suffixe "_t" étant réservé au système). |
je ne crois pas que le suffixe _t soit réservé "au système" - je ne sais pas ce que tu entends par là. Ce que je sais, c'est qu'un certain nombres de types finissant en _t est réservé à l'implémentation. Mais si tu crées un type suffixé par _t autre que ceux qui sont réservés - cf la norme - c'est légal.
Quand à la convention t_ en préfixe, justement, quelle est cette convention ?
Marsh Posté le 27-01-2007 à 21:35:36
++fab a écrit : je ne crois pas que le suffixe _t soit réservé "au système" |
Lapsus, j'aurais du dire "aux programmeurs du système"...
++fab a écrit : - je ne sais pas ce que tu entends par là. Ce que je sais, c'est qu'un certain nombres de types finissant en _t est réservé à l'implémentation. Mais si tu crées un type suffixé par _t autre que ceux qui sont réservés - cf la norme - c'est légal. |
Ben une fois, Emmanuel m'a dit que non. Je vais tenter de retrouver le post...
++fab a écrit : Quand à la convention t_ en préfixe, justement, quelle est cette convention ? |
Ben une convention c'est pas une obligation fixée par RFC, c'est plutôt un "consensus"...
Marsh Posté le 27-01-2007 à 23:06:59
Sve@r a écrit : Ben une convention c'est pas une obligation fixée par RFC, c'est plutôt un "consensus"... |
Alors même question s/convention/consensus/g
Marsh Posté le 28-01-2007 à 01:52:26
Sve@r a écrit : Lapsus, j'aurais du dire "aux programmeurs du système"... |
Le suffixe _t est réservé par POSIX pour définir les types.
Marsh Posté le 28-01-2007 à 12:47:24
++fab a écrit : Alors même question s/convention/consensus/g |
même question |sed -e "s/convention/consensus/g"
J'ai rien d'écrit à ce sujet. Ce ne sont que des transmissions orales que le sorcier de ma tribu nous raconte le soir devant notre cage à feu et que nous transmettrons plus tard à nos enfant de la même façon
Marsh Posté le 29-01-2007 à 01:45:47
Bon après tous ces bon conseils voilà ce que j'ai modifié:
1) J'adopte le format t_matrice
Apparemment c'est ce que j'ai jugé bon d'utiliser d'après vos explications
2) Modification des la fonction memset
Après ton explication ça a très bien marché!
3) Passage des structures par adresse dans toutes les fonctions.
Aucun problème à ce niveau là.
4) Renvoie d'une valeur entière par les fonctions alloueEspace, initialisation, additionner et multiplier.
En fait la fonction alloueEspace renvoie 0 si il n'y a pas d'erreur et 1 si il y en a une. L'erreur se manifeste si une des fonctions malloc renvoie un pointeur NULL. Ensuite les fonctions qui utilisent la fonction alloueEspace prennent en compte cette erreur pour elle même renvoyer une erreur de la même forme (un entier 1).
Exemple avec alloueEspace:
Code :
|
D'ailleur pour que le programme reconnaisse la constante NULL j'ai dû intégrer stdio.h dans mon fichier fonction.c qui contient les fonctions. Ca ne me parait pas normal étant donné que le fichier main.c fait appel au fichier fonction.c après avoir fait appel à la librairie stdio.h. Donc le compilateur devrait déjà connaitre la constante qui est définie dans la librairie.
5) Liberation puis allocation d'espace mémoire dans les fonctions multiplier et additionner
Donc maintenant les fonctions multiplier et additionner ne libèrent les pointeurs de matrice que s'il ont déjà été alloué au moins une fois. Pour ce faire j'ai pris la 1ère méthode que tu m'a proposé. Donc je force tous les pointeurs de matrice à NULL dès le départ (dans le fichier main.c). Ensuite les fonctions vérifient si le pointeur de matrice est NULL ou pas pour libérer ou non.
Code :
|
6) Création d'une fonction saisie() qui permet de sécuriser la saisie.
Après quelques recherches j'ai réussi à construire la fonction saisie qui fait une boucle tant que sscanf n'est pas égal à 1.
Code :
|
Je n'ai pas utilisé la fonction fgets car je n'ai pas encore compris son fonctionnement, mais ça va venir.
Je vous mets le programme avec les 3 fichiers: main.c, fonctions.h, fonctions.c
Fichier main
Code :
|
Fichier fonctions.h
Code :
|
Fichier fonctions.c
Code :
|
Problèmes
Aucun mise à part le problème du pointeur NULL qui m'oblige à insérer la librairie dans le fichier des fonctions et qui me parait être une manoeuvre barbare! Et la fonction fgets à comprendre aussi.
Merci encore pour toute l'aide que vous m'apportez J'essaye d'être clair et d'apprendre un maximum, donc ne vous génez pas.
Marsh Posté le 29-01-2007 à 02:22:06
Sve@r a écrit : Ce ne sont que des transmissions orales que le sorcier de ma tribu nous raconte le soir devant notre cage à feu et que nous transmettrons plus tard à nos enfant de la même façon |
Marsh Posté le 29-01-2007 à 16:19:35
ngkreator a écrit : 2) Modification des la fonction memset |
En fait, et après mûre réflexion, je ne suis pas certain qu'il soit judicieux d'utiliser "memset". en effet, pour tout remplir à "0" ça marche car on met "0" dans chaque octet. Mais s'il fallait, par exemple, tout remplir à "1", ça ne marcherait plus car "memset()" mettrait des "1" dans chaque octet donc ta matrice serait remplie de "0x0101" soit de 257 en décimal. Donc à toi de voir si tu la gardes ou pas...
ngkreator a écrit : En fait la fonction alloueEspace renvoie 0 si il n'y a pas d'erreur et 1 si il y en a une. L'erreur se manifeste si une des fonctions malloc renvoie un pointeur NULL. Ensuite les fonctions qui utilisent la fonction alloueEspace prennent en compte cette erreur pour elle même renvoyer une erreur de la même forme (un entier 1). |
Principe général d'utilisation d'une fonction qui peut renvoyer une erreur => la fonction appelante teste cette valeur particulière et agit en conséquence
ngkreator a écrit : D'ailleur pour que le programme reconnaisse la constante NULL j'ai dû intégrer stdio.h dans mon fichier fonction.c qui contient les fonctions. Ca ne me parait pas normal étant donné que le fichier main.c fait appel au fichier fonction.c après avoir fait appel à la librairie stdio.h. Donc le compilateur devrait déjà connaitre la constante qui est définie dans la librairie. |
Je ne comprends pas ton terme "fait appel". Est-ce que tu as inclu "fonction.c" dans "main.c" ? Si c'est ça se serait HORRIBLE !!!
Si tu regardes bien mon cours sur la compilation de plusieurs sources séparés, tu verras que chaque source est traité pour aller jusqu'au ".o". Et la vérification syntaxique se fait au début de la compilation. Donc si t'as 2 sources distincts et que les 2 ont besoin d'un truc présent dans un ".h" ben les 2 doivent inclure ce ".h".
ngkreator a écrit : 6) Création d'une fonction saisie() qui permet de sécuriser la saisie.
|
Presque bon. le problème de "gets" est que cette fonction ne contrôle pas le nb d'octets saisis => donc l'utilisateur peut en taper plus que ce que lazone peut en recevoir => gros bug => tu devrait taper "gets" dans google, ça m'étonnerait que tu ne trouves pas 150 pages détaillant pourquoi il ne faut jamais s'en servir
Principe de "fgets()": la fonction saisit une chaîne dans le flux demandé et stocke cette chaîne dans la zone demandée. Et elle s'arrête quand elle rencontre un "<return>" OU quand le nb de caractères indiqué est atteint (n - 1 en fait car elle garde un caractère dispo pour stocker le '\0') => Donc l'utilisateur ne pourra jamais entrer plus d'octets que ce que la zone peut en contenir...
Marsh Posté le 11-02-2007 à 20:16:05
Sve@r a écrit : En fait, et après mûre réflexion, je ne suis pas certain qu'il soit judicieux d'utiliser "memset". en effet, pour tout remplir à "0" ça marche car on met "0" dans chaque octet. Mais s'il fallait, par exemple, tout remplir à "1", ça ne marcherait plus car "memset()" mettrait des "1" dans chaque octet donc ta matrice serait remplie de "0x0101" soit de 257 en décimal. Donc à toi de voir si tu la gardes ou pas... |
Merci pour la précision
Sve@r a écrit : Je ne comprends pas ton terme "fait appel". Est-ce que tu as inclu "fonction.c" dans "main.c" ? Si c'est ça se serait HORRIBLE !!! |
Ok je te rassure j'ai seulement mit le *.h dans le main.c
En fait dans le main j'ai:
#include <stdio.h>
#include <memory.h>
#include "fonctions.h"
Dans le *.h j'ai rien et dans le *.c j'ai:
#include <stdio.h>
#include "fonctions.h"
Maintenant ça fonctionne et je déclare la structure t_matrice sulement dans le *.h donc tout va bien!
Sve@r a écrit : |
D'accord!
Marsh Posté le 12-01-2007 à 23:47:28
Salut à tous Ne soyez pas effrayé par la longueur du post: je pose juste une toute petite question de syntaxe à la fin
Il y a un petit moment je m'étais amusé à faire un programme qui multipliait des matrices carrées: http://forum.hardware.fr/hfr/Progr [...] 6904_1.htm
Aujourd'hui j'ai décidé d'améliorer le programme en permettant la multiplication et l'addition de matrices de dimensions différentes.
J'ai utilisé des structures (une matrice, le nbre de lignes, le nbre de colonnes et un idientificateur) c'est quand même plus pratique. J'obtient un programme qui marche avec une sorte de petit menu, bon bref...tout va bien. Donc je mets le code pour les curieux:
Bon c'est très lourd dans les arguments des fonctions je sais C'est pourquoi je me suis dit: "quel idiot pourquoi tu ne met pas juste une structure sous forme de pointeur en argument?"
Alors j'ai obtenu ça:
Oui mais si je poste c'est qu'il y a un problème Ca se situe au niveau des structures. Quand je fais une fonction avec une structure en pointeur en argument: si je veux affecter ne valeur à un entier qui se situe dans la structure la syntaxe est bien nom_de_la_structure->variable_entière=un_entier ??
Plus précisément le problème se situe à la dernière ligne: ([i]resultat->matrice[ligne][colonne]=matA[ligne][colonne]+matB[ligne][colonne])
En fait le compilateur me dit "subscripted value is neither array nor pointer" Donc j'ai du faire une erreur au niveau de l'affectation (c'est cette affectation qui est surlignée en rouge dans DEV).
Un grand merci pour ceux qui pourront m'aider.
Message édité par ngkreator le 12-01-2007 à 23:55:48