2014-05-25 4 views
2

Je suis en train de coder pour la multiplication de matrices de matrices carrées et il va continuer à donner Segmentation fault après quelques entires sur plusieurs essais. J'ai cherché une question différente sur le site et essayé quelques façons avec deux codes suivants.matrice C allouent Dynamiquement pour la multiplication

Aussi, Pourquoi avons-nous besoin des conseils pour « pointeur vers un pointeur » comme donnée par int ** mat1, ** mat2 etc.? Je ne sais pas pourquoi cela doit être fait mais je l'ai vu dans une réponse même.

code 1

void mxmult() 
{ 
    int n,m,a,b,c,d, sum=0; 
    int x,y,z; 
    printf("Enter first order [n*n]\n"); 
    scanf("%d", &n); 
    printf("Enter second order [m*m]\n"); 
    scanf("%d", &m); 
    if (n!=m) 
    { 
     printf("Invalid orders"); 

    } 
    else 
    { 
     //mem allocate for matrix 1 
     int **mat1 = (int**)malloc(n*sizeof(int)); 
     for(x=0;x<n;x++) 
      { 
       mat1[x]=(int*)malloc(n*sizeof(int)); 
      } 
     // input matrix 1 
     printf("Enter the first matrix entries\n"); 
     for (a = 0; a <n; a++) 
     { 
      for (b = 0; b < n; b++) 
      { 
       scanf("%d", &mat1[a][b]); 
      } 
     } 
     // memory allocate matrix 2 
     int **mat2 = (int**)malloc(m*sizeof(int)); 
     for(y=0;y<n;y++) 
      { 
       mat2[y]=(int*)malloc(m*sizeof(int)); 
      } 

     //inpur matrix 2 
     printf("Enter the second matrix entries\n"); 
     for (c = 0; c <n; c++) 
     { 
      for (d= 0; d < n; d++) 
      { 
       scanf("%d", &mat2[c][d]); 
      } 
     } 

     //Memory allocate matrix Mult 
     int **mult=(int**)malloc(m*sizeof(int)); 
     for(z=0;z<m;z++) 
      mult[z]=(int*)malloc(m*sizeof(int)); 
     for (a = 0; a < n; a++) 
     { 
      for (d = 0; d < m; d++) 
      { 
       for (c = 0; c < n; c++) 
       { 
        sum=sum + (mat1[a][c] *mat2[c][d]); 
       } 
       mult[a][d] = sum; 
       sum= 0; 
      } 
     } 
     printf("Product\n"); 

     for (a = 0 ; a < n ; a++) 
     { 
      for (d = 0 ; d < m ; d++) 
       printf("%d\t", mult[a][d]); 
      printf("\n"); 
     } 

    } 
} 

Code 2:

void mxmult() 
{ 
    int n,m,a,b,c,d, sum=0; 
    int x,y,z; 
    printf("Enter first order [n*n]\n"); 
    scanf("%d", &n); 
    printf("Enter second order [m*m]\n"); 
    scanf("%d", &m); 
    if (n!=m) 
    { 
     printf("Invalid orders"); 

    } 
    else 
    { 
     //mem allocate for matrix 1 
     int **mat1 = (int**)malloc(n*n*sizeof(int)); 

     // input matrix 1 
     printf("Enter the first matrix entries\n"); 
     for (a = 0; a <n; a++) 
     { 
      for (b = 0; b < n; b++) 
      { 
       scanf("%d", &mat1[a][b]); 
      } 
     } 
     // memory allocate matrix 2 
     int **mat2 = (int**)malloc(m*m*sizeof(int)); 

      //input matrix 2 
     printf("Enter the second matrix entries\n"); 
     for (c = 0; c <n; c++) 
     { 
      for (d= 0; d < n; d++) 
      { 
       scanf("%d", &mat2[c][d]); 
      } 
     } 

     //Memory allocate matrix Mult 
     int **mult=(int**)malloc(m*m*sizeof(int)); 

      // Mx multiplicatn 
     for (a = 0; a < n; a++) 
     { 
      for (d = 0; d < m; d++) 
      { 
       for (c = 0; c < n; c++) 
       { 
        sum=sum + (mat1[a][c] *mat2[c][d]); 
       } 
       mult[a][d] = sum; 
       sum= 0; 
      } 
     } 
     printf("Product\n"); 

     for (a = 0 ; a < n ; a++) 
     { 
      for (d = 0 ; d < m ; d++) 
       printf("%d\t", mult[a][d]); 
      printf("\n"); 
     } 

    } 
} 

J'ai essayé d'exécuter du code 2, puis, code2. Les deux finissent par donner des failles de ségrégation après quelques entires.

+0

pas sûr, mais cela semble incorrect: 'scanf ("% d", et mat1 [a] [b]) '. Puisque mat1 est déjà un pointeur, vous ne devriez pas utiliser l'esperluette. – MightyPork

+1

'int ** mat1 = (int **) malloc (n * taille de (int));' -> 'int ** mat1 = (int **) malloc (n * sizeof (int *));' – BLUEPIXY

+0

'int ** mat1 = (int **) malloc (n * n * taille de (int));' -> 'int (* mat1) [n] = malloc (n * n * taille de (int));' – BLUEPIXY

Répondre

9

Le type int ** est ce que l'on appelle un tableau ragged. Vous créez un tableau irrégulier en allouant d'abord un tableau "spine", qui contient des pointeurs sur chacune des "côtes". Lorsque vous référencez matrix[x][y], vous déréférencer le pointeur à l'index x dans la «colonne vertébrale», puis obtenir l'élément à l'index «y» dans la «nervure». Voici un schéma illustrant bien cette structure:

Ragged array in C

Vous pouvez lire comp.lang.c FAQ list · Question 6.16: How can I dynamically allocate a multidimensional array? (aussi la source de l'image ci-dessus) pour plus d'informations.

Une autre option consiste à allouer en fait un tableau 2D pour votre matrice (ma méthode préférée). Cela nécessite un compilateur prenant en charge certaines constructions C99, mais tous les principaux compilateurs, à l'exception du compilateur Microsoft C (par exemple, gcc et clang) semblent le supporter par défaut. Voici un exemple:

int (*matrix)[colCount] = (int(*)[colCount]) malloc(sizeof(int)*rowCount*colCount); 

La syntaxe bizarre ci-dessus est la façon dont vous declare a pointer to an array in C. Les parenthèses autour de *matrix sont nécessaires pour le désambiguïser de declaring from an array of pointers. You don't need to cast the result of malloc in C, donc de manière équivalente:

int (*matrix)[colCount] = malloc(sizeof(int)*rowCount*colCount); 

Ceci affecte un seul bloc de mémoire pour la matrice, et puisque le compilateur connaît la longueur de chaque rangée (par exemple colCount), on peut insérer le calcul pour calculer l'adresse correcte pour toute Référence 2D Par exemple, matrix[x][y] est équivalent à ((int*)matrix)[x*colCount+y]. Je préfère allouer un tableau 2D parce que vous pouvez faire toute l'allocation dans une ligne, alors qu'avec le tableau ragged vous devez placer le pointeur sur chaque ligne individuellement, ce qui nécessite généralement deux autres lignes pour une boucle.


Quant à votre segfault, cette ligne semble suspect:

int **mat1 = (int**)malloc(n*sizeof(int)); 

Depuis mat1 est de type int**, chaque entrée mat1 devrait être un int*. Cependant, votre malloc utilise sizeof(int) pour allouer la mémoire aux entrées!Essayez ceci:

int **mat1 = (int**)malloc(n*sizeof(int*)); 

En supposant que vous êtes sur un système 64 bits, sizeof(int) est probablement 4 (octets), alors que sizeof(int*) devrait être 8 (octets). Cela signifie que vous allouez actuellement la moitié de la mémoire dont vous avez besoin, ce qui signifie qu'une mauvaise chose se produira lorsque vous accéderez aux entrées dans la seconde moitié de ce tableau. En utilisant la bonne taille (sizeof(int*)) devrait résoudre ce problème.

(Il pourrait y avoir d'autres problèmes, mais c'est celui qui se distingue au premier coup d'œil.)

Questions connexes