Opérations matrices problème structure pointeur

Opérations matrices problème structure pointeur - C - Programmation

Marsh Posté le 12-01-2007 à 23:47:28    

Salut à tous :hello:  Ne soyez pas effrayé par la longueur du post: je pose juste une toute petite question de syntaxe à la fin :D
 
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:
 

Code :
  1. #include <stdio.h>
  2. #define M 4
  3. typedef struct{
  4.         int matrice[M][M];
  5.         int nbligne;
  6.         int nbcolonne;
  7.         int ident;
  8.         }matrice_type;
  9. void afficheMenu(){
  10.      printf("    ## Alemna 0.0.1 ##\n" );
  11.      printf("\n1) Initialiser une matrice" );
  12.      printf("\n2) Additionner 2 matrices" );
  13.      printf("\n3) Multiplier 2 matrices" );
  14.      printf("\n4) Afficher une matrice\n" );
  15. }
  16. int identification(){
  17.      int temp;
  18.      printf("\nEntrez l'identificateur de la matrice: " );
  19.      scanf("%d",&temp);
  20.      return temp;
  21.      }
  22. void initialiser(int tab[M][M],int *nbligne, int *nbcolonne){
  23.      int ligne,colonne,temp;
  24.      printf("# Initialisation d'une matrice #\n\n" );
  25.      printf("Nombre de lignes: " );scanf("%d",nbligne);
  26.      printf("Nombre de colonnes: " );scanf("%d",nbcolonne);
  27.      for(ligne=0;ligne<*nbligne;ligne++)
  28.         for(colonne=0;colonne<*nbcolonne;colonne++){
  29.         printf("Valeur en [%d,%d]: ",ligne,colonne);
  30.         scanf("%d",&temp);
  31.         tab[ligne][colonne]=temp;}
  32.         }
  33. void afficher(int tab[M][M],int nbligne, int nbcolonne){
  34.      int ligne,colonne;
  35.      printf("\nMatrice:\n\n" );
  36.      for(ligne=0;ligne<nbligne;ligne++){
  37.         for(colonne=0;colonne<nbcolonne;colonne++)
  38.            printf("\t%d",tab[ligne][colonne]);
  39.         printf("\n\n" );
  40.         }
  41.      }
  42. void zero(int tab[M][M],int nbligne,int nbcolonne){
  43.      int ligne,colonne;
  44.      for(ligne=0;ligne<nbligne;ligne++)
  45.         for(colonne=0;colonne<nbcolonne;colonne++){
  46.         tab[ligne][colonne]=0;}
  47.         }
  48. void additionner(int matA[M][M],int nbligneA,int nbcolonneA,int matB[M][M],int nbligneB,int nbcolonneB,int resultat[M][M], int *nbligneR,int *nbcolonneR){
  49.      int ligne,colonne,curs;
  50.      *nbligneR=nbligneA;
  51.      *nbcolonneR=nbcolonneA;
  52.      zero(resultat,*nbligneR,*nbcolonneR);
  53.    
  54.      for(ligne=0;ligne<*nbligneR;ligne++)
  55.         for(colonne=0;colonne<*nbcolonneR;colonne++)
  56.         resultat[ligne][colonne]=matA[ligne][colonne]+matB[ligne][colonne];
  57.          
  58. }
  59. void multiplier(int matA[M][M],int nbligneA,int nbcolonneA,int matB[M][M],int nbligneB,int nbcolonneB,int resultat[M][M], int *nbligneR,int *nbcolonneR){
  60.      int ligne,colonne,curs;
  61.      *nbligneR=nbligneA;
  62.      *nbcolonneR=nbcolonneB;
  63.      zero(resultat,*nbligneR,*nbcolonneR);
  64.    
  65.      for(ligne=0;ligne<*nbligneR;ligne++)
  66.         for(colonne=0;colonne<*nbcolonneR;colonne++)
  67.            for(curs=0;curs<nbcolonneA;curs++){
  68.            resultat[ligne][colonne]+=(matA[ligne][curs]*matB[curs][colonne]);
  69.            }
  70. void main()
  71. {
  72.   matrice_type matA[3];
  73.   matrice_type resultat;
  74.   int i,curseur;
  75.  
  76.   while(curseur!=0){
  77.      afficheMenu();
  78.      scanf("%d",&curseur);
  79.      system("cls" );
  80.      switch(curseur){
  81.                      case 1: i=identification()-1;
  82.                              matA.ident=i-1;
  83.                              initialiser(matA[i].matrice,&matA[i].nbligne,&matA[i].nbcolonne);
  84.                              afficher(matA[i].matrice,matA[i].nbligne,matA[i].nbcolonne);
  85.                              system("PAUSE" );
  86.                              system("cls" );
  87.                              break;
  88.                    
  89.                      case 2: additionner(matA[0].matrice,matA[0].nbligne,matA[0].nbcolonne,matA[1].matrice,matA[1].nbligne,matA[1].nbcolonne,resultat.matrice,&resultat.nbligne,&resultat.nbcolonne);break;
  90.                      case 3: multiplier(matA[0].matrice,matA[0].nbligne,matA[0].nbcolonne,matA[1].matrice,matA[1].nbligne,matA[1].nbcolonne,resultat.matrice,&resultat.nbligne,&resultat.nbcolonne);break;
  91.                      case 4: i=identification()-1;
  92.                              if (i==9) afficher(resultat.matrice,resultat.nbligne,resultat.nbcolonne);
  93.                              else afficher(matA[i].matrice,matA[i].nbligne,matA[i].nbcolonne);
  94.                              system("PAUSE" );
  95.                              system("cls" );
  96.                              break;
  97.                    
  98.                      }
  99.   }
  100.   system("PAUSE" );
  101. }


 
Bon c'est très lourd dans les arguments des fonctions je sais [:cupra]  C'est pourquoi je me suis dit: "quel idiot pourquoi tu ne met pas juste une structure sous forme de pointeur en argument?"  [:chris barnes]  
 
Alors j'ai obtenu ça:
 

Code :
  1. #include <stdio.h>
  2. #define M 4
  3. typedef struct{
  4.         int matrice[M][M];
  5.         int nbligne;
  6.         int nbcolonne;
  7.         int ident;
  8.         }matrice_type;
  9. void afficheMenu(){
  10.      printf("    ## Alemna 0.0.2 ##\n" );
  11.      printf("\n1) Initialiser une matrice" );
  12.      printf("\n2) Additionner 2 matrices" );
  13.      printf("\n3) Multiplier 2 matrices" );
  14.      printf("\n4) Afficher une matrice\n" );
  15. }
  16. int identification(){
  17.      int temp;
  18.      printf("\nEntrez l'identificateur de la matrice: " );
  19.      scanf("%d",&temp);
  20.      return temp;
  21.      }
  22. void initialiser(matrice_type *mat){
  23.      int ligne,colonne,temp;
  24.    
  25.      printf("# Initialisation d'une matrice #\n\n" );
  26.      printf("Nombre de lignes: " );scanf("%d",&mat->nbligne);
  27.      printf("Nombre de colonnes: " );scanf("%d",&mat->nbcolonne);
  28.    
  29.      for(ligne=0;ligne<mat->nbligne;ligne++)
  30.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  31.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  32.            scanf("%d",&temp);
  33.            mat->matrice[ligne][colonne]=temp;}
  34.         }
  35. void afficher(matrice_type mat){
  36.      int ligne,colonne;
  37.    
  38.      printf("\nMatrice:\n\n" );
  39.    
  40.      for(ligne=0;ligne<mat.nbligne;ligne++){
  41.         for(colonne=0;colonne<mat.nbcolonne;colonne++)
  42.            printf("\t%d",mat.matrice[ligne][colonne]);
  43.            printf("\n\n" );
  44.         }
  45.      }
  46. void zero(matrice_type *mat){
  47.      int ligne,colonne;
  48.      for(ligne=0;ligne<mat->nbligne;ligne++)
  49.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  50.         mat->matrice[ligne][colonne]=0;}
  51.         }
  52. void additionner(matrice_type matA,matrice_type matB,matrice_type *resultat){
  53.      int ligne,colonne,curs;
  54.    
  55.      resultat->nbligne=matA.nbligne;
  56.      resultat->nbcolonne=matA.nbcolonne;
  57.      zero(resultat);
  58.    
  59.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  60.         for(colonne=0;resultat->nbcolonne;colonne++)
  61.         resultat->matrice[ligne][colonne]=matA[ligne][colonne]+matB[ligne][colonne];
  62.          
  63. }
  64. void multiplier(matrice_type matA,matrice_type matB,matrice_type *resultat){
  65.      int ligne,colonne,curs;
  66.      resultat->nbligne=matA.nbligne;
  67.      resultat->nbcolonne=matB.nbcolonne;
  68.      zero(&resultat);
  69.    
  70.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  71.         for(colonne=0;colonne<resultat->nbcolonne;colonne++)
  72.            for(curs=0;curs<matA.nbcolonne;curs++){
  73.            resultat->matrice[ligne][colonne]+=(matA[ligne][curs]*matB[curs][colonne]);
  74.            }
  75. void main()
  76. {
  77.   matrice_type mat[3];
  78.   matrice_type resultat;
  79.   int i,curseur;
  80.  
  81.   while(curseur!=0){
  82.      afficheMenu();
  83.      scanf("%d",&curseur);
  84.      system("cls" );
  85.      switch(curseur){
  86.                      case 1: i=identification()-1;
  87.                              matA[i].ident=i-1;
  88.                              initialiser(&mat[i]);
  89.                              afficher(mat[i]);
  90.                              system("PAUSE" );
  91.                              system("cls" );
  92.                              break;
  93.                    
  94.                      case 2: additionner(mat[0],mat[1],&resultat);break;
  95.                      case 3: multiplier(mat[0],mat[1],&resultat);break;
  96.                      case 4: i=identification()-1;
  97.                              if (i==9) afficher(resultat);
  98.                              else afficher(mat[i]);
  99.                              system("PAUSE" );
  100.                              system("cls" );
  101.                              break;
  102.                    
  103.                      }
  104.   }
  105.   system("PAUSE" );
  106. }


 
Oui mais si je poste c'est qu'il y a un problème :D 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])
 

Code :
  1. void additionner(matrice_type matA,matrice_type matB,matrice_type *resultat){
  2.      int ligne,colonne,curs;
  3.    
  4.      resultat->nbligne=matA.nbligne;
  5.      resultat->nbcolonne=matA.nbcolonne;
  6.      zero(resultat);
  7.    
  8.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  9.         for(colonne=0;resultat->nbcolonne;colonne++)
  10.         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 cité 1 fois
Message édité par ngkreator le 12-01-2007 à 23:55:48
Reply

Marsh Posté le 12-01-2007 à 23:47:28   

Reply

Marsh Posté le 13-01-2007 à 00:08:41    

ngkreator a écrit :

Salut à tous :hello:  Ne soyez pas effrayé par la longueur du post: je pose juste une toute petite question de syntaxe à la fin :D
<...>

 
Code :
  1. 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).


Ben pour la syntaxe vu le type de MatA et MatB, c'est :

 
Code :
  1. resultat->matrice[ligne][colonne]=matA.matrice[ligne][colonne]+matB.matrice[ligne][colonne];


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...


Project   : Forums
Compiler  : GNU GCC Compiler (called directly)
Directory : C:\dev\forums2\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.c
main.c:14: warning: function declaration isn't a prototype
main.c:23: warning: function declaration isn't a prototype
main.c: In function `additionner':
main.c:76: warning: unused variable `curs'
main.c: In function `multiplier':
main.c:95: warning: passing arg 1 of `zero' from incompatible pointer type
main.c: At top level:
main.c:107: warning: function declaration isn't a prototype
main.c:107: warning: return type of 'main' is not `int'
main.c: In function `main':
main.c:116: warning: implicit declaration of function `system'
main.c:121: error: `matA' undeclared (first use in this function)
main.c:121: error: (Each undeclared identifier is reported only once
main.c:121: error: for each function it appears in.)
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 7 warnings

Message cité 1 fois
Message édité par Emmanuel Delahaye le 13-01-2007 à 00:11:55

---------------
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 13-01-2007 à 00:12:26    

Emmanuel Delahaye a écrit :

Ben pour la syntaxe vu le type de MatA et MatB, c'est :  
 

Code :
  1. resultat->matrice[ligne][colonne]=matA.matrice[ligne][colonne]+matB.matrice[ligne][colonne];


mais passer une structure par valeur, c'est des plus crades...
 
http://www.siteduzero.com/forum-83 [...] ml#r955806

Ah oui c'est vrai j'ai oublié de remplacer matA par matA.matrice :jap:  
 
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 :  
A part ça, c'est pas fini...


Project   : Forums
Compiler  : GNU GCC Compiler (called directly)
Directory : C:\dev\forums2\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.c
main.c:14: warning: function declaration isn't a prototype
main.c:23: warning: function declaration isn't a prototype
main.c: In function `additionner':
main.c:76: warning: unused variable `curs'
main.c: In function `multiplier':
main.c:95: warning: passing arg 1 of `zero' from incompatible pointer type
main.c: At top level:
main.c:107: warning: function declaration isn't a prototype
main.c:107: warning: return type of 'main' is not `int'
main.c: In function `main':
main.c:116: warning: implicit declaration of function `system'
main.c:121: error: `matA' undeclared (first use in this function)
main.c:121: error: (Each undeclared identifier is reported only once
main.c:121: error: for each function it appears in.)
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 7 warnings


C'est ce que tu as obtenu en le compilant? Ah ben oui! Il y avait d'autres étourderies en fait:
 

Code :
  1. #include <stdio.h>
  2. #define M 4
  3. typedef struct{
  4.         int matrice[M][M];
  5.         int nbligne;
  6.         int nbcolonne;
  7.         int ident;
  8.         }matrice_type;
  9. void afficheMenu(){
  10.      printf("    ## ALEMNA ##\n" );
  11.      printf("\n1) Initialiser une matrice" );
  12.      printf("\n2) Additionner 2 matrices" );
  13.      printf("\n3) Multiplier 2 matrices" );
  14.      printf("\n4) Afficher une matrice\n" );
  15. }
  16. int identification(){
  17.      int temp;
  18.      printf("\nEntrez l'identificateur de la matrice: " );
  19.      scanf("%d",&temp);
  20.      return temp;
  21.      }
  22. void initialiser(matrice_type *mat){
  23.      int ligne,colonne,temp;
  24.    
  25.      printf("# Initialisation d'une matrice #\n\n" );
  26.      printf("Nombre de lignes: " );scanf("%d",&mat->nbligne);
  27.      printf("Nombre de colonnes: " );scanf("%d",&mat->nbcolonne);
  28.    
  29.      for(ligne=0;ligne<mat->nbligne;ligne++)
  30.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  31.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  32.            scanf("%d",&temp);
  33.            mat->matrice[ligne][colonne]=temp;}
  34.         }
  35. void afficher(matrice_type mat){
  36.      int ligne,colonne;
  37.    
  38.      printf("\nMatrice:\n\n" );
  39.    
  40.      for(ligne=0;ligne<mat.nbligne;ligne++){
  41.         for(colonne=0;colonne<mat.nbcolonne;colonne++)
  42.            printf("\t%d",mat.matrice[ligne][colonne]);
  43.            printf("\n\n" );
  44.         }
  45.      }
  46. void zero(matrice_type *mat){
  47.      int ligne,colonne;
  48.      for(ligne=0;ligne<mat->nbligne;ligne++)
  49.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  50.         mat->matrice[ligne][colonne]=0;}
  51.         }
  52. void additionner(matrice_type matA,matrice_type matB,matrice_type *resultat){
  53.      int ligne,colonne,curs;
  54.    
  55.      resultat->nbligne=matA.nbligne;
  56.      resultat->nbcolonne=matA.nbcolonne;
  57.      zero(resultat);
  58.    
  59.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  60.         for(colonne=0;resultat->nbcolonne;colonne++)
  61.         resultat->matrice[ligne][colonne]=matA.matrice[ligne][colonne]+matB.matrice[ligne][colonne];
  62.          
  63. }
  64. void multiplier(matrice_type matA,matrice_type matB,matrice_type *resultat){
  65.      int ligne,colonne,curs;
  66.      resultat->nbligne=matA.nbligne;
  67.      resultat->nbcolonne=matB.nbcolonne;
  68.      zero(resultat);
  69.    
  70.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  71.         for(colonne=0;colonne<resultat->nbcolonne;colonne++)
  72.            for(curs=0;curs<matA.nbcolonne;curs++){
  73.            resultat->matrice[ligne][colonne]+=(matA.matrice[ligne][curs]*matB.matrice[curs][colonne]);
  74.            }
  75. void main()
  76. {
  77.   matrice_type mat[3];
  78.   matrice_type resultat;
  79.   int i,curseur;
  80.  
  81.   while(curseur!=0){
  82.      afficheMenu();
  83.      scanf("%d",&curseur);
  84.      system("cls" );
  85.      switch(curseur){
  86.                      case 1: i=identification()-1;
  87.                              mat[i].ident=i;
  88.                              initialiser(&mat[i]);
  89.                              afficher(mat[i]);
  90.                              system("PAUSE" );
  91.                              system("cls" );
  92.                              break;
  93.                    
  94.                      case 2: additionner(mat[0],mat[1],&resultat);break;
  95.                      case 3: multiplier(mat[0],mat[1],&resultat);break;
  96.                      case 4: i=identification()-1;
  97.                              if (i==9) afficher(resultat);
  98.                              else afficher(mat[i]);
  99.                              system("PAUSE" );
  100.                              system("cls" );
  101.                              break;
  102.                    
  103.                      }
  104.   }
  105.   system("PAUSE" );
  106. }


 
Bon maitenant le programme se lance mais le résultat des matrices laisse à désirer. Je vais voir ça [:ngkreator]
 
Edit2: ah ben si les multiplications marchent très bien, mais le programme se ferme lors des additions [:million dollar baby]


Message édité par ngkreator le 13-01-2007 à 00:40:22
Reply

Marsh Posté le 15-01-2007 à 12:23:53    

C'est bon tout fonctionne :) Merci beaucoup pour ton aide  :jap:  
 
Voilà ce que j'obtiens:
 

Code :
  1. #include <stdio.h>
  2. #define M 4
  3. //On défini une structure {Matrice} {nbre ligne} {nbre colonne} {n° identification}
  4. typedef struct{
  5.         int matrice[M][M];
  6.         int nbligne;
  7.         int nbcolonne;
  8.         int ident;
  9.         }matrice_type;
  10. //____________Définition des fonctions________________//
  11. //____________________________________________________//
  12. void afficheMenu(){
  13.      printf("    ## MINDO 0.0.3 ##\n" );
  14.      printf("\n1) Initialiser une matrice" );
  15.      printf("\n2) Additionner 2 matrices" );
  16.      printf("\n3) Multiplier 2 matrices" );
  17.      printf("\n4) Afficher une matrice\n" );
  18. }
  19. //Demande le N° d'identification puis l'insere dans la structure
  20. int identification(){
  21.      int temp;
  22.      printf("\nEntrez l'identificateur de la matrice: " );
  23.      scanf("%d",&temp);
  24.      return temp;
  25.      }
  26. void initialiser(matrice_type *mat){
  27.      int ligne,colonne,temp;
  28.    
  29.      printf("# Initialisation d'une matrice #\n\n" );
  30.      printf("Nombre de lignes: " );scanf("%d",&mat->nbligne);
  31.      printf("Nombre de colonnes: " );scanf("%d",&mat->nbcolonne);
  32.    
  33.      for(ligne=0;ligne<mat->nbligne;ligne++)
  34.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  35.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  36.            scanf("%d",&temp);
  37.            mat->matrice[ligne][colonne]=temp;}
  38.         }
  39. void afficher(matrice_type mat){
  40.      int ligne,colonne;
  41.    
  42.      printf("\nMatrice:\n\n" );
  43.    
  44.      for(ligne=0;ligne<mat.nbligne;ligne++){
  45.         for(colonne=0;colonne<mat.nbcolonne;colonne++)
  46.            printf("\t%d",mat.matrice[ligne][colonne]);
  47.            printf("\n\n" );
  48.         }
  49.      system("PAUSE" );
  50.      system("cls" );
  51.      }
  52. void zero(matrice_type *mat){
  53.      int ligne,colonne;
  54.      for(ligne=0;ligne<mat->nbligne;ligne++)
  55.         for(colonne=0;colonne<mat->nbcolonne;colonne++){
  56.         mat->matrice[ligne][colonne]=0;}
  57.         }
  58. void additionner(matrice_type matA,matrice_type matB,matrice_type *resultat){
  59.      int ligne,colonne,curs;
  60.    
  61.      if((matA.nbligne==matB.nbligne) && (matA.nbcolonne==matB.nbcolonne)){
  62.         resultat->nbligne=matA.nbligne;
  63.         resultat->nbcolonne=matA.nbcolonne;
  64.         zero(resultat);
  65.    
  66.         for(ligne=0;ligne<resultat->nbligne;ligne++)
  67.            for(colonne=0;colonne<resultat->nbcolonne;colonne++)
  68.               resultat->matrice[ligne][colonne]=matA.matrice[ligne][colonne]+matB.matrice[ligne][colonne];
  69.      }
  70.      else
  71.         printf("Erreur: les 2 matrices ne sont pas de même dimension." );
  72. }
  73. void multiplier(matrice_type matA,matrice_type matB,matrice_type *resultat){
  74.      int ligne,colonne,curs;
  75.    
  76.      resultat->nbligne=matA.nbligne;
  77.      resultat->nbcolonne=matB.nbcolonne;
  78.      zero(resultat);
  79.    
  80.      for(ligne=0;ligne<resultat->nbligne;ligne++)
  81.         for(colonne=0;colonne<resultat->nbcolonne;colonne++)
  82.            for(curs=0;curs<matA.nbcolonne;curs++){
  83.            resultat->matrice[ligne][colonne]+=(matA.matrice[ligne][curs]*matB.matrice[curs][colonne]);
  84.            }
  85. //______________Le programme______________//
  86. //________________________________________//
  87. void main()
  88. {
  89.   matrice_type mat[3];
  90.   matrice_type resultat;
  91.   int i,curseur;
  92.  
  93.   while(curseur!=0){
  94.      afficheMenu();
  95.      scanf("%d",&curseur);
  96.      system("cls" );
  97.      switch(curseur){
  98.                      case 1: i=identification()-1;
  99.                              mat[i].ident=i;
  100.                              initialiser(&mat[i]);
  101.                              afficher(mat[i]);
  102.                              break;
  103.                    
  104.                      case 2: additionner(mat[0],mat[1],&resultat);
  105.                              afficher(resultat);
  106.                              break;
  107.                            
  108.                      case 3: multiplier(mat[0],mat[1],&resultat);
  109.                              afficher(resultat);
  110.                              break;
  111.                            
  112.                      case 4: i=identification()-1;
  113.                              if (i==9) afficher(resultat);
  114.                              else afficher(mat[i]);
  115.                              break;
  116.                      }
  117.   }
  118.   system("PAUSE" );
  119. }


 
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 :)

Reply

Marsh Posté le 15-01-2007 à 13:14:04    

Tiens, tu devrais commencer par ameliorer ce petit bout de code:

Code :
  1. #define M 4
  2. //On défini une structure {Matrice} {nbre ligne} {nbre colonne} {n° identification}
  3. typedef struct
  4. {
  5.         int matrice[M][M];
  6.         int nbligne;
  7.         int nbcolonne;
  8. ...

Message cité 1 fois
Message édité par breizhbugs le 15-01-2007 à 13:14:56
Reply

Marsh Posté le 15-01-2007 à 16:05:23    

breizhbugs a écrit :

Tiens, tu devrais commencer par ameliorer ce petit bout de code:

Code :
  1. #define M 4
  2. //On défini une structure {Matrice} {nbre ligne} {nbre colonne} {n° identification}
  3. typedef struct
  4. {
  5.         int matrice[M][M];
  6.         int nbligne;
  7.         int nbcolonne;
  8. ...



C'est une blague?  :??:

Reply

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 ?

Reply

Marsh Posté le 15-01-2007 à 20:27:51    

breizhbugs a écrit :

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 ?

Ah non je pensais que tu disais qu'il fallait que je refasse tout le code (que c'était de la merde quoi :D ). 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 :D).  
 
Donc au final j'ai mis 4 pour mes tests [:spamafote]
 
Maintenant je ne vois vraiment pas comment faire. Y a-t-il une technique utilisée d'habitude pour ce genre de cas?

Message cité 1 fois
Message édité par ngkreator le 15-01-2007 à 20:30:21
Reply

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 {
    int **matrice;
    unsigned short nbLig;
    unsigned short nbCol;
} t_matrice;
 
fonction_quelconque()
{
    t_matrice M;
    unsigned short i;
 
    // Saisie M.nbLig et M.nbCol
    ...
 
    // Création
    M.matrice=malloc(M.nbLig * sizeof(int*));
 
    for (i=0; i < M.nbLig; i++)
        M.matrice[i]=malloc(M.nbCol * sizeof(int));
}


 
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...


Message édité par Sve@r le 15-01-2007 à 21:44:30

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

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  :jap:

Message cité 1 fois
Message édité par ngkreator le 15-01-2007 à 22:17:29
Reply

Marsh Posté le 15-01-2007 à 22:16:02   

Reply

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.

Reply

Marsh Posté le 15-01-2007 à 22:57:00    

Ok je verrai tout ça :jap:


Message édité par ngkreator le 15-01-2007 à 22:57:10
Reply

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  :jap:


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;
tab=malloc(10);      // Allocation de 10 octets => T'as accès à tous les octets de "tab[0]" jusqu'à "tab[9]".
<... travail ...>
free(tab);              // Le bloc est libéré


Message édité par Sve@r le 16-01-2007 à 07:13:45

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

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 :
  1. typedef struct{
  2.         int **matrice;
  3.         int nLig;
  4.         int nCol;
  5.         int id;
  6.         }matrice_type;


 
J'ai crée une nouvelle fonction qui renvoie un pointeur avec l'espace mémoire dédiée demandé:
 

Code :
  1. int **alloueEspace(int nLig,int nCol){
  2.     int **pointeur,i;
  3.    
  4.     pointeur=malloc(nLig*sizeof(int*));
  5.     for(i=0;i<nCol;i++)
  6.        pointeur[i]=malloc(nCol*sizeof(int));
  7.        return pointeur;
  8. }


 
 
Donc voilà en gros c'est presque tout ce que j'avais à modifier. :D 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 :
  1. void initialiser(matrice_type *mat){
  2.      int ligne,colonne,temp;
  3.    
  4.      printf("# Initialisation d'une matrice #\n\n" );
  5.      printf("Nombre de lignes: " );scanf("%d",&mat->nLig);
  6.      printf("Nombre de colonnes: " );scanf("%d",&mat->nCol);
  7.    
  8.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);
  9.      for(ligne=0;ligne<mat->nLig;ligne++)
  10.         for(colonne=0;colonne<mat->nCol;colonne++){
  11.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  12.            scanf("%d",&temp);
  13.            mat->matrice[ligne][colonne]=temp;}
  14.         }


 
Et à la ligne 4 ici:
 

Code :
  1. void zero(matrice_type *mat){
  2.      int ligne,colonne;
  3.    
  4.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);
  5.    
  6.      for(ligne=0;ligne<mat->nLig;ligne++)
  7.         for(colonne=0;colonne<mat->nCol;colonne++){
  8.         mat->matrice[ligne][colonne]=0;}
  9.         }


 
 
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 :D Mais c'est mieux!
 
 
Sinon j'ai 2 questions toutes simples.  
 

  • Disons qu'on a une structure composée d'un pointeur. Si je fait appel à la structure dans une fonction, mais sous forme de pointeur, je devrai avoir avec au pointeur (celui dans la structure) avec la ligne suivante: structure->pointeur  sachant que la structure est déclarée comme ça: typedef struct{ int *pointeur; ...}structure;


Et pour accéder au conteur pointé par le pointeur je devrai taper: structure->*pointeur  
 
Apparemment ça fonctionne mais je voudrai être sûr :jap:
 

  • Je n'ai pas libéré les pointeurs à la fin avec la fonction free() En fait je ne sais pas où la mettre. Si je la mets trop tôt mes matrices vont disparaitre.  Je la mets donc à la fin? Mais dans ce cas là est-ce vraiment utile? Et à quoi ça sert exactement?


Merci :jap:  
 
 
 
 
 
 
 
 
Le code final:
 

Code :
  1. #include <stdio.h>
  2. //On défini une structure {Matrice} {nbre ligne} {nbre colonne} {n° identification}
  3. typedef struct{
  4.         int **matrice;
  5.         int nLig;
  6.         int nCol;
  7.         int id;
  8.         }matrice_type;
  9. //____________Définition des fonctions________________//
  10. //____________________________________________________//
  11. int **alloueEspace(int nLig,int nCol){
  12.     int **pointeur,i;
  13.    
  14.     pointeur=malloc(nLig*sizeof(int*));
  15.     for(i=0;i<nCol;i++)
  16.        pointeur[i]=malloc(nCol*sizeof(int));
  17.        return pointeur;
  18. }
  19. void afficheMenu(){
  20.      printf("    ## MINDO 0.0.4 ##\n" );
  21.      printf("\n1) Initialiser une matrice" );
  22.      printf("\n2) Additionner 2 matrices" );
  23.      printf("\n3) Multiplier 2 matrices" );
  24.      printf("\n4) Afficher une matrice\n" );
  25. }
  26. //Demande le N° d'identification puis l'insere dans la structure
  27. int identification(){
  28.      int temp;
  29.      printf("\nEntrez l'identificateur de la matrice: " );
  30.      scanf("%d",&temp);
  31.      return temp;
  32.      }
  33. void initialiser(matrice_type *mat){
  34.      int ligne,colonne,temp;
  35.    
  36.      printf("# Initialisation d'une matrice #\n\n" );
  37.      printf("Nombre de lignes: " );scanf("%d",&mat->nLig);
  38.      printf("Nombre de colonnes: " );scanf("%d",&mat->nCol);
  39.    
  40.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);
  41.      for(ligne=0;ligne<mat->nLig;ligne++)
  42.         for(colonne=0;colonne<mat->nCol;colonne++){
  43.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  44.            scanf("%d",&temp);
  45.            mat->matrice[ligne][colonne]=temp;}
  46.         }
  47. void afficher(matrice_type mat){
  48.      int ligne,colonne;
  49.    
  50.      printf("\nMatrice:\n\n" );
  51.    
  52.      for(ligne=0;ligne<mat.nLig;ligne++){
  53.         for(colonne=0;colonne<mat.nCol;colonne++)
  54.            printf("\t%d",mat.matrice[ligne][colonne]);
  55.            printf("\n\n" );
  56.         }
  57.      system("PAUSE" );
  58.      system("cls" );
  59.      }
  60. void zero(matrice_type *mat){
  61.      int ligne,colonne;
  62.    
  63.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);
  64.    
  65.      for(ligne=0;ligne<mat->nLig;ligne++)
  66.         for(colonne=0;colonne<mat->nCol;colonne++){
  67.         mat->matrice[ligne][colonne]=0;}
  68.         }
  69. void additionner(matrice_type matA,matrice_type matB,matrice_type *resultat){
  70.      int ligne,colonne,curs;
  71.    
  72.      if((matA.nLig==matB.nLig) && (matA.nCol==matB.nCol)){
  73.         resultat->nLig=matA.nLig;
  74.         resultat->nCol=matA.nCol;
  75.         zero(resultat);
  76.    
  77.         for(ligne=0;ligne<resultat->nLig;ligne++)
  78.            for(colonne=0;colonne<resultat->nCol;colonne++)
  79.               resultat->matrice[ligne][colonne]=matA.matrice[ligne][colonne]+matB.matrice[ligne][colonne];
  80.      }
  81.      else
  82.         printf("Erreur: les 2 matrices ne sont pas de même dimension." );
  83. }
  84. void multiplier(matrice_type matA,matrice_type matB,matrice_type *resultat){
  85.      int ligne,colonne,curs;
  86.    
  87.      resultat->nLig=matA.nLig;
  88.      resultat->nCol=matB.nCol;
  89.      zero(resultat);
  90.    
  91.      for(ligne=0;ligne<resultat->nLig;ligne++)
  92.         for(colonne=0;colonne<resultat->nCol;colonne++)
  93.            for(curs=0;curs<matA.nCol;curs++){
  94.            resultat->matrice[ligne][colonne]+=(matA.matrice[ligne][curs]*matB.matrice[curs][colonne]);
  95.            }
  96. //______________Le programme______________//
  97. //________________________________________//
  98. void main()
  99. {
  100.   matrice_type mat[3];
  101.   matrice_type resultat;
  102.   int i,curseur;
  103.  
  104.   while(curseur!=0){
  105.      afficheMenu();
  106.      scanf("%d",&curseur);
  107.      system("cls" );
  108.      switch(curseur){
  109.                      case 1: i=identification()-1;
  110.                              mat[i].id=i;
  111.                              initialiser(&mat[i]);
  112.                              afficher(mat[i]);
  113.                              break;
  114.                    
  115.                      case 2: additionner(mat[0],mat[1],&resultat);
  116.                              afficher(resultat);
  117.                              break;
  118.                            
  119.                      case 3: multiplier(mat[0],mat[1],&resultat);
  120.                              afficher(resultat);
  121.                              break;
  122.                            
  123.                      case 4: i=identification()-1;
  124.                              if (i==9) afficher(resultat);
  125.                              else afficher(mat[i]);
  126.                              break;
  127.                      }
  128.   }
  129.   system("PAUSE" );
  130. }

Message cité 1 fois
Message édité par ngkreator le 27-01-2007 à 00:44:27
Reply

Marsh Posté le 27-01-2007 à 10:59:45    

ngkreator a écrit :

Code :
  1. void zero(matrice_type *mat){
  2.      int ligne,colonne;
  3.    
  4.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);
  5.    
  6.      for(ligne=0;ligne<mat->nLig;ligne++)
  7.         for(colonne=0;colonne<mat->nCol;colonne++){
  8.         mat->matrice[ligne][colonne]=0;}
  9.         }



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 :
  1. void zero(matrice_type *mat){
  2.      int ligne;
  3.    
  4.      mat->matrice=alloueEspace(mat->nLig,mat->nCol);     // Pas forcément judicieux
  5.    
  6.      for(ligne=0;ligne<mat->nLig;ligne++)
  7.         memset(mat->matrice[ligne], 0, mat->ncol);
  8.      // On peut aussi faire ainsi (ce qui te permettra d'apprendre à manipuler les pointeurs)
  9.      int **ptLig;
  10.      for(ligne=0, ptLig=mat->matrice; ligne<mat->nLig;ligne++, ptLig++)
  11.         memset(*ptLig, 0, mat->ncol);
  12. }


 

ngkreator a écrit :

Sinon j'ai 2 questions toutes simples.  
 

  • Disons qu'on a une structure composée d'un pointeur. Si je fait appel à la structure dans une fonction, mais sous forme de pointeur, je devrai avoir avec au pointeur (celui dans la structure) avec la ligne suivante: structure->pointeur  sachant que la structure est déclarée comme ça: typedef struct{ int *pointeur; ...}structure;


Et pour accéder au conteur pointé par le pointeur je devrai taper: structure->*pointeur


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 :

  • Je n'ai pas libéré les pointeurs à la fin avec la fonction free() En fait je ne sais pas où la mettre. Si je la mets trop tôt mes matrices vont disparaitre.  Je la mets donc à la fin? Mais dans ce cas là est-ce vraiment utile? Et à quoi ça sert exactement?

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"...

Message cité 1 fois
Message édité par Sve@r le 27-01-2007 à 11:16:36

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

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 ...

Reply

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...


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

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 :
  1. free(resultat->matrice);
  2. resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  3. zero(resultat);


 
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 :
  1. for(i=0;i<resultat->nLig;i++) memset(resultat->matrice[i],0,sizeof(int));


 
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() [:cupra]  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?

Message cité 1 fois
Message édité par ngkreator le 27-01-2007 à 13:00:37
Reply

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 :
  1. char *tab;
  2. tab=malloc(10);            // malloc me renvoie une adresse X que je stocke dans "tab"
  3. ...<travail>...
  4. tab=malloc(12);            // malloc me renvoie une adresse Y que je stocke dans "tab" => j'ai perdu "X" !!!


 

ngkreator a écrit :

Code :
  1. free(resultat->matrice);
  2. resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  3. zero(resultat);



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

Code :
  1. for(i=0;i<resultat->nLig;i++) memset(resultat->matrice[i],0,sizeof(int));


 
Ca marche très bien et je n'ai plus besoin de la fonction zero()


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"...

Message cité 1 fois
Message édité par Sve@r le 27-01-2007 à 13:33:13

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

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:

Code :
  1. char *tab;
  2. tab=malloc(10);            // malloc me renvoie une adresse X que je stocke dans "tab"
  3. ...<travail>...
  4. tab=malloc(12);            // malloc me renvoie une adresse Y que je stocke dans "tab" => j'ai perdu "X" !!!


 
 
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...

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 :


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

C'est noté.
 

Sve@r a écrit :


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é...

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 :


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"...

Ok

Reply

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)...


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

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 :
  1. /*Définition d'une structure {matrice} {nbre lignes} {nb colonnes}*/
  2. typedef struct{
  3.         int **matrice;
  4.         int nLig;
  5.         int nCol;
  6.         int id;
  7.         }matrice_type;
  8. /*Définition des fonctins*/
  9. int **alloueEspace(int nLig,int nCol){
  10.     int **pointeur,i;
  11.    
  12.     pointeur=malloc(nLig*sizeof(int*));
  13.     for(i=0;i<nCol;i++)
  14.        pointeur[i]=malloc(nCol*sizeof(int));
  15.        return pointeur;
  16. }
  17. void libereEspace(matrice_type *data){
  18.      int i;
  19.    
  20.      for(i=0;i<data->nLig;i++) free(data->matrice[i]);
  21.      free(data->matrice);
  22. }
  23. void afficheMenu(){
  24.      printf("    ## MINDO 0.0.5 ##\n" );
  25.      printf("\n1) Initialiser une matrice" );
  26.      printf("\n2) Additionner 2 matrices" );
  27.      printf("\n3) Multiplier 2 matrices" );
  28.      printf("\n4) Afficher une matrice" );
  29.      printf("\n0) Quitter le programme\n" );
  30. }
  31. //Demande le N° d'identification puis l'insere dans la structure
  32. int identification(){
  33.      int temp;
  34.      printf("\nEntrez l'identificateur de la matrice: " );
  35.      scanf("%d",&temp);
  36.      return temp;
  37. }
  38. void initialiser(matrice_type *data){
  39.      int ligne,colonne,temp;
  40.    
  41.      printf("# Initialisation d'une matrice #\n\n" );
  42.      printf("Nombre de lignes: " );scanf("%d",&data->nLig);
  43.      printf("Nombre de colonnes: " );scanf("%d",&data->nCol);
  44.    
  45.      libereEspace(data);
  46.      data->matrice=alloueEspace(data->nLig,data->nCol);
  47.      for(ligne=0;ligne<data->nLig;ligne++)
  48.         for(colonne=0;colonne<data->nCol;colonne++){
  49.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  50.            scanf("%d",&temp);
  51.            data->matrice[ligne][colonne]=temp;
  52.         }
  53. }
  54. void afficher(matrice_type mat){
  55.      int ligne,colonne;
  56.    
  57.      printf("\nMatrice:\n\n" );
  58.    
  59.      for(ligne=0;ligne<mat.nLig;ligne++){
  60.         for(colonne=0;colonne<mat.nCol;colonne++)
  61.            printf("\t%d",mat.matrice[ligne][colonne]);
  62.            printf("\n\n" );
  63.         }
  64.        
  65.      system("PAUSE" );
  66.      system("cls" );
  67. }
  68. void zero(matrice_type *data){
  69.      int i,j;
  70.      //for(i=0;i<data->nLig;i++) memset(data->matrice[i],0,data->nCol);
  71.      for(i=0;i<data->nLig;i++)
  72.         for(j=0;j<data->nCol;j++)
  73.            data->matrice[i][j]=0;
  74. }
  75. void additionner(matrice_type dataA,matrice_type dataB,matrice_type *resultat){
  76.      int ligne,colonne,curs,i;
  77.    
  78.      if((dataA.nLig==dataB.nLig) && (dataA.nCol==dataB.nCol)){
  79.         resultat->nLig=dataA.nLig;
  80.         resultat->nCol=dataA.nCol;
  81.         libereEspace(resultat);
  82.         resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  83.         zero(resultat);
  84.    
  85.         for(ligne=0;ligne<resultat->nLig;ligne++)
  86.            for(colonne=0;colonne<resultat->nCol;colonne++)
  87.               resultat->matrice[ligne][colonne]=dataA.matrice[ligne][colonne]+dataB.matrice[ligne][colonne];
  88.      }
  89.      else
  90.         printf("Erreur: les 2 matrices ne sont pas de même dimension." );
  91. }
  92. void multiplier(matrice_type dataA,matrice_type dataB,matrice_type *resultat){
  93.      int ligne,colonne,curs,i;
  94.    
  95.      resultat->nLig=dataA.nLig;
  96.      resultat->nCol=dataB.nCol;
  97.      libereEspace(resultat);
  98.      resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  99.      zero(resultat);
  100.        
  101.      for(ligne=0;ligne<resultat->nLig;ligne++)
  102.         for(colonne=0;colonne<resultat->nCol;colonne++)
  103.            for(curs=0;curs<dataA.nCol;curs++){
  104.            resultat->matrice[ligne][colonne]+=(dataA.matrice[ligne][curs]*dataB.matrice[curs][colonne]);
  105.            }
  106. }


 
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 :
  1. #include <stdio.h>
  2. #include <memory.h>
  3. #include "fonctions.h"
  4. //______________Le programme_____________//
  5. int main(void)
  6. {
  7.   matrice_type data[3];
  8.   matrice_type resultat;
  9.   int i,curseur;
  10.  
  11.   while(curseur!=0){
  12.      afficheMenu();
  13.      scanf("%d",&curseur);
  14.      system("cls" );
  15.      switch(curseur){
  16.                      case 1: i=identification()-1;
  17.                              data[i].id=i;
  18.                              initialiser(&data[i]);
  19.                              afficher(data[i]);
  20.                              break;
  21.                    
  22.                      case 2: additionner(data[0],data[1],&resultat);
  23.                              afficher(resultat);
  24.                              break;
  25.                            
  26.                      case 3: multiplier(data[0],data[1],&resultat);
  27.                              afficher(resultat);
  28.                              break;
  29.                            
  30.                      case 4: i=identification()-1;
  31.                              if (i==9) afficher(resultat);
  32.                              else afficher(data[i]);
  33.                              break;
  34.                      }
  35.   }
  36.  
  37.   for(i=0;i<3;i++) libereEspace(&data[i]);
  38.   libereEspace(&resultat);
  39.  
  40.   system("PAUSE" );
  41.   return 0;
  42. }


 
Le fichier qui contient les prototypes (on y voit plus clair) :D  

Code :
  1. /*Prototypes des fonctions*/
  2. //Alloue de l'espace mémoire au pointeur de matrice.
  3. int **alloueEspace(int nLig,int nCol);
  4. //
  5. void libereEspace(matrice_type *data);
  6. //Affiche le menu principal.
  7. void afficheMenu();
  8. //
  9. void zero(matrice_type *data);
  10. //Demande et enregistre le n° d'identifiaction d'une matrice.
  11. int identification();
  12. //Permet à l'utilisateur de créer une matrice
  13. void initialiser(matrice_type *data);
  14. //Affiche une matrice
  15. void afficher(matrice_type mat);
  16. //Additionne 2 matrices et enregistre le résultat dans une matrice.
  17. void additionner(matrice_type dataA,matrice_type dataB,matrice_type *resultat);
  18. //Multiplie 2 matrices et enregistre le résultat dans une matrice.
  19. void multiplier(matrice_type dataA,matrice_type dataB,matrice_type *resultat);


 
J'en ai profité pour commencer à apprendre à utiliser plusieurs fichiers pour clarifier le tout.

Reply

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:
 

Code :
  1. /*Définition d'une structure {matrice} {nbre lignes} {nb colonnes}*/
  2. typedef struct{
  3.         int **matrice;
  4.         int nLig;
  5.         int nCol;
  6.         int id;
  7.         }matrice_type;
  8. /*Définition des fonctins*/
  9. int **alloueEspace(int nLig,int nCol){
  10.     int **pointeur,i;
  11.    
  12.     pointeur=malloc(nLig*sizeof(int*));
  13.     for(i=0;i<nCol;i++)
  14.        pointeur[i]=malloc(nCol*sizeof(int));
  15.        return pointeur;
  16. }
  17. void libereEspace(matrice_type *data){
  18.      int i;
  19.    
  20.      for(i=0;i<data->nLig;i++) free(data->matrice[i]);
  21.      free(data->matrice);
  22. }
  23. void afficheMenu(){
  24.      printf("    ## MINDO 0.0.5 ##\n" );
  25.      printf("\n1) Initialiser une matrice" );
  26.      printf("\n2) Additionner 2 matrices" );
  27.      printf("\n3) Multiplier 2 matrices" );
  28.      printf("\n4) Afficher une matrice" );
  29.      printf("\n0) Quitter le programme\n" );
  30. }
  31. //Demande le N° d'identification puis l'insere dans la structure
  32. int identification(){
  33.      int temp;
  34.      printf("\nEntrez l'identificateur de la matrice: " );
  35.      scanf("%d",&temp);
  36.      return temp;
  37. }
  38. void initialiser(matrice_type *data){
  39.      int ligne,colonne,temp;
  40.    
  41.      printf("# Initialisation d'une matrice #\n\n" );
  42.      printf("Nombre de lignes: " );scanf("%d",&data->nLig);
  43.      printf("Nombre de colonnes: " );scanf("%d",&data->nCol);
  44.    
  45.      libereEspace(data);
  46.      data->matrice=alloueEspace(data->nLig,data->nCol);
  47.      for(ligne=0;ligne<data->nLig;ligne++)
  48.         for(colonne=0;colonne<data->nCol;colonne++){
  49.            printf("Valeur en [%d,%d]: ",ligne,colonne);
  50.            scanf("%d",&temp);
  51.            data->matrice[ligne][colonne]=temp;
  52.         }
  53. }
  54. void afficher(matrice_type mat){
  55.      int ligne,colonne;
  56.    
  57.      printf("\nMatrice:\n\n" );
  58.    
  59.      for(ligne=0;ligne<mat.nLig;ligne++){
  60.         for(colonne=0;colonne<mat.nCol;colonne++)
  61.            printf("\t%d",mat.matrice[ligne][colonne]);
  62.            printf("\n\n" );
  63.         }
  64.        
  65.      system("PAUSE" );
  66.      system("cls" );
  67. }
  68. void zero(matrice_type *data){
  69.      int i,j;
  70.      //for(i=0;i<data->nLig;i++) memset(data->matrice[i],0,data->nCol);
  71.      for(i=0;i<data->nLig;i++)
  72.         for(j=0;j<data->nCol;j++)
  73.            data->matrice[i][j]=0;
  74. }
  75. void additionner(matrice_type dataA,matrice_type dataB,matrice_type *resultat){
  76.      int ligne,colonne,curs,i;
  77.    
  78.      if((dataA.nLig==dataB.nLig) && (dataA.nCol==dataB.nCol)){
  79.         resultat->nLig=dataA.nLig;
  80.         resultat->nCol=dataA.nCol;
  81.         libereEspace(resultat);
  82.         resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  83.         zero(resultat);
  84.    
  85.         for(ligne=0;ligne<resultat->nLig;ligne++)
  86.            for(colonne=0;colonne<resultat->nCol;colonne++)
  87.               resultat->matrice[ligne][colonne]=dataA.matrice[ligne][colonne]+dataB.matrice[ligne][colonne];
  88.      }
  89.      else
  90.         printf("Erreur: les 2 matrices ne sont pas de même dimension." );
  91. }
  92. void multiplier(matrice_type dataA,matrice_type dataB,matrice_type *resultat){
  93.      int ligne,colonne,curs,i;
  94.    
  95.      resultat->nLig=dataA.nLig;
  96.      resultat->nCol=dataB.nCol;
  97.      libereEspace(resultat);
  98.      resultat->matrice=alloueEspace(resultat->nLig,resultat->nCol);
  99.      zero(resultat);
  100.        
  101.      for(ligne=0;ligne<resultat->nLig;ligne++)
  102.         for(colonne=0;colonne<resultat->nCol;colonne++)
  103.            for(curs=0;curs<dataA.nCol;curs++){
  104.            resultat->matrice[ligne][colonne]+=(dataA.matrice[ligne][curs]*dataB.matrice[curs][colonne]);
  105.            }
  106. }


 
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 :
  1. #include <stdio.h>
  2. #include <memory.h>
  3. #include "fonctions.h"
  4. //______________Le programme_____________//
  5. int main(void)
  6. {
  7.   matrice_type data[3];
  8.   matrice_type resultat;
  9.   int i,curseur;
  10.  
  11.   while(curseur!=0){
  12.      afficheMenu();
  13.      scanf("%d",&curseur);
  14.      system("cls" );
  15.      switch(curseur){
  16.                      case 1: i=identification()-1;
  17.                              data[i].id=i;
  18.                              initialiser(&data[i]);
  19.                              afficher(data[i]);
  20.                              break;
  21.                    
  22.                      case 2: additionner(data[0],data[1],&resultat);
  23.                              afficher(resultat);
  24.                              break;
  25.                            
  26.                      case 3: multiplier(data[0],data[1],&resultat);
  27.                              afficher(resultat);
  28.                              break;
  29.                            
  30.                      case 4: i=identification()-1;
  31.                              if (i==9) afficher(resultat);
  32.                              else afficher(data[i]);
  33.                              break;
  34.                      }
  35.   }
  36.  
  37.   for(i=0;i<3;i++) libereEspace(&data[i]);
  38.   libereEspace(&resultat);
  39.  
  40.   system("PAUSE" );
  41.   return 0;
  42. }



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

  • créer tes 3 matrices une seule fois
  • les remplir, réinitialiser autant de fois que tu veux
  • utiliser la matrice 3 pour récupérer le résultat des deux autres.
  • libérer les 3 matrices une seule fois

Ca sera plus rapide que de

  • libérer la matrice "résultat"
  • réallouer de la mémoire

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

  • faire un "fgets()" dans une chaîne
  • faire un "sscanf()" de la chaîne dans le nombre et vérifier que "sscanf()" renvoie bien le bon nombre de variables remplies


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 :
  1. memset(data->matrice[i],0,data->nCol * sizeof(int));


 

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

Message cité 1 fois
Message édité par Sve@r le 27-01-2007 à 16:46:52

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

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
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
 
Tu veux dire que je dois toujours avoir une fonction de la forme: void maFonction(struture_type *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
 
Ok
 
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
 
Quelles sont les avantages ou les inconvénients dans les 2 cas?
 
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
 
Ok
 
5) la bonne façon de procéder est de

  • créer tes 3 matrices une seule fois
  • les remplir, réinitialiser autant de fois que tu veux
  • utiliser la matrice 3 pour récupérer le résultat des deux autres.
  • libérer les 3 matrices une seule fois

Ca sera plus rapide que de

  • libérer la matrice "résultat"
  • réallouer de la mémoire

Pour chaque opération
 
Donc entre autre je pourrais utiliser la fonction realloc() pour redimensionner une matrice?
 
http://fr.lang.free.fr/cours/Gener [...] t_v1.0.pdf
 
Je vais voir ça


 
Merci encore de consacrer un peu de ton temps pour m'aider à faire du travail propre. :jap:

Message cité 1 fois
Message édité par ngkreator le 27-01-2007 à 16:59:54
Reply

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  
Quelles sont les avantages ou les inconvénients dans les 2 cas?


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 :
  1. matrice_type mat1;
  2. mat1.matrice=alloueEspace(...);


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 :
  1. matrice_type mat1;
  2. alloueEspace(&mat1, ...);


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

  • te faut un indicateur indiquant "alloué/jamais alloué" dans ta matrice => ça peut très bien être "elem->matrice !=/== NULL"
  • te faut initialiser cet indicateur pour toute nouvelle matrice que tu vas utiliser

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

  • tu es obligé de déclarer résultat sous cette forme: "matrice_type* res=addition(&m1, &m2);"
  • tu es obligé de penser à libérer "res" un jour où l'autre (en ayant pris soin de commencer par libérer son contenu)


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....


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

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 ?

Message cité 1 fois
Message édité par ++fab le 27-01-2007 à 21:01:21
Reply

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"...


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

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 ;)

Reply

Marsh Posté le 28-01-2007 à 01:52:26    

Sve@r a écrit :

Lapsus, j'aurais du dire "aux programmeurs du système"...
<...>
Ben une fois, Emmanuel m'a dit que non. Je vais tenter de retrouver le post...


Le suffixe _t est réservé par POSIX pour définir les types.


---------------
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 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" [:aloi]
 
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   :sol:

Message cité 1 fois
Message édité par Sve@r le 28-01-2007 à 12:50:18

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

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 :D
 
 
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 :
  1. int alloueEspace(t_matrice *data){
  2.     int i;
  3.    
  4.     data->matrice=malloc(data->nLig*sizeof(int*));
  5.     if(data->matrice==NULL) return 1;
  6.     for(i=0;i<data->nLig;i++){
  7.        data->matrice[i]=malloc(data->nCol*sizeof(int));
  8.        if(data->matrice[i]==NULL) return 1;
  9.     }
  10.     return 0;
  11. }


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 :
  1. int multiplier(t_matrice *dataA,t_matrice *dataB,t_matrice *resultat){
  2.      int ligne,colonne,curs,i,erreur;
  3.    
  4.      //Effectue la multiplication si les dimensions des 2 matrices correspondent
  5.      if(dataA->nCol==dataB->nLig){
  6.         resultat->nLig=dataA->nLig;
  7.         resultat->nCol=dataB->nCol;
  8.         //Vérifie si la matrice a déjà été allouée
  9.         if(resultat->matrice!=NULL) libereEspace(resultat);
  10.         erreur=alloueEspace(resultat);
  11.        
  12.         if(erreur==0){
  13.            zero(resultat);
  14.            for(ligne=0;ligne<resultat->nLig;ligne++)
  15.               for(colonne=0;colonne<resultat->nCol;colonne++)
  16.                  for(curs=0;curs<dataA->nCol;curs++)
  17.                  resultat->matrice[ligne][colonne]+=(dataA->matrice[ligne][curs]*dataB->matrice[curs][colonne]);
  18.         }
  19.         return 0;
  20.      }
  21.      else
  22.         return 1;
  23. }


 
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 :
  1. void saisie(int *nbre){
  2.     char str[10];
  3.     int verif=0;
  4.    
  5.     while(verif!=1){
  6.        gets(str);
  7.        verif=sscanf(str,"%d",nbre);
  8.        if(verif!=1)
  9.           printf("Erreur de saisie!\n" );
  10.     }
  11. }


 
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 :
  1. #include <stdio.h>
  2. #include <memory.h>
  3. #include "fonctions.h"
  4. //______________Le programme_____________//
  5. int main(void)
  6. {
  7.   t_matrice data[2],resultat;
  8.   int i,curseur,erreur;
  9.   for(i=0;i<2;i++) data[i].matrice=NULL;
  10.   resultat.matrice=NULL;
  11.  
  12.   while(curseur!=0){
  13.      afficheMenu();
  14.      saisie(&curseur);
  15.      system("cls" );
  16.      switch(curseur){
  17.                      //Saisie d'une matrice
  18.                      case 1: do{i=identification();}while(i!=0 && i!=1);
  19.                              data[i].id=i;
  20.                              initialiser(&data[i]);
  21.                              afficher(&data[i]);
  22.                              break;
  23.                            
  24.                      //Addition
  25.                      case 2: erreur=additionner(&data[0],&data[1],&resultat);
  26.                              if(erreur==1){
  27.                                 printf("Erreur dimension matrices\n" );
  28.                                 system("pause" );
  29.                                 system("cls" );
  30.                              }
  31.                              else
  32.                                 afficher(&resultat);
  33.                              break;
  34.                      //Multiplication
  35.                      case 3: erreur=multiplier(&data[0],&data[1],&resultat);
  36.                              if(erreur==1){
  37.                                printf("Erreur dimension matrices\n" );
  38.                                system("pause" );
  39.                                system("cls" );
  40.                              }
  41.                              else
  42.                                 afficher(&resultat);
  43.                              break;
  44.                            
  45.                      //Affichage d'une matrice au choix (en fct de l'identificateur)  
  46.                      case 4: do{i=identification();}while(i!=0&&i!=1&&i!=2);
  47.                              if (i==2) afficher(&resultat);
  48.                              else afficher(&data[i]);
  49.                              break;
  50.                      }
  51.   }
  52.  
  53.   //Libération des matrices
  54.   for(i=0;i<2;i++)
  55.      if(data[i].matrice!=NULL)//Vérifie que data a déjà été utilisée <=> nLig et nCol définis
  56.         libereEspace(&data[0]);//Si nLig et nCol définis alors pas d'erreur
  57.   if(resultat.matrice!=NULL)
  58.      libereEspace(&resultat);
  59.   system("PAUSE" );
  60.   return 0;
  61. }


 
Fichier fonctions.h
 

Code :
  1. /*Prototypes des fonctions*/
  2. void saisie(int *nbre);
  3. //Alloue de l'espace mémoire au pointeur de matrice.
  4. int alloueEspace(t_matrice *data);
  5. //
  6. void libereEspace(t_matrice *data);
  7. //Affiche le menu principal.
  8. void afficheMenu();
  9. //
  10. void zero(t_matrice *data);
  11. //Demande et enregistre le n° d'identifiaction d'une matrice.
  12. int identification();
  13. //Permet à l'utilisateur de créer une matrice
  14. int initialiser(t_matrice *data);
  15. //Affiche une matrice
  16. void afficher(t_matrice *mat);
  17. //Additionne 2 matrices et enregistre le résultat dans une matrice.
  18. int additionner(t_matrice *dataA,t_matrice *dataB,t_matrice *resultat);
  19. //Multiplie 2 matrices et enregistre le résultat dans une matrice.
  20. int multiplier(t_matrice *dataA,t_matrice *dataB,t_matrice *resultat);


 
Fichier fonctions.c
 

Code :
  1. #include <stdio.h>
  2. #include <memory.h>
  3. /*Définition d'une structure {matrice} {nbre lignes} {nb colonnes}*/
  4. typedef struct{
  5.         int **matrice;
  6.         int nLig;
  7.         int nCol;
  8.         int id;
  9.         }t_matrice;
  10. //_____Définition des fonctions______/
  11. void saisie(int *nbre){
  12.     char str[10];
  13.     int verif=0;
  14.    
  15.     while(verif!=1){
  16.        gets(str);
  17.        verif=sscanf(str,"%d",nbre);
  18.        if(verif!=1)
  19.           printf("Erreur de saisie!\n" );
  20.     }
  21. }
  22. int alloueEspace(t_matrice *data){
  23.     int i;
  24.    
  25.     data->matrice=malloc(data->nLig*sizeof(int*));
  26.     if(data->matrice==NULL) return 1;
  27.     for(i=0;i<data->nLig;i++){
  28.        data->matrice[i]=malloc(data->nCol*sizeof(int));
  29.        if(data->matrice[i]==NULL) return 1;
  30.     }
  31.     return 0;
  32. }
  33. void libereEspace(t_matrice *data){
  34.      int i;
  35.    
  36.      for(i=0;i<data->nLig;i++) free(data->matrice[i]);
  37.      free(data->matrice);
  38. }
  39. void afficheMenu(){
  40.      printf("    ## MINDO 0.0.5.1 ##\n" );
  41.      printf("\n1) Initialiser une matrice" );
  42.      printf("\n2) Additionner 2 matrices" );
  43.      printf("\n3) Multiplier 2 matrices" );
  44.      printf("\n4) Afficher une matrice" );
  45.      printf("\n0) Quitter le programme\n" );
  46. }
  47. //Demande le N° d'identification puis l'insere dans la structure
  48. int identification(){
  49.      int tmp;
  50.      printf("\nEntrez l'identificateur de la matrice: " );
  51.      saisie(&tmp);
  52.      return tmp;
  53. }
  54. //Saisie d'une matrice
  55. int initialiser(t_matrice *data){
  56.      int ligne,colonne,tmp,erreur;
  57.    
  58.      printf("# Initialisation d'une matrice #\n\n" );
  59.      printf("Nombre de lignes: " );saisie(&data->nLig);
  60.      printf("Nombre de colonnes: " );saisie(&data->nCol);
  61.    
  62.      //Libération de la matrice (si déjà allouée) puis allocation
  63.      if(data->matrice!=NULL) libereEspace(data);
  64.      erreur=alloueEspace(data);//Allocation de mémoire, et vérification de l'allocation
  65.    
  66.      if(erreur==0){
  67.         for(ligne=0;ligne<data->nLig;ligne++)
  68.            for(colonne=0;colonne<data->nCol;colonne++){
  69.               printf("Valeur en [%d,%d]: ",ligne,colonne);
  70.               saisie(&tmp);
  71.               data->matrice[ligne][colonne]=tmp;
  72.            }
  73.         return 0;
  74.      }
  75.      else
  76.         return 1;
  77. }
  78. //Affichage d'une matrice en fct de son identificateur
  79. void afficher(t_matrice *data){
  80.      int ligne,colonne;
  81.    
  82.      printf("\nMatrice:\n\n" );
  83.    
  84.      if(data->matrice!=NULL){//Vérifie qu'il s'agit bien d'une matrice définie
  85.      for(ligne=0;ligne<data->nLig;ligne++){
  86.         for(colonne=0;colonne<data->nCol;colonne++)
  87.            printf("\t%d",data->matrice[ligne][colonne]);
  88.            printf("\n\n" );
  89.         }
  90.      }
  91.      system("PAUSE" );
  92.      system("cls" );
  93. }
  94. void zero(t_matrice *data){
  95.      int i,j;
  96.      for(i=0;i<data->nLig;i++) memset(data->matrice[i],0,data->nCol*sizeof(int));
  97. }
  98. int additionner(t_matrice *dataA,t_matrice *dataB,t_matrice *resultat){
  99.      int ligne,colonne,curs,i,erreur;
  100.    
  101.      //Effectue l'addition si les 2 matrices sont de même dimensions
  102.      if((dataA->nLig==dataB->nLig) && (dataA->nCol==dataB->nCol)){
  103.         resultat->nLig=dataA->nLig;
  104.         resultat->nCol=dataA->nCol;
  105.         if(resultat->matrice!=NULL) libereEspace(resultat);
  106.         erreur=alloueEspace(resultat);
  107.         if(erreur==0){
  108.            zero(resultat);
  109.            for(ligne=0;ligne<resultat->nLig;ligne++)
  110.               for(colonne=0;colonne<resultat->nCol;colonne++)
  111.                  resultat->matrice[ligne][colonne]=dataA->matrice[ligne][colonne]+dataB->matrice[ligne][colonne];
  112.         }
  113.         return 0;
  114.      }
  115.      else
  116.         return 1;
  117. }
  118. int multiplier(t_matrice *dataA,t_matrice *dataB,t_matrice *resultat){
  119.      int ligne,colonne,curs,i,erreur;
  120.    
  121.      //Effectue la multiplication si les dimensions des 2 matrices correspondent
  122.      if(dataA->nCol==dataB->nLig){
  123.         resultat->nLig=dataA->nLig;
  124.         resultat->nCol=dataB->nCol;
  125.         if(resultat->matrice!=NULL) libereEspace(resultat);
  126.         erreur=alloueEspace(resultat);
  127.        
  128.         if(erreur==0){
  129.            zero(resultat);
  130.            for(ligne=0;ligne<resultat->nLig;ligne++)
  131.               for(colonne=0;colonne<resultat->nCol;colonne++)
  132.                  for(curs=0;curs<dataA->nCol;curs++)
  133.                  resultat->matrice[ligne][colonne]+=(dataA->matrice[ligne][curs]*dataB->matrice[curs][colonne]);
  134.         }
  135.         return 0;
  136.      }
  137.      else
  138.         return 1;
  139. }


 
 
Problèmes
 
Aucun mise à part le problème du pointeur NULL :D 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 :jap:  J'essaye d'être clair et d'apprendre un maximum, donc ne vous génez pas.

Message cité 1 fois
Message édité par ngkreator le 29-01-2007 à 11:53:33
Reply

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   :sol:


 [:roxelay]


---------------
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 29-01-2007 à 16:19:35    

ngkreator a écrit :

2) Modification des la fonction memset
 
Après ton explication ça a très bien marché!


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.
 
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 :
  1. void saisie(int *nbre){
  2.     char str[10];
  3.     int verif=0;
  4.    
  5.     while(verif!=1){
  6.        gets(str);
  7.        verif=sscanf(str,"%d",nbre);
  8.        if(verif!=1)
  9.           printf("Erreur de saisie!\n" );
  10.     }
  11. }


 
Je n'ai pas utilisé la fonction fgets car je n'ai pas encore compris son fonctionnement, mais ça va venir.


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...


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

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 :jap:  
 

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 !!!
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".

Ok je te rassure j'ai seulement mit le *.h dans le main.c :D
 
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 :


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...

D'accord!

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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