Intégrer un tableau dans un autre en C

Fermé
alphenix Messages postés 3 Date d'inscription dimanche 15 avril 2007 Statut Membre Dernière intervention 5 janvier 2022 - 15 avril 2007 à 14:56
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 - 17 avril 2007 à 23:54
Ca ne fait pas longtemps que je me suis lancé dans la programmation. J'en suis toujours à faire des programmes en fenêtre DOS.
Je voulais savoir comment on faisait pour intégrer un tableau dans un autre tableau. L'objectif serait de pouvoir mettre, par exemple, un (ou plusiuers) tableau(x) de dimension 2X2 dans un tableau de dimension 9X9 ou plus. Ce qui me permettrait de modifier la position de mon petit tableau dans le tableau plus grand. (Un peu comme un puzzle où chaque pièce ferait office de tableau).
A voir également:

7 réponses

ekra Messages postés 1870 Date d'inscription vendredi 15 avril 2005 Statut Membre Dernière intervention 24 juillet 2014 342
15 avril 2007 à 20:32
Bonjour,

Par exemple pour mettre un tab 2*2 dans un 9*9 en statique :

int main(void) {
int** tab9x9[9][9];
int tab2x2[2][2];

/* Stockage dans le tableau 9*9 en 3,4 */
tab9x9[3][4]=tab2x2;

/* Pour y accéder à une valeur du tableau 2*2 (en 0,1): */
printf("%d\n",tab9x9[3][4][0][1]);
return0;
}


0
alphenix Messages postés 3 Date d'inscription dimanche 15 avril 2007 Statut Membre Dernière intervention 5 janvier 2022
16 avril 2007 à 20:27
Merci pour ta réponse mais il y a un petit détail que je ne comprends pas:
Pourquoi deux astérisque dans cette ligne: int** tab9x9[9][9]; ?

Avec ce que tu m'as appris, j'ai éssayer de faire un code intégrant un tableau 2*2 dans un tableau 4*4. Bon, j'ai du faire pas mal d'erreur car le programme ne fonctionne pas et je l'ai fait avec touts les connaissances que j'ai en programmation (c'est-à-dire pas grand chose).

#include <iostream>

using namespace std;

int main()
{
int** tab4X4[4][4];
int tab2X2[2][2];
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
tab4X4[i][j]='NULL';
}
}
for (int i=0;i<2;i++)
{
for (int j=0;j<2;j++)
{
cout<<"Entrer la valeur de la case "<<i<<j<<" du tableau 2X2"<<endl;
cin>>tab2X2[i][j];
}
}
tab4X4[1][1]=tab2X2;
system("PAUSE");
}

Tu saurais me dire où je me suis planter?

MERCI d'avance.
0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
16 avril 2007 à 21:13
Le problème c'est que ekra à cru que tu avait un tableau 9x9 dont chaque case contenait un matrice 2x2, je ne crois pas que ce soit ce que tu veux.

Si j'ai bien compris tu veux par exemple mettre le tableau
1 2
3 4

Dans le tableau
0 0 0
0 0 0
0 0 0

ce qui donnerait par exemple, en (0,1) :
0 1 2
0 3 4
0 0 0

c'est ça ?

Si oui le plus simple c'est de repartir sur une classe de matrice
typedef struct matrix_t{
  unsigned nb_ligne;
  unsigned nb_colonne;
  int **valeurs;
} matrix_t;

Ensuite tu fais une fonction pour l'allouer, une pour la desallouer, une pour modifier la case (i,j), une pour lire la case (i,j).
#include <stdlib.h>
#include <stdio.h>
#include <cassert.h>

matrix_t new_matrix(unsigned nbl,unsigned nbc){
  matrix_t m;
  unsigned i;
  for(i=0;i<nbl;++i) m.valeurs[i] = (int *)calloc(nbc,sizeof(int));
  m.nb_ligne = nbl;
  m.nb_colonne = nbc;
  return m;
}

void delete_matrix(matrix_t m){
  for(i=0;i<m.nb_ligne;++i) free(m.valeurs);
}

// (si les lignes avec les cassert ne compilent pas, 
// change les par un test)
void set(matrix_t m,unsigned i,unsigned j,int val){
  cassert(i<m.nb_ligne);
  cassert(j<m.nb_colonne);
  m[i][j] = val;
}

int get(matrix_t m,unsigned i,unsigned j){
  cassert(i<m.nb_ligne);
  cassert(j<m.nb_colonne);
  return m[i][j];
}

void print(matrix_t m){
  unsigned int i,j;
  for(i=0;i<m.nb_ligne;++i){
    for(j=0;j<m.nb_colonne;++j){
      printf("%d ",get(m,i,j));
    }
    printf("\n");
  }
}

Si je ne me suis pas trop craquée tu dois avoir une classe de matrice de base :
int main(){
  matrix_t m = new_matrix(3,3);
  print(m);
  delete_matrix(m);
  return 0;
}

Il ne reste plus qu'à rajouter une fonction pour recopier une sous matrice dans une matrice, et à compléter le main (laisse-le en fin de fichier) :
int copy(
  matrix_t subm,
  matrix_t m,
  unsigned decalage_ligne,
  unsigned decalage_colonne
){
  unsigned int i,j;
  assert(subm.nb_ligne+decalage_ligne < m.nb_ligne);
  assert(subm.nb_colonne+decalage_colonne < m.nb_colonne);
  for(i=0;i<subm.nb_ligne;++i){
    for(j=0;j<subm.nb_ligne;++j){
      set(m,i+decalage_ligne,j+decalage_colonne,get(subm,i,j));
    }
  }
}

int main(){
  unsigned int i,j,x=0;
  matrix_t m1 = new_matrix(3,3);
  matrix_t m2 = new_matrix(5,5);
  for(i=0;i<m1.nb_ligne;++i){
    for(j=0;j<m1.nb_colonne;++j){
      set(m1,i,j,++x);
    }
  }
  printf("m1=\n");
  print(m1);
  printf("m2=\n");
  print(m2);
  printf("m1->m2=\n");
  copy(m1,m2,1,2);
  print(m2);  
  delete_matrix(m1);
  delete_matrix(m2);
  return 0;
}

N'étant pas sous linux actuellement je n'ai pas pu vérifier si ça compilait mais on ne doit pas être loin du bonheur ;-)

Bonne chance
0
ekra Messages postés 1870 Date d'inscription vendredi 15 avril 2005 Statut Membre Dernière intervention 24 juillet 2014 342
16 avril 2007 à 23:13
En fait je ne sais pas si c'est ce que tu demandais (cf mamiemando) mais bon je te donne ça si ça t'interresse vu que tu débutes.

J'ai essayé de corriger ton code. Je te conseille en C, (selon la norme norme c99), d'oublier les déclarations en non début de code (comme dans les boucles for), pas de iostream, cout et sin => printf et scanf.
Je crois que tu mélanges la syntaxe C/C++. Si tu n'aborde pas l'objet (je pense que c'est inutile pour un débutant), concentre-toi uniquement sur le C.

#include <stdio.h> /* Ne pas oublier le .h */

int main(void)
{
  int** tab4X4[4][4];
  int tab2X2[2][2];
  int i,j;

  for (i=0;i<4;i++){
      for (j=0;j<4;j++){
	  tab4X4[i][j]=NULL; /* /!\ Ce n'est pas une chaine mais une constante. Pas de 'NULL' mais NULL */
      }
  }
  for (i=0;i<2;i++) {
    for (j=0;j<2;j++) {
      printf("Entrer la valeur de la case [%d][%d] du tableau 2X2",i,j);
      scanf("%d",&tab2X2[i][j]);
    }
  }
  tab4X4[1][1] = (int **)tab2X2; /* L'abscence de (int**) génère un Warning (pas grave) */
  return 0;
} 


au fait les "int *" dans la déclaration signale que c'est signifie que c'est une adresse de variable pointant sur un int.
S'il y a "int **" signifie que c'est une adresse pointant vers un "int *"

Je te conseille de te consacrer sur différents cours à un même chapitre : Les pointeurs. Je pense que c'est LE chapitre le plus difficile et LE plus important qu'il faut assimiler complétement. Je pense que c'est inutile d'avancer plus loin s'il on ne le maitrise pas. Le problème est de savoir si on le maitrise !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
17 avril 2007 à 00:59
Booaah un pointeur c'est simple. Un pointeur plop * c'est l'adresse d'un objet plop. On passe de l'adresse au pointeur avec l'opérateur unaire *, et de l'objet à l'adresse avec le &.

Une fois que tu as compris
a- que les adresses, quelles que soit leur type, ne sont jamais que des adresses (donc grosso modo un entier) et donc très rapide à recopier,
b- qu'elle permettent de "relier des objets ensemble",
c- et que quand tu appelles une fonction en C, les paramètres sont en fait une recopie (d'où l'intérêt des pointeurs car ce qui est à cette adresse n'est pas recopié)
... tu as presque tout compris au C...
0
alphenix Messages postés 3 Date d'inscription dimanche 15 avril 2007 Statut Membre Dernière intervention 5 janvier 2022
17 avril 2007 à 20:43
Merci pour vos codes.
Je vais un peu essayer de jongler avec ça. J'en aurais surement pour un petit temps.

Pour ce qui est des pointeurs, je sais ce que c'est et en quoi ça consiste. Le problème, c'est que je ne les ai pas encore fort utilisé donc je ne suis pas fort à l'aise avec.
Tant qu'il y a un int *a, je comprend que c'est un pointeur vers a. Par contre, s'il y a un pointeur int **a, je suis perdu. ekra m'a bien expliqué que c'était un pointeur vers un autre pointeur. Jusque là, ça va. Mais je ne comprend pas bien comment il fonctionne dans ce code et donc à quoi il sert.
0
mamiemando Messages postés 33077 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 18 avril 2024 7 748
17 avril 2007 à 23:54
Une int **a c'est l'adresse d'un int *. Il se trouve que ce int * est lui même une adresse mais en soi, on s'en fout. Par contre ce qu'on ne t'explique pas en C, c'est le lien entre int[] et int *.

En effet, on se plait à dire qu'un int * désigne un tableau de int. En fait c'est une hérésie. C'est une adresse et c'est tout. Si tu considère le tableau int tab[10], quand tu écris tab[i], tu manipules juste l'entier qui est décalé de i int par rapport au pointeur "tab". En particulier tab[0] <=> *tab. Si l'on omet que les crochets permettent d'allouer statiquement une plage d'objets (par exemple int tab[10] alloue de manière statique 10 entiers), la notation avec des crochets n'est là que dans un soucis de lisibilité.
0