TAD matrice (structure + tableau dynamique)
salut tout le monde !
je suis plutôt débutant en C et je dois réaliser une classe matrice en C.
J'ai trois fichiers :
matrice.h
Code:
1 2 3 4 5 6 7 8 9
|
typedef struct matrice *matrice;
/* Fonctions */
matrice initialiserMatriceNulle(int, int);
matrice initialiserMatrice(int, int);
///* Procédures */
void afficherMatrice(matrice); |
matrice.c
Code:
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
|
#include "matrice.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct matrice
{
int nbLigne;
int nbColonne;
float **tableau;
};
//* Procédures */
//* afficherMatrice(matrice) : Cette procédure affiche une matrice */
void afficherMatrice(matrice m)
{
int i,j;
for(i=0;i<m->nbLigne;i++)
{
for(j=0;j<m->nbColonne;j++)
{
printf("\t %lf ",m->tableau[i][j]);
}
printf("\n");
}
}
//* Fonctions */
matrice initialiserMatriceNulle(int m, int n)
{
matrice maMatrice;
maMatrice = (matrice)malloc(sizeof(struct matrice));
maMatrice->nbLigne = m;
maMatrice->nbColonne = n;
maMatrice->tableau = malloc(m*sizeof(*(maMatrice->tableau)));
int i,j;
for(i=0;i<m;i++)
maMatrice->tableau[i] = malloc(n*sizeof(**(maMatrice->tableau)));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
maMatrice->tableau[i][j]= 4;
return maMatrice;
}
matrice initialiserMatrice(int m, int n)
{
matrice maMatrice = initialiserMatriceNulle(m,n);
int i,j;
/* m et n doivent être testés avant > 0 et < NMAX */
for(i=0;i<m;i++)
{
printf("\nLigne %d :\n",i+1);
for(j=0;j<n;j++)
{
printf("\nElement a[%d][%d] = ",i+1,j+1);
scanf("%lf",&maMatrice->tableau[i][j]);
}
}
return maMatrice;
} |
main.c (pour tester)
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#include "matrice.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main()
{
int m,n;
matrice maMatrice,m1,m2;
printf("Nombre de lignes : ");
scanf("%d",&m);
printf("\nNombre de colonnes : ");
scanf("%d",&n);
maMatrice = initialiserMatriceNulle(m, n);
afficherMatrice(maMatrice);
m1 = initialiserMatrice(m, n);
afficherMatrice(m1);
system("PAUSE");
return 0;
} |
:?: Il m'est imposé de mettre la structure dans matrice.c et de créer un pointeur vers cette structure dans le .h. Ce serait pour "cacher" comment je code une matrice. Quelqu"un pourrait-il m'apporter des infos à ce sujet ? merci.
:?: La fonction initialiserMatriceNulle semble marcher. (j'ai mis 4 pour voir si ça affichait bien 4). Par contre la fonction initialiserMatrice me donne une matrice de bonne dimension mais avec que des 0 (même pas des 4). J'ai dû oublier un truc élémentaire ?
:?: Avant de quitter le programme, je dois libérer la mémoire ? Je ne peux pas faire seulement un free(matrice) ? il faut que je désalloue toutes les cases. C'est à ce moment là que je crie ausssssssseeeeeeeecccccourrrrrrrssss je suis perdu ! :cry:
:!: Voilà ça fait beaucoup de questions. Je tiens à préciser que je travaille avec dev c++ et que j'ai déjà regardé la faq et quelques sujets pour faire mes allocations mémoires, mais avec la structure ça complique les choses...
Si quelqu'un peu répondre à une des trois questions... hésitez pas !
Merci
Manu
Re: Classe matrice (structure + tableau dynamique)
Citation:
Envoyé par supermanu
je suis plutôt débutant en C et je dois réaliser une classe matrice en C.
Si ton prof parle de 'classe' en C, change d'école et fait toi rembourser. Il n'y a pas de 'classe' en C. Par contre, ce que je vois de la suite s'apparente à un TAD (Type Abstrait de Donnée ou ADT, Abstract Data Type), ce qui est la forme la plus basique de l'approche objet en C.
http://emmanuel-delahaye.developpez.com/tad.htm
et, après lecture rapide du code, c'est plutôt une bonne approche, alors attend un peu avant de quitter l'école!
Citation:
:?: Il m'est imposé de mettre la structure dans matrice.c et de créer un pointeur vers cette structure dans le .h. Ce serait pour "cacher" comment je code une matrice. Quelqu"un pourrait-il m'apporter des infos à ce sujet ? merci.
Oui, c'est le principe même du type abstrait de données. La définition de la structure est 'coupée en deux'.
La partie visible (interface) est réduite à sa plus simple expression:
Code:
typedef struct type type_s;
ou (dans ton cas)
Code:
typedef struct type *ptype_s;
alors que dans la partie implémentation, on trouve la définition complète de la structure:
Code:
1 2 3 4 5 6
|
struct type
{
/* liste des elements */
...
}; |
Citation:
:?: La fonction initialiserMatriceNulle semble marcher. (j'ai mis 4 pour voir si ça affichait bien 4). Par contre la fonction initialiserMatrice me donne une matrice de bonne dimension mais avec que des 0 (même pas des 4). J'ai dû oublier un truc élémentaire ?
Code:
scanf ("%lf", &maMatrice->tableau[i][j]);
Le type de l'adresse est (float*), alors que type attendu par "%lf" est (double *) Il faut etre coherent.
Code:
scanf ("%f", &maMatrice->tableau[i][j]);
D'autre part, d'une façon générale, il faut tester le code retour des fonctions d'entrées (ici, si on a pas 1, c'est qu'il y a une erreur); et il est déconseillé d'utiliser les fonctions scanf() et fscanf() qui sont difficiles, même pour un programmeur expérimenté. Il y a des aletrnatives simples et fiables.
http://emmanuel-delahaye.developpez....tes.htm#saisie
Citation:
:?: Avant de quitter le programme, je dois libérer la mémoire ? Je ne peux pas faire seulement un free(matrice) ? il faut que je désalloue toutes les cases. C'est à ce moment là que je crie au secours je suis perdu !
Il suffit de faire le travail inverse.
- parcourir le tableau de pointeurs pour libérer les blocs un à un
- libérer le tableau de pointeurs.
Autres points concernants ton code
- Les commentaires sont bizarres. C'est soit /* */ (portable), soit // (C99), mais pas un mélange des deux (ça trouble ma machine à relooker les commentaires! :lol:)
- Ton indentation est moche (je sais, c'est une affaire de gout).
- Plus sérieux, le fichier d'en-tête devrait être encadré par des protections anti inclusions multiples.
http://emmanuel-delahaye.developpez....ganiser_source
- Je ne suis pas trop d'accord pour pousser l'abstraction au point de cacher le fait que l'objet est un pointeur. Ca ne facilite pas la relecture du code. Les programmeurs C n'ont pas honte d'utiliser des pointeurs. Il n'y a rien à cacher. Si c'est imposé, je conseille alors de mettre un 'p' dans l'identificateur.
- Il est inutile de mettre un cast avec malloc()
http://emmanuel-delahaye.developpez....tes.htm#malloc
- Contrairement au Pascal, il n'y a pas de 'procedure' en C. Uniquement des fonctions, quelque soit le type retourné.
- Le nom 'initialiserMatriceNulle()' est mal choisi. Le rôle principal de cette fonction est la création de la matrice (il manque d'ailleurs une fonction de destruction). Je les aurais appelées 'creerMatrice()' et detruireMatrice()'. Pour remplir la matrice de '4', j'aurais crée une fonction de remplissage séparée remplirMatrice() avec la valeur en paramètre. Mais pour vérifier sa matrice, il vaut mieux la remplir de valeurs différentes....
- Il est assez troublant et étrange qu'il y ait 2 fonctions publiques qui servent à créer l'objet (initialiserMatriceNulle() et initialiserMatrice()). En tant qu'utilisateur, je me demande laquelle il faut utiliser..
Je n'ai pas étudié ton code dans le détail...
A l'exécution (après correction du scanf() et instrumentation de la mémoire), j'obtiens ceci:
Code:
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
|
D:\DEV-CPP>bc proj.prj
SYSALLOC BC++ Ver 4.10 LARGE 62096 MS-DOS
SYSALLOC Overload (14 rec)
SYSALLOC Successful initialization: 14 records available
Nombre de lignes : 2
Nombre de colonnes : 3
4.000000 4.000000 4.000000
4.000000 4.000000 4.000000
Ligne 1 :
Element a[1][1] = 1.1
Element a[1][2] = 1.2
Element a[1][3] = 1.3
Ligne 2 :
Element a[2][1] = 2.1
Element a[2][2] = 2.2
Element a[2][3] = 2.3
1.100000 1.200000 1.300000
2.100000 2.200000 2.300000
SYSALLOC min=61968 max=62096 delta=128
SYSALLOC Err: Not-matched list:
SYSALLOC Bloc 90D6:0004 (8 bytes) malloc'ed at line 36 of 'MATRICE.C' not freed
SYSALLOC Bloc 90D7:0004 (8 bytes) malloc'ed at line 40 of 'MATRICE.C' not freed
SYSALLOC Bloc 90D8:0004 (12 bytes) malloc'ed at line 46 of 'MATRICE.C' not freed
SYSALLOC Bloc 90D9:0004 (12 bytes) malloc'ed at line 46 of 'MATRICE.C' not freed
SYSALLOC Bloc 90DA:0004 (8 bytes) malloc'ed at line 36 of 'MATRICE.C' not freed
SYSALLOC Bloc 90DB:0004 (8 bytes) malloc'ed at line 40 of 'MATRICE.C' not freed
SYSALLOC Bloc 90DC:0004 (12 bytes) malloc'ed at line 46 of 'MATRICE.C' not freed
SYSALLOC Bloc 90DD:0004 (12 bytes) malloc'ed at line 46 of 'MATRICE.C' not freed
SYSALLOC Err: Memory leak (128 bytes) |
ce qui montre un fonctionnement apparement correct, mais un sérieux problème de libération mémoire, comme tu l'avais évoqué.
Voici une solution plus... industrielle, disons (avec des appels à ma bibliothèque) :
http://emmanuel-delahaye.developpez.com/clib.htm
Code:
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
|
#ifndef H_ED_MATRICE_20041113095110
#define H_ED_MATRICE_20041113095110
#ifdef __cplusplus
extern "C"
{
#endif
/* matrice.h */
/* macros ============================================================== */
/* constants =========================================================== */
/* types =============================================================== */
typedef struct matrice matrice_s;
/* structures ========================================================== */
/* internal public functions =========================================== */
/* entry points ======================================================== */
matrice_s *matriceCreer (int lin, int col);
void matriceDetruire (matrice_s *maMatrice);
int matriceAfficher (matrice_s const *self);
int matriceSaisir (matrice_s *self);
int matriceRemplir (matrice_s const *self, double value);
/* public variables ==================================================== */
#ifdef __cplusplus
}
#endif
#endif /* guard */
/* Guards added by GUARD (c) ED 2000-2003 May 09 2004 Ver. 1.6 */ |
Code:
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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
/* matrice.c */
#include "matrice.h"
#include "ed/inc/sysalloc.h"
#include "ed/inc/io.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* macros ============================================================== */
/* constants =========================================================== */
/* types =============================================================== */
/* structures ========================================================== */
struct matrice
{
int nbLigne;
int nbColonne;
float **tableau;
};
/* private variables =================================================== */
/* private functions =================================================== */
/* internal public functions =========================================== */
/* entry points ======================================================== */
matrice_s *matriceCreer (int const lin, int const col)
{
matrice_s *this = NULL;
if (lin > 0 && col > 0)
{
/* creer l'objet */
this = malloc (sizeof *this);
if (this != NULL)
{
/* initialiser l'objet */
{
static const matrice_s z =
{0};
*this = z;
}
/* creer le tableau de 'lin' pointeurs
* (pas tres optimise, mais simple et sur)
*/
{
float **pp = malloc (sizeof *pp * lin);
if (pp != NULL)
{
int i;
int err = 0;
/* initialiser le tableau */
for (i = 0; i < lin; i++)
{
pp[i] = NULL;
}
/* creer les lignes */
for (i = 0; i < lin; i++)
{
float *p = malloc (sizeof *p * col);
if (p != NULL)
{
/* effacer la ligne */
int j;
for (j = 0; j < col; j++)
{
p[j] = 0;
}
pp[i] = p;
}
else
{
err = 1;
break;
}
}
/* erreur memoire ? */
if (!err)
{
this->nbColonne = col;
this->nbLigne = lin;
this->tableau = pp;
}
else
{
matriceDetruire (this), this = NULL;
}
}
}
}
}
return this;
}
void matriceDetruire (matrice_s * this)
{
if (this != NULL)
{
int i;
/* liberer les lignes */
for (i = 0; i < this->nbLigne; i++)
{
free (this->tableau[i]), this->tableau[i] = NULL;
}
/* liberer le tableau */
free (this->tableau);
/* liberer l'objet */
free (this);
}
}
int matriceAfficher (matrice_s const *this)
{
int err = 0;
if (this != NULL)
{
int i;
for (i = 0; i < this->nbLigne; i++)
{
int j;
for (j = 0; j < this->nbColonne; j++)
{
printf ("%8.2f", this->tableau[i][j]);
}
printf ("\n");
}
}
else
{
err = 1;
}
return err;
}
int matriceRemplir (matrice_s const *this, double value)
{
int err = 0;
if (this != NULL)
{
int i;
for (i = 0; i < this->nbLigne; i++)
{
int j;
for (j = 0; j < this->nbColonne; j++)
{
this->tableau[i][j] = value;
}
}
}
else
{
err = 1;
}
return err;
}
int matriceSaisir (matrice_s * this)
{
int err = 0;
if (this != NULL)
{
int i;
for (i = 0; i < this->nbLigne; i++)
{
int j;
printf ("\nLigne %d :\n", i + 1);
for (j = 0; j < this->nbColonne; j++)
{
double value;
printf ("\nElement a[%d][%d] = ", i + 1, j + 1);
get_d (&value);
/* des controles sont possibles ici... */
this->tableau[i][j] = value;
}
}
}
else
{
err = 1;
}
return err;
}
/* public variables ==================================================== */ |
Code:
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
|
/* main.c */
#include "ed/inc/sysalloc.h"
#include "ed/inc/io.h"
#include "matrice.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main_ (void)
{
int lin, col;
long l;
matrice_s *maMatrice;
printf ("Nombre de lignes : ");
get_l (&l);
lin = (int) l;
printf ("\nNombre de colonnes : ");
get_l (&l);
col = (int) l;
maMatrice = matriceCreer (lin, col);
matriceRemplir (maMatrice, 4);
matriceAfficher (maMatrice);
matriceSaisir (maMatrice);
matriceAfficher (maMatrice);
matriceDetruire (maMatrice);
system ("PAUSE");
return 0;
}
int main (void)
{
int ret;
static char Trace[1 << 8];
SYS_INIT (Trace, OFF);
ret = main_();
sys_mem_trace();
return ret;
} |