Partage
  • Partager sur Facebook
  • Partager sur Twitter

Fonction transposée matrice (C)

    17 mai 2010 à 20:06:42

    Bonjour,

    J'aimerais créer une fonction en C, qui me permette de faire la transposée de n'importe quelle matrice.
    Mais j'ai plusieurs problèmes pour la declaration. Par exemple : comment passer des tableau dans les fonctions?

    voici mon code :

    #include <stdio.h>
    #include <math.h>

    void transpose(double matrice,double tmatrice,int *i, int *j, int *l, int *c);

    void main(void)
    {
    ...
    }

    void transpose(double matrice,double tmatrice,int *i, int *j, int *l, int *c)
    {
    for (*i=0;*i<*l;*i++)
    {
    for (*j=0;*j<*c;*j++)
    {
    matrice[*j][*i]=tmatrice[*i][*j];
    }
    }
    }


    voila pourriez vous m'aider un petit peu please ? :)
    • Partager sur Facebook
    • Partager sur Twitter
      17 mai 2010 à 21:01:04

      Cela est très facile.
      Premièrement, pour passer un tableau on fait dans les paramètres d'une fonction "double tableau[]" ou "double *tableau".

      Attention, tu ne pourras pas calculer la taille du tableau avec un "sizeof(tableau) / sizeof(double)" car tu ne peux faire ça que dans la même fonction où tu l'as déclaré, pour toi, je suppose que tu as déclaré ton tableau dans le main. Donc tu devras passer en paramètre la longueur de chaque tableau.


      Mais dis-moi, pourquoi les "int *i, int *j, int *l, int *c" sont des pointeurs :D ?
      Et en plus, les deux premières variable i et j ne servent à rien puisque tu les utilises comme index dans le for.
      Donc i et j sont à supprimer.
      Et je suppose que l et c sont la taille des deux matrices... C'est ça ?
      Si c'est le cas, tu n'as pas besoin qu'ils soient des pointeurs.

      La déclaration de ta fonction devient alors :

      void transpose(double matrice[], double matrice_2[], int size_matrice1, int size_matrice2);
      


      J'ai changé un peu les noms pour qu'ils soient plus claires :p .

      Et donc la fonction devient :
      void transpose(double matrice[], double matrice2[], int size_matrice1, int size_matrice2)
      {
           int i = 0;
           int j = 0;
      
           for(i = 0; i < size_matrice1; i++)
           {
                for(j = 0; j < size_matrice2; j++)
                {
                       matrice[j][i] = matrice2[i][j];
                }
           }
      }
      
      • Partager sur Facebook
      • Partager sur Twitter
        Staff 17 mai 2010 à 21:18:22

        Bonsoir,

        Avec le début de code que tu as présenté il y a un petit problème, tu ne pourras manipuler que des matrices carrées, or, tu voudrais que ce soit pour n'importe quel matrice (carrée ou rectangulaire).
        La solution à ça, c'est de passer par l'allocation dynamique, comment ? c'est simple tu passe en argument à ta fonction la matrice M de dimension lignes x colonnes et tu alloues de la mémoire pour stocker la matrice TM (transposée de M) qui aura les dimensions colonnes x lignes, et pour finir tu renvoi en retour de la fonction un pointeur sur la matrice allouée (TM).

        Le prototype de la fonction de calcul de la transposée ressemblerait à ceci :

        double **calculTransposee(double **matrice,int nbLignes,int nbColonnes);
        

        • Partager sur Facebook
        • Partager sur Twitter
          17 mai 2010 à 23:43:49

          Merci Adimux,
          voila ce que j'ai fait :
          void transpose(double matrice[],double tmatrice[],int l, int c)
           {
          	 int i,j;
          	 for (i=0;i<l;i++)
             {
              for (j=0;j<c;j++)
              {
                          tmatrice[j][i]=matrice[i][j];
              }
             }
           }
          


          avec c le nombre de colone et l le nombre de ligne. Normalement ma matrice transposée devrait mettre les valeurs des lignes en colones et vice versa.
          Mais j'ai une erreur : sur ma ligne : tmatrice=matrice, j'ai l'erreur :"un indice requiert un type tableau ou pointeur".ET pour Uknow désolé je n'ai pas compris le probleme. Ce n'est pas gave si ma matrice n'est pas carré puisque c'est juste le passage des lignes aux colones, nan?
          Merci encore
          • Partager sur Facebook
          • Partager sur Twitter
            18 mai 2010 à 18:52:55

            C'est quoi exactement l'erreur du compilo.
            Recopie-là ici.
            • Partager sur Facebook
            • Partager sur Twitter
              18 mai 2010 à 20:18:48

              Ben je l'avais ecrite c'est:

              error C2109: un indice requiert un type tableau ou pointeur

              et elle fait référence à la ligne : tmatrice[j][i]=matrice[i][j];

              Et en fait il dit qu'il y a deux erreurs mais ceux sont les deux mêmes, pour la même ligne de code
              • Partager sur Facebook
              • Partager sur Twitter
                18 mai 2010 à 20:31:30

                bonsoir

                Tes paramètres de la fonction sont des tableaux de 1 dimension, et tu fais des calculs sur des tableaux à 2 dimensions.
                • Partager sur Facebook
                • Partager sur Twitter
                  18 mai 2010 à 21:01:43

                  AAAh ouais, j'avais oublié que tu utilisais des tableaux de deux dimensions

                  Donc la déclaration de la fonction c'est :

                  void transpose(double *matrice[], double *tmatrice[],int l, int c);
                  // Ou... (c'est la même chose)
                  void transpose(double **matrice, double **tmatrice, int l, int c);
                  


                  Et bien sûr, n'oublie de changer aussi la même chose sur la fonction.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 mai 2010 à 13:32:38

                    Ok merci ça a déjà enlevé cette erreur et ça m'a bien aidé.

                    Mais maintenant comment j'utilise ma fonction dans mon programme?
                    void main(void)
                    {
                    double beta[5][6]={
                    		{1.0/4, 0, 0, 0, 0, 0},
                    		{3.0/32, 9.0/32, 0, 0, 0, 0},
                    		{1932.0/2197, -7200.0/2197, 7926.0/2197, 0, 0, 0},
                    		{8341.0/4104, -32832.0/4104, 29440.0/4104, -845.0/4104, 0, 0},
                    		{-6080.0/20520, 41040.0/20520, -28352.0/20520, 9925.0/20520, -5643.0/20520, 0}
                    						};
                    // Transposition des coeffs
                    
                    	int i,j,l,c;
                    	double talpha[5],tbeta[5][6],tgamma[2][6];
                    	l=5;
                    	c=6;
                    	transpose(beta,tbeta,l,c); //là je dois ecrire comment mes matrcie ? expl: "&&beta"?
                                                       //ou je laisse comme ca?
                    
                    }
                    


                    Parce que là j'ai une erreur :
                    error C2664: 'transpose' : impossible de convertir le paramètre 1 de 'double [5][6]' en 'double **'

                    Est ce que c'est parceque j'ai déjà défini ma taille de matrice? J'ai lu certain truc sur l'allocation dynamique mais je n'ai pas tout compris...Est ce que le problème viendrait de là?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      19 mai 2010 à 13:44:48

                      void transpose(double *matrice[], double *tmatrice[],int l, int c);
                      // Ou... (c'est la même chose)
                      void transpose(double **matrice, double **tmatrice, int l, int c);
                      




                      FAUX!

                      Attention!
                      Un pointeur n'est pas un tableau!
                      Cela donne la même chose, mais c'est différent, attention à pas mélanger!
                      Dans ce cas là, sa change rien. Mais il faut bien savoir la différence ;)
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Sois ce que tu codes, codes ce que tu es.
                        19 mai 2010 à 14:41:13

                        @pingloveur : Tu as raison, j'avais oublié :D .

                        @PhoboS97310, malheureusement si tu veux faire cela, tu dois déclarer ton tableau d'une autre façon : l'allouer dynamiquement OU tu changes la déclaration de ta fonction en sachant que la taille de tes matrices est fixe, je veux dire que tu dois connaître exactement la taille de ta matrice et la fonction n'acceptera que les tableaux de cette même taille.
                        Voici un exemple de déclaration de la fonction :

                        void transpose(double matrice[5][6], double tmatrice[6][5], int l, int c);
                        // Comme tu vois, la taille du tableau matrice doit être de 5 lignes et 6 colonnes et celle de tmatrice 6 lignes et 5 colonnes
                        


                        Mais pour l'allocation dynamique, tu pourras donner un tableau 2D de n'importe quelle taille, MAIS tu devras remplir case par case ta matrice :

                        int longueur = 3, largeur = 2, i = 0;
                        double **matrice = (double **)malloc( sizeof(double **) * longueur);
                        
                        for(i = 0; i < longueur; i++)
                            matrice[i] = (double *) malloc( sizeof(double *) * largeur);
                        


                        Puis, remplir case par case :D.

                        matrice[0][0] = 4.12;
                        matrice[0][1] = 3;
                        // Etc...
                        
                        • Partager sur Facebook
                        • Partager sur Twitter
                          19 mai 2010 à 23:44:39

                          Ok ça marche mieux merci, mais malheureusement j'ai encore des soucis!
                          J'ai l'impression que ma matrice ne se remplit pas... Quand je regarde dans la fenêtre "variables locales" du compilateur ma matrice ne ressemble pas à celle que j'avais créer avant et je ne vois aucune de me valeurs...

                          Voici le code :
                          void main(void)
                          {
                          //coeffs
                          int l=5, c=6, i=0;
                          	double **beta =(double **)malloc( sizeof(double **) * l);
                          
                          	for(i = 0; i < l; i++)
                              beta[i] = (double *)malloc( sizeof(double *) * c);
                          	
                          	beta[0][0]=1.0/4;
                          	beta[0][1]=0;
                          	beta[0][2]=0;
                          	beta[0][3]=0;
                          	beta[0][4]=0;
                          	beta[0][5]=0;
                          	beta[1][0]=3.0/32;
                          	beta[1][1]=9.0/32;
                          	beta[1][2]=0;
                          	beta[1][3]=0;
                          	beta[1][4]=0;
                          	beta[1][5]=0;
                          	beta[2][0]=1932.0/2197;
                          	beta[2][1]=-7200.0/2197;
                          	beta[2][2]=7926.0/2197;
                          	beta[2][3]=0;
                          	beta[2][4]=0;
                          	beta[2][5]=0;
                          	beta[3][0]=8341.0/4104;
                          	beta[3][1]=-32832.0/4104;
                          	beta[3][2]=29440.0/4104;
                          	beta[3][3]=-845.0/4104;
                          	beta[3][4]=0;
                          	beta[3][5]=0;
                          	beta[4][0]=-6080.0/20520;
                          	beta[4][1]=41040.0/20520;
                          	beta[4][2]=-28352.0/20520;
                          	beta[4][3]=9925.0/20520;
                          	beta[4][4]=-5643.0/20520;
                          	beta[4][5]=0;
                          
                          	int j;
                          	 for (i=0;i<l;i++)
                             {
                              for (j=0;j<c;j++)
                              {
                                          printf("%f",beta[i][j]);
                          				if (j==5) printf("\n");
                              }
                             }
                          
                          //transpo
                          	l=6;
                          	c=5;
                          	double **tbeta =(double **)malloc( sizeof(double **) * l);
                          	for(i = 0; i < l; i++)
                              tbeta[i] = (double *)malloc( sizeof(double *) * c);
                          	l=5;
                          	c=6;
                          	transpose(beta,tbeta,l,c);
                          
                          }
                          


                          Mais qd je fais "printf" je vois bien ma matrice! Donc en fait j'ai l'impression que je ne vois que la première valeur de ma matrice dans "variable local" comment ca se fait?
                          • Partager sur Facebook
                          • Partager sur Twitter
                            20 mai 2010 à 0:34:26

                            Sinon, petite précision :
                            Si on a 2 tableaux de taille TAILLE, alors
                            for (i=0; i<TAILLE; i++)
                            	for (j=0; j<TAILLE; j++)
                            		tab2[i][j] = tab[j][i];
                            


                            est meilleur que :
                            for (i=0; i<TAILLE; i++)
                            	for (j=0; j<TAILLE; j++)
                            		tab2[j][i] = tab[i][j];
                            


                            La parcours linéaire est préférable pour l'écriture (je vous épargne les détails du pourquoi).
                            • Partager sur Facebook
                            • Partager sur Twitter
                              20 mai 2010 à 1:22:28

                              Citation : Arthurus

                              Sinon, petite précision :
                              Si on a 2 tableaux de taille TAILLE, alors

                              for (i=0; i<TAILLE; i++)
                              	for (j=0; j<TAILLE; j++)
                              		tab2[i][j] = tab[j][i];
                              



                              est meilleur que :

                              for (i=0; i<TAILLE; i++)
                              	for (j=0; j<TAILLE; j++)
                              		tab2[j][i] = tab[i][j];
                              



                              La parcours linéaire est préférable pour l'écriture (je vous épargne les détails du pourquoi).



                              Parce que les données d'un tableau bidimensionnel sont contiguës en mémoire, la ligne 0 en entier d'abord puis la ligne 1 en entier ensuite etc ? Probablement mais de toute façon, ce parcours va être ralenti par l'accès à l'élément symétrique.

                              Disons que moi j'aurais peut-être écrit ceci :


                              #include <stdio.h>
                              
                              void afficher(int *z, int nl, int nc)
                              {
                                int i, j;
                              
                                for (i = 0; i < nl; i++)
                                  {
                                    for (j = 0; j < nc; j++)
                                      printf("%d ", *z++);
                                    printf("\n");
                                  }
                              }
                              
                              int main(void)
                              {
                              #define NL 2
                              #define NC 3
                                int t[NL][NC] = { 4, 7, 8, 0, 6, 5 };
                                int tt[NC][NL], *p = &tt[0][0];
                              
                                int lig, col;
                              
                                for (col = 0; col < NC; col++)
                                  for (lig = 0; lig < NL; lig++)
                                    *p++ = t[lig][col];
                              
                                afficher(&t[0][0], NL, NC);
                                printf("\n");
                                afficher(&tt[0][0], NC, NL);
                                return 0;
                              }
                              


                              4 7 8 
                              0 6 5 
                              
                              4 0 
                              7 6 
                              8 5
                              • Partager sur Facebook
                              • Partager sur Twitter
                                20 mai 2010 à 1:48:17

                                Citation : candide

                                Parce que les données d'un tableau bidimensionnel sont contiguës en mémoire, la ligne 0 en entier d'abord puis la ligne 1 en entier ensuite etc ? Probablement mais de toute façon, ce parcours va être ralenti par l'accès à l'élément symétrique.



                                Oui bien sûr que ça va être ralenti par l'élément symétrique, sauf que ce ralenti sera dû à une lecture.
                                Si on inverse, il y aura parcours linéaire sur la partie droite, mais dans ce cas ralenti à gauche à cause d'une écriture, et là c'est pire, car dans les caches, on préfère écrire un flot de données avant de les envoyer pour de vrai en RAM, plutôt que d'envoyer à la RAM directement les mots un par un.
                                Pour résumer, et en utilisant le jargon adapté, un miss de cache sur une lecture est moins grave qu'un miss de cache sur une écriture (un miss de cache veut dire que le processeur ne trouve pas la donnée qu'il cherche dans ce cache). Donc on préférera faire un parcours qui linéarise une écriture même si cela implique de l'autre coté un parcours non linéaire en lecture (le cas de figure que j'ai proposé).

                                Sinon pour le programme que tu as écrit, d'un point de vue théorique, il est équivalent au bon parcours linéaire sur les écritures que j'avais donné... Après peut être que le compilateur sera plus à l'aise avec mon écriture ou la tienne, ça j'en sais trop rien (après tout, c'est toi le pro en C ;) ).
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  21 mai 2010 à 19:20:28

                                  Si avec printf() tu vois bien ta matrice donc ton programme marche et par conséquent, t'en as rien à foutre (excusez du terme) des "variables locales" :D .
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    21 mai 2010 à 19:51:06

                                    Citation : Arthurus

                                    (après tout, c'est toi le pro en C ;) ).



                                    Heu non, je ne suis pas un pro du C, peut-être un jour, ça dépendra de mes besoins. Pour l'instant, il faut bien reconnaitre que je fais du C de salon et ce qui m'intéresse avant tout c'est l'enseignement du C (bon et encore, de moins en moins).
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Fonction transposée matrice (C)

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown