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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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:
	
| 12
 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;
} |