1 les pointeurs et les tableaux statiques et tableaux dynamiques

58
1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

Upload: micheline-maillard

Post on 04-Apr-2015

122 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

1

Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

Page 2: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

2

Tableaux Statiques et Tableaux Dynamiques

Les tableaux statiques nécessitent de maximiser lors de l'écriture du programme la dimension des tableaux.

Il serait plus utile de ne réserver, pour chaque exécution, que la taille nécessaire à l'application en cours.

#define composante float

composante tab[dim];

composante*tab;tab=(composante *)malloc(taille*sizeof(composante));free(tab);tab=NULL;

Déclaration d’un tableau statique

Déclaration d’un tableau dynamique(si on a besoin du tableau)

Si le tableau redevient inutile.

Page 3: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

3

Tableaux Statiques et Tableaux Dynamiques

Si on a l'une ou l'autre des déclarations

on peut écrire:

float t[100];float *t = (float*)malloc(10*sizeof(float));

t[0] ou *tt[i] ou *(t+i)

On doit connaître la dimension d'un tableau dynamique (taille) avant sa première utilisation.

Page 4: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

4

Tableaux Statiques et Tableaux Dynamiques

Remarque 1. La similitude entre un tableau et un pointeur est grande, notamment dans la partie exécutable des fonctions. Mais il subsiste des différences, surtout dans les déclarations. Il ne faut pas oublier que les déclarations:

introduisent p comme une variable pointeur et t comme une constante pointeur. Ainsi, les expressions p = t etp++ sont légitimes, mais t = p et t++ sont illégales, car elles tentent de modifier une non variable (un nomde tableau n'est pas une lvalue).

int *p, t[100];

Page 5: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

5

Tableaux Statiques et Tableaux Dynamiques

Remarque 2. Dans ce mème esprit, rappelons la difference qu'il peut y avoir entre les deux déclarations suivantes :

s est l'adresse d'un tableau de caractères

char s[ ] = "Bonsoir";etchar *t = "Bonsoir";

Page 6: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

6

Tableaux Statiques et Tableaux Dynamiques

Remarque 2. tandis que t est l'adresse d'un tableau de caractère(s)

Page 7: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

7

Tableaux Statiques et Tableaux Dynamiques

On pourra référencer ces caractères par:

Cependant, dans le premier cas le compilateur a alloué un vrai tableau de 8 caractères, et y a copié la chaîne donnée.

Dans le second cas, la chaîne a été rangée avec les autres constantes littérales et le compilateur n'a alloué qu'une variable de type pointeur dans laquelle il a rangé l'adresse de cette constante. Par suite, s n'est pas une variable mais *s, s[i] et *(s + i) en sont, tandis que t est une variable mais *t, t[i] et *(t + i) n'en sont pas.

s[i], *(s + i) t[i], *(t + i)

Page 8: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

8

Tableaux Statiques et Tableaux Dynamiques

Exemple classique :

La fonction strcpy(dest, srce) copie la chaîne de caractères srce dans l'espace pointé par dest.

char *strcpy(char *dest, char *srce) {

char *d = dest, *s = srce;while ((*d++ = *s++) != '\0');return dest;

}

Page 9: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

9

Tableaux Statiques et Tableaux Dynamiques

Example: utilisation de la fonction strcpy

#include <stdio.h>char *strcpy(char *dest, char *srce);void main(){ char s[ ] = "AAAAAAA"; char *t = "Bonjour"; puts (strcpy(s,t));}char *strcpy(char *dest, char *srce){

char *d = dest, *s = srce;while ((*d++ = *s++) != '\0');return dest;

}

Bonjour

La longueur de t <= de celle de s

Page 10: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

10

Tableaux Statiques et Tableaux Dynamiques

Example: utilisation de la fonction strcpy

#include <stdio.h>char *strcpy(char *dest, char *srce);void main(){ char s[ ] = "AAAA"; char *t = "Bonjour"; puts (strcpy(s,t));}char *strcpy(char *dest, char *srce){

char *d = dest, *s = srce;while ((*d++ = *s++) != '\0');return dest;

}

Erreur!

La longueur de t > de celle de s

#include <stdio.h> #include <string.h> #include <stdlib.h>char *strcpy(char *dest, char *srce);void main(){ char *t = "Bonjour"; int len=strlen(t); char *s=(char *)malloc((len+1)*sizeof(char)); puts (strcpy(s,t));}

Bonjour

Page 11: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

11

Tableaux Statiques et Tableaux Dynamiques

L'équivalence entre les tableaux et les pointeurs permet de réaliser des tableaux dynamiques, c'est-à-dire des tableaux dont la taille n'est pas connue au moment de la compilation mais uniquement lors de l'exécution, lorsque le tableau commence à exister.

Pour cela il suffit de: remplacer la déclaration du tableau par celle d'un

pointeur; allouer l'espace à l'exécution, avant toute utilisation du

tableau, par un appel de malloc ou calloc; dans le cas d'un tableau local, libérer l'espace à la fin de

l'utilisation.

Page 12: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

12

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau statique Faire un programme à afficher le triangle de Pascal

(Rappelons que les coeficients de la neme ligne du triangle de Pascal sont définis récursivement à partir de ceux de la n-1eme ligne).

#include <stdio.h> 1/3#include <stdlib.h>#define N_MAX 50

void Blaise(int n);

Le prototype de la fonction

Page 13: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

13

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau statique

void main() 2/3{ int n;

do { printf("Entrer n=");

scanf("%d",&n); }while(n<=0 || n > N_MAX);Blaise(n);

}

La fonction main, appelante la fonction Blaise

Entrer n=311 11 2 11 3 3 1

Page 14: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

14

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau statique

void Blaise(int n) 3/3 { int j, p, i; int tab[N_MAX + 1]; /* N_MAX est une constante connue à la compilation */ for (j = 0; j <= n; j++) { tab[0] = tab[j] = 1; for (p = j - 1; p > 0; p--)

tab[p] += tab[p - 1];/* exploitation de tab ; par exemple, afichage : */ for (i = 0; i <= j; i++)

printf("%5d", tab[i]); printf("\n"); }}

La définition de la fonction Blaise

Page 15: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

15

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau dynamique Faire le même programme

#include <stdio.h> 1/3#include <stdlib.h>

void Blaise(int n);

Le prototype de la fonction

Page 16: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

16

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau dynamique

void main() 2/3{ int n;

printf("Entrer n=");scanf("%d",&n);Blaise(n);

}

La fonction main, appelante la fonction Blaise

Entrer n=311 11 2 11 3 3 1

Page 17: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

17

Tableaux Statiques et Tableaux Dynamiques

Programmation avec un tableau dynamique

void Blaise(int n) { 3/3int j, p, i;int *tab; /* ici, pas besoin de constante connue à la compilation */tab =(int *) malloc((n + 1) * sizeof(int));if (tab == NULL) exit(1);for (j = 0; j <= n; j++)

{ *(tab+0) = *(tab+j) = 1; for (p = j - 1; p > 0; p--)

*(tab+p) += *( tab+p-1);/* exploitation de tab ; par exemple, afichage : */

for (i = 0; i <= j; i++)printf("%5d", *(tab+i));

printf("\n");}

free(tab);tab=NULL; /* à ne pas oublier ( tab est une variable locale) */}

La définition de la fonction Blaise

La réservation dynamique de la mémoire

Page 18: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

18

#include <stdio.h> 1/3#include <stdlib.h>void main() { int *p,*q,n,s;

printf("Entrer n=");scanf("%d",&n);p=(int*)malloc(n*sizeof(int));if(p == NULL)

{ printf("Pas de place!\n"); exit(1);}

printf("Apres malloc p=%p\n",p);

Entrer n=3Apres malloc p=245F:00F2

Exemple 1 Réserver de la mémoire pour un tableau de n nombres entiers. Remplir le tableau en dialogue. Modifier la taille de la mémoire préalablement alloué pour qu’on puisse ajouter la somme des éléments entrés. Afficher le tableau au début et après l’ajout de la somme.

La réservation initialle de la mémoire

Tableaux Dynamiques Unidimensionnels

Page 19: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

19

for(q=p,s=0;q<p+n;q++) 2/3{printf("Entrer un nombre:"); scanf("%d",q); s+=*q;}

for(q=p;q<p+n;q++)printf("%3d",*q);

printf("\n");

Entrer un nombre:11Entrer un nombre:22Entrer un nombre:33 11 22 33

Exemple 1

Remplir le tableau dynamique.Faire la somme des éléments entrés.

Affichage du tableau initial

Tableaux Dynamiques Unidimensionnels

Page 20: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

20

p=(int*)realloc(p,(n+1)*sizeof(int)); 3/3if(p == NULL)

{ printf("Pas de place!\n"); exit(1);}

printf("Apres realloc p=%p\n",p);*(p+n)=s;for(q=p;q<p+n+1;q++)

printf("%3d",*q);printf("\nLa somme=%3d\n",*(p+n));

free(p);p=NULL;

}

Apres realloc p=245F:00E6 11 22 33 66La somme=66

Exemple 1

Affichage du tableau après l’ajout de la somme

Modification de la taille

Tableaux Dynamiques Unidimensionnels

Page 21: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

21

1/4#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <conio.h>#define NUM 2

char *entrer(int n);void miroir(char *s,char *t);

Exemple 2Réserver de la mémoire pour un tableau (chaîne) de n caractères . Remplir la chaîne en dialogue. Modifier la taille s’il y a besoin. Afficher la chaîne et le nombre de caractères entrés. Trouver la chaîne miroir et l’afficher.

Les prototypes des fonctions

Tableaux Dynamiques Unidimensionnels

Page 22: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

22

void main() 2/4{ int n,len;

char *str,*rez;printf("Entrer n=");scanf("%d",&n);str=entrer(n);printf("\n");len=strlen(str);puts(str);printf("Le nombre de caracteres=%d\n",len);rez=(char *) calloc((len + 1) , sizeof(char));miroir(rez,str);printf("La chaine miroir est:\n");puts(rez);free(rez);rez=NULL;

}

Exemple 2

Tableaux Dynamiques Unidimensionnels

Page 23: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

23

char * entrer(int n) 3/4{ int i=0,len;

char *s,c;s =(char *) calloc((n + 1) , sizeof(char));if (s == NULL){ printf("Pas de place!|n"); exit(1); }do { fflush(stdin);

printf("\nEntrer un car.:"); c=getchar(); if(i >= n) {len=n+NUM; s =(char *) realloc(s,len * sizeof(char)); if (s == NULL) { printf("Pas de place!\n"); exit(1); } n=len; } s[i++]=c; printf("Entrer car suivant - O/N?");} while(toupper (getche()) == 'O');

s[i]='\0';free(s); /* ne ne pas oublier ( s est une variable locale) */return (s);

}

Exemple 2 La définition de la fonction d’entré

Page 24: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

24

void miroir(char *s,char *t) 4/4{ int n=strlen(t); t+=n-1; while(n)

{ *s++=*t--; n--;}

*s='\0';}

Exemple 2La définition de la fonction de miroir

Tableaux Dynamiques Unidimensionnels

Page 25: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

25

Tableaux Multidimensionnels

Réflexions sur la double indexation. Supposons que nous

ayons à écrire un programme qui opère sur des matrices à L lignes et C colonnes.

Un tableau à deux dimensions A est à interpréter comme

un tableau (uni-dimensionnel) de dimension L dont chaque composante est un tableau (uni-dimensionnel) de dimension C.

On appelle L le nombre de lignes du tableau et C le nombre de colonnes du tableau. L et C sont alors les deux dimensions du tableau. Un tableau à deux dimensions contient donc L*C composantes.

Page 26: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

26

Tableaux Multidimensionnels

On dit qu'un tableau à deux dimensions est carré, si L est égal à C.

En faisant le rapprochement avec les mathématiques, on peut dire que "A est un vecteur de L vecteurs de dimension C", ou mieux:

"A est une matrice de dimensions L et C".

Page 27: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

27

Tableaux Multidimensionnels Exemple Pour mémoriser les notes des 20 élèves dans les 10

devoirs d'un trimestre, nous pouvons rassembler plusieurs des tableaux uni-dimensionnels dans un tableau NOTE à deux dimensions. Dans une ligne nous retrouvons les notes de tous les élèves dans un devoir. Dans une colonne, nous retrouvons toutes les notes d'un élève.

Page 28: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

28

Tableaux Multidimensionnels Exemple

Déclaration et mémorisation

Comme pour les tableaux à une dimension, le nom d'un tableau est le représentant de l'adresse du premier élément du tableau (c.-à-d. l'adresse de la première ligne du tableau). Les composantes d'un tableau à deux dimensions sont stockées ligne par ligne dans la mémoire.

int NOTE[10][20] = { {45, 34, ... , 50, 48}, {39, 24, ... , 49, 45},

... ... ... {40, 40, ... , 54, 44} };

<TypeSimple> <NomTabl>[<DimLigne>][<DimCol>];

Page 29: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

29

Tableaux Multidimensionnels Exemple En supposant qu'une variable du type double occupe 8 octets (c.-à-d:

sizeof(double)=8), pour le tableau T déclaré par: double T[10][15];C réservera L*C*M = 10*15*8 = 1200 octets en mémoire.

Initialisation Lors de la déclaration d'un tableau, on peut initialiser les composantes du

tableau, en indiquant la liste des valeurs respectives entre accolades.

float B[3][2] = { {-1.05, -1.10 }, {86e-5, 87e-5 }, {-12.5E4, -12.3E4} };

Page 30: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

30

Tableaux Multidimensionnels Initialisation Lors de l'initialisation, les valeurs sont affectées ligne par ligne en passant de gauche à

droite. Nous ne devons pas nécessairement indiquer toutes les valeurs. Les valeurs manquantes seront initialisées par zéro. Il est cependant défendu d'indiquer trop de valeurs pour un tableau.

Réservation automatique Si le nombre de lignes L n'est pas indiqué explicitement lors de l'initialisation,

l'ordinateur réserve automatiquement le nombre d'octets nécessaires.

float B[ ][2] = { {-1.05, -1.10 }, {86e-5, 87e-5 }, {-12.5E4, -12.3E4} }; Réservation de 3*2*4 = 24 octets

Page 31: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

31

Tableaux Multidimensionnels Accès aux composantes

Affichage du contenu d'un tableau à deux dimensions

NomTableau>[<Ligne>][<Colonne>]

#include <stdio.h>main(){ int a[4][4]={{1},{1},{1},{1}};

int i,j; /* Pour chaque ligne ... */ for (i=0; i<4; i++)

{ /*considerer chaque composante */ for (j=0; j<4; j++)

printf("%3d", a[i][j]); /* Retour a la ligne */

printf("\n");}

return 0;}

1 0 0 01 0 0 01 0 0 01 0 0 0

Page 32: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

32

Tableaux Multidimensionnels Affectation avec des valeurs provenant de l'extérieur

#include <stdio.h>main(){ int a[3][4];

int i,j; for (i=0; i<3; i++)

{ for (j=0; j<4; j++) { printf("a[%d][%d]:",i,j); scanf("%d",&a[i][j]);}

} for (i=0; i<3; i++)

{ for (j=0; j<4; j++) printf("%3d", a[i][j]);

printf("\n");}

return 0;}

a[0][0]:1a[0][1]:2a[0][2]:3a[0][3]:4a[1][0]:5a[1][1]:6a[1][2]:7a[1][3]:8a[2][0]:9a[2][1]:10a[2][2]:11a[2][3]:12 1 2 3 4 5 6 7 8 9 10 11 12

Page 33: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

33

Tableaux Multidimensionnels

Un élément particulier de la matrice (m1) sera noté m1[i][j]. D'après ce que nous savons déjà, on peut l'interpréter de la manière suivante (Pour alléger les formules, nous supposons ici que la taille d'un int, et donc celle d'un

unsigned, sont égales à celle d'un pointeur):

float m1[NL][NC];m1[i][j]

= *(m1[ i ] + j)= *(float *)((unsigned int) m1[ i ] + j * sizeof(float))

m1[i] est un pointeur sur i-ème ligne

Page 34: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

34

Tableaux Multidimensionnels Etudions une autre manière d'accéder aux éléments de cette même matrice. Soient

les déclarations:

La variable m2 est donc déclarée comme un tableau de NL pointeurs vers des nombres flottants. Pour réaliser la matrice dont nous avons besoin, il nous sufit d'initialiser correctement ces pointeurs : chacun sera l'adresse d'une ligne de la matrice précédente.

float m1[NL][NC], *m2[NL];

Page 35: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

35

Tableaux Multidimensionnels

Il est remarquable qu'un élément de la nouvelle matrice ainsi déclarée se note encore

m2[i][j]

Page 36: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

36

Tableaux Multidimensionnels L’expression m2[i][j] se traduira (en continuant à négliger les conversions des types pointeurs)

par :

Il nous faut initialiser le tableau de pointeurs m2. La matrice m1 est la matrice existante.

m2[i][j]= *(m2[i] + j * sizeof(float))= *(*(m2 + i * sizeof(float *)) + j * sizeof(float))

for (i = 0; i < NL; i++)m2[i] = m1[i];

Page 37: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

37

Tableaux Multidimensionnels Dynamiques

Il n'y a pas en C d'équivalence d'écriture permettant une utilisation directe de l'allocation dynamique pour les tableaux multidimensionnels.

En effet, NC doit être connu à la compilation pour que l'expression i * NC + j ait un sens. Pour allouer dynamiquement une matrice de taille (NL,NC), on réserve un tableau

unidimensionnel de taille NL*NC.

Page 38: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

38

Tableaux Multidimensionnels Dynamiques

Supposons que la fonction void unCalcul(int nl, int nc) implémente un

algorithme qui requiert une matrice locale à nl lignes et nc colonnes.

#define NL 20#define NC 30. . .void unCalcul(int nl, int nc) {double mat[NL][NC]; /* en espérant que nl <= NL et nc <= NC */int i, j;/* utilisation de la matrice mat. Par exemple : */for (i = 0; i < nl; i++)for (j = 0; j < nc; j++)

mat[i][j] = 0;etc.}

Version statique

Page 39: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

39

Tableaux Multidimensionnels Dynamiques

void unCalcul(int nl, int nc) {double **mat;int i, j;/* initialisation des pointeurs */mat =(double **) malloc(nl * sizeof(double *));for (i = 0; i < nl; i++)

mat[i] = (double *) malloc(nc * sizeof(double));/* utilisation de la matrice mat. Par exemple : */for (i = 0; i < nl; i++)for (j = 0; j < nc; j++)

mat[i][j] = 0;etc./* libération (indispensable dans le cas d'une variable locale) */for (i = 0; i < nl; i++)

{ free(mat[i]); mat[i]=NULL; }free(mat);mat=NULL;}

Version dynamique

Page 40: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

40

Tableaux Multidimensionnels Dynamiques

Dans cette manière de procéder, les lignes de la matrice sont allouées à l'occasion de nl appels distincts de malloc.

La matrice est réalisée par des morceaux de mémoire.

lignes allouées séparément

Page 41: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

41

Tableaux Multidimensionnels Dynamiques

Exemple : Faire un programme de: 1) création d’une matrice dynamique de nombres entiers de l lignes, c colonnes; 2) affichage de la matrice. Utiliser les fonctions differentes de création et d’affichage.

#include <stdio.h> 1/4#include <stdlib.h>

int **creation(int l,int c);void affichage(int l, int c, int **a);

Les prototypes des fonctions

Page 42: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

42

Tableaux Multidimensionnels Dynamiques

Exemple

void main() 2/4{ int **x,l,c;

printf("nombre de lignes: ");scanf("%d",&l);printf("nombre de colonnes: ");scanf("%d",&c);x=creation(l,c);printf("La matrice cree.\n");affichage(l,c,x);

}

La fonction main, appelante les fonctions

nombre de lignes: 2nombre de colonnes: 3el[0][0]:1el[0][1]:2el[0][2]:3el[1][0]:4el[1][1]:5el[1][2]:6La matrice cree. 1 2 3 4 5 6

Page 43: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

43

Tableaux Multidimensionnels Dynamiques

Exemple

int **creation(int l,int c) 3/4{ int **t,i,j; t=(int **)malloc(l*sizeof(int *)); for(i=0;i<l;i++)

t[i]=(int *)malloc(c*sizeof(int)); for(i=0;i<l;i++)

for(j=0;j<c;j++) { printf("el[%d][%d]:",i,j);

scanf("%d",(t[i]+j)); }

free(t);return t;

}

La définition de la fonction de création

Page 44: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

44

Tableaux Multidimensionnels Dynamiques

Exemple

void affichage(int l, int c, int **a) 4/4{ int i,j;

for(i=0;i<l;i++){ for(j=0;j<c;j++)

printf("%3d",*(a[i]+j)); printf("\n");}

}

La définition de la fonction d’affichage

Page 45: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

45

Tableaux Multidimensionnels Dynamiques

#include <stdio.h>#include <stdlib.h> void main() { int **t,i,j;

t=(int **)malloc(2*sizeof(int*));for(i=0;i<2;i++)

t[i]=(int *)calloc(3,sizeof(int));for(i=0;i<2;i++)

*(t[i]+2)=6; for(i=0;i<2;i++)

{ for(j=0;j<3;j++)printf("%d%c",*(t[i]+j),' ');

printf("\n");}

}

Exercice

Page 46: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

46

Tableaux Multidimensionnels Dynamiques

#include <stdio.h>#include <stdlib.h> void main(){ int **t,i,j;

t=(int **)malloc(2*sizeof(int*));for(i=0;i<2;i++)

t[i]=(int *)calloc(3,sizeof(int));for(i=0;i<2;i++)

{ *(t[i]+1)=i; *(t[i]+2)=i+1;}

for(i=0;i<2;i++){ for(j=0;j<3;j++)

printf("%d%c",*(t[i]+j),' ');printf("\n");

} }

Exercice

Page 47: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

47

Tableaux de Tableaux Dynamiques

(matrices non pleines)

On gère en fait un ensemble de lignes de longueur différente (donc des tableaux dynamiques).

On utilise alors la même méthode que pour les matrices pleines, en changeant simplement le calcul pour accéder à une composante.

Chaque ligne est allouée dynamiquement (l'adresse et la longueur de chaque ligne étant stockée dans un tableau statique ou dynamique).

Les manipulations de composantes (dans les lignes) restent des manipulations de type tableaux.

Page 48: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

48

Tableaux de Tableaux Dynamiques

(matrices non pleines) Les manipulations de lignes se font par manipulation d'adresses (par exemple pour

échanger deux lignes, il suffit d'échanger les deux adresses de lignes, les lignes elles-mêmes n'étant physiquement pas déplacées).

Ces tableaux de tableaux dynamiques permettent toujours un accès presque direct à un élément l,c.

tab[ adresse_ligne[l] ][c]

Page 49: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

49

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères)

Le remplacement d'un tableau à deux indices par un tableau de pointeurs se révèle encore plus utile dans le traitement des tableaux de chaînes de caractères.

Cette technique permet de remplacer un tableau rectangulaire dont la largeur est déterminée par la plus grande longueur possible d'une chaîne par un espace linéaire dans lequel chaque chaîne n'occupe que la place qui lui est nécessaire.

Page 50: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

50

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères)

A. Matrice de caractères

Page 51: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

51

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères)

B. Tableau de chaînes de caractères

Page 52: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

52

Mot0

Mot1

Mot2

Mot9

char *Mot[10]

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères)

10 mots longueur maximale: 50 caractères

Page 53: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

53

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères)

Exemple - Ecrire un programme qui lit des mots (nombre des mots quelconque) au clavier (longueur maximale: 50 caractères). On attribue leurs adresses à un tableau dynamique a deux dimensions text. Afficher les mots saisies.

Page 54: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

54

text[0] Mot0

text[1]

text[2]

Mot1

Mot2

text[i]

text[n]Motn

char **text

Page 55: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

55

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères) Exemple

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <conio.h>#define L_MOT 51#define NUM 2void entrer_sortir(char **text,int *n_m,int *n_el);void main() { char **text;

int n_m=0,n_el=NUM;text=(char **)malloc(n_el*sizeof(char *));if(text==NULL) { printf("Error!Memory not allocated!\n"); exit(1); }entrer_sortir(text,&n_m,&n_el);

}

Page 56: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

56

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères) Exemple

void entrer_sortir(char **text, int *n_m, int *n_el) { char temp[51];

int i; char *mot;printf("Introduire des mots terminees par un retour a la ligne\n");fflush(stdin);do{

printf("\nmot %d:",*n_m);fgets(temp,sizeof(temp),stdin);mot=(char *)malloc((strlen(temp)+1)*sizeof(char));if(mot==NULL) exit(1);strcpy(mot,temp);if(*n_m==*n_el){ *n_el+=NUM;

text=(char**)realloc(text,*n_el*sizeof(char*));if(text==NULL) exit(1);

}

Page 57: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

57

Tableaux de Tableaux Dynamiques

(Tableaux de chaînes de caractères) Exemple

text[(*n_m)++]=mot;printf("\nMot suivant? Y/N:");

} while(toupper(getch()) == 'Y'); strcat(*(text+*n_m-1),"\n"); printf("\nLes mots sont\n"); for(i=0;i<*n_m;i++)

puts(text[i]); free(mot); mot=NULL;}

Page 58: 1 Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques

58