Problème courant du tableau 2D

Problème courant du tableau 2D - C - Programmation

Marsh Posté le 16-11-2008 à 15:39:05    

Bonjour,
 
Je galère un peu sur les tableaux 2D... J'ai déjà cherché et trouvé pleins de choses sur google mais je comprend pas tout...
 
Je dois déclarer un tableau 2D de int dont les dimensions nbl et nbc sont connues :
 
Allocatation statique

Code :
  1. int tab2D[nbl][nbc];
  2. int ic,il;    // index colonnes , lignes
  3. // Affichage
  4.     for(il=0 ; il<nbl ; pl++)     
  5.     {
  6.         for(ic=0 ; ic<nbc ; ic++)   
  7.                 printf("%d ",tab2D[il][ic]);
  8.         printf("\n" );
  9.     }


 
Je voudrais remplacer tab2D[il][ic] par *(tab2D + ...) impossible de trouver les ... qui vont bien.
 
Allocation dynamique
Maintenant nbl et nbc ne sont connus qu'à l'exécution du programme.
Sachant que je veux pourvoir utiliser un adressage type tab2D[il][ic] et *(tab2D + ...), comment déclarer l'alloc ?
 

Code :
  1. int** tab2D;    // Je dois bien déclarer comme ca pour pouvoir ensuite faire du tab2D[il][ic] = x;
  2.     if((tab2D = (int**) malloc(nbc*nbl*sizeof(int)))==NULL)
  3.     {
  4.         printf("Allocation fail\n" );
  5.         exit(EXIT_FAILURE);
  6.     }


=> Marche pas...
 

Code :
  1. int** tab2D;    // Je dois bien déclarer comme ca pour pouvoir ensuite faire du tab2D[il][ic] = x;
  2.     if((tab2D = (int**)malloc(nbl*sizeof(int*)))==NULL)
  3.     {
  4.         printf("Allocation fail\n" );
  5.         exit(EXIT_FAILURE);
  6.     }
  7.     for(pl=0;pl<nbl;pl++)
  8.     {
  9.         if((tab2D[pl] = (int*)malloc(nbc*sizeof(int)))==NULL)
  10.         {
  11.             printf("Allocation fail\n" );
  12.             exit(EXIT_FAILURE);
  13.         }
  14.     }


=> Ceci est un tableau de pointeurs, et non un tableau 2D ?
 
Merci d'avance pour votre aide

Reply

Marsh Posté le 16-11-2008 à 15:39:05   

Reply

Marsh Posté le 16-11-2008 à 20:12:08    

Si je me souviens bien, on peut remplacer

tab2D[il][ic]

par

*(tab2D + il * nbc + ic)

EDIT : Je me suis trompé, il manque une étoile, c'est :

*(*tab2D + il * nbc + ic)


Pour l'allocation dynamique, il faut imaginer un arbre plutôt qu'un damier. Cela devrait aider à comprendre, par exemple, que le premier tableau (le tableau des pointeurs de pointeurs, en **) n'a pas besoin d'avoir nbc * nbl éléments, que nbl éléments suffit.
 
Par ailleurs, il faudrait soigner la présentation, par exemple en ayant des indentations de taille fixe (en préférant utiliser toujours trois ou quatre espaces plutôt que la touche de tabulation qui donne des résultats aléatoires) en ne mettant pas d'espace avant les points virgules et les virgules, mais en mettant toujours un espace après ces deux signes, et en mettant un espace avant et après les signes arithmétiques.
 


Message édité par olivthill le 18-11-2008 à 07:38:05
Reply

Marsh Posté le 16-11-2008 à 20:20:04    

Citation :

*(tab2D + il * nbc + ic)


Marche pas (à ma grande surprise justement !) ... Ce qui marche, c'est ça (avec un tab2D déclaré en statique ou en dynamique avec la 2ème méthode) :
 

Citation :

*(*tab2D + il * nbc + ic)

Reply

Marsh Posté le 17-11-2008 à 09:42:17    

On peut aussi faire les choses proprement et alloué des tableaux 2D qui ne nécessitent pas cette gymnastique :

 
Code :
  1. float** alloc_array( int h, int w )
  2. {
  3.   /* Allocation des h pointeurs sur les debuts de lignes */
  4.   float** m = (float**)malloc(h*sizeof(float*));
  5.   /* La premiere ligne pointe vers le debut de l'espace memoire contigu du tableau */
  6.   m[0] = (float*)malloc(h*w*sizeof(float));
  7.   /* Pre-calcul des debut de lignes 1 à h-1 */
  8.   for(int i=1;i<h;i++) m[i] = m[i-1]+w;
  9.   return m;
  10. }
  11. void release_array(float** m)
  12. {
  13.   free( m[0] );
  14.   free( m);
  15. }
 

L'accès en en l,c se fait via : tab[l][c].
Les gens intelligents trouveront aussi par eux mêmes comment en modifiant ce code, on peut gérer des tableaux à indices négatifs ;)


Message édité par Joel F le 17-11-2008 à 14:33:27
Reply

Marsh Posté le 17-11-2008 à 10:01:16    

Salut,
 

sherminator+ a écrit :

Ceci est un tableau de pointeurs, et non un tableau 2D ?


 
Il me semble qu'en C les tableaux dit 2D sont des tableaux de pointeurs.
 
Pour ton premier exemple d'allocation dynamique, tu crée un tableau à une dimension. En toute logique tu devrais declarer un simple pointeur et non un pointeur sur pointeur. Apres c'est "ton esprit" qui va le découper pour en faire un tableau 2D.
 
edit pour au dessus:
je croyais que les gens intelligents étaient ceux qui savaient écrire du code propre et commenté!

Message cité 2 fois
Message édité par h0taru le 17-11-2008 à 10:11:32
Reply

Marsh Posté le 17-11-2008 à 14:32:34    

h0taru a écrit :


je croyais que les gens intelligents étaient ceux qui savaient écrire du code propre et commenté!


 
Oui, correction faite. Les gens intelligents m'auraient indiqué la fautes de frappe dans sizeof au lieu de faire genre ;)
 

Reply

Marsh Posté le 17-11-2008 à 15:00:42    

h0taru a écrit :

Il me semble qu'en C les tableaux dit 2D sont des tableaux de pointeurs.


Non justement, les tableaux 2D (du genre tab[i][j]) sont un seul bloc de i*j éléments.

Reply

Marsh Posté le 17-11-2008 à 23:50:06    

Au temps pour moi. je dois manquer d'intelligence  :)

Reply

Marsh Posté le 18-11-2008 à 20:45:16    

matafan a écrit :


Non justement, les tableaux 2D (du genre tab[i][j]) sont un seul bloc de i*j éléments.


oui mais ce sont également des tableaux de pointeurs même en allocation statique.
tab[i] est bien un pointeur vers le début de la colonne.

Message cité 1 fois
Message édité par sligor le 18-11-2008 à 20:45:36
Reply

Marsh Posté le 19-11-2008 à 10:07:34    

sligor a écrit :


oui mais ce sont également des tableaux de pointeurs même en allocation statique.
tab[i] est bien un pointeur vers le début de la colonne.


Je trouve que présenter les choses comme tu le fais est un peu trompeur. Oui, tab[i] a bien le type int *, mais la valeur de tab[i] n'est stockée nul part en mémoire. Seul le compilo connait la connait. C'est pour ça qu'on ne peut pas dire ce qu'a dit h0taru, c'est à dire que "les tableaux dit 2D sont des tableaux de pointeurs". Ce n'est pas vrai.  
 
Ce que je veux dire, c'est que quand on fait "int tab[2][2]", tout ce qu'on a en mémoire c'est 4 int consécutifs. Il n'y a pas de pointeur là dedans.

Reply

Marsh Posté le 19-11-2008 à 10:07:34   

Reply

Marsh Posté le 20-11-2008 à 07:51:29    

Ca dépend comment on voit les choses, matafan.
 
Une succession de 4 int est fondamentalement un tableau à 1 dimension. Le C permet d'écrire tab[2][2] mais considérer que c'est de la 2D est selon moi un abus de langage.
 
Dans le doute, j'vais regarder le K&R dans la journée :)

Reply

Sujets relatifs:

Leave a Replay

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