1. CHAPITRE 3:
TABLEAUX ET POINTEURS
Abdelouahed Sabri
abdelouahed.sabri@gmail.com
Références:
[1] Anne Canteaut« Programmation en langage C »
[2] E. Boucharé« Langage C »
[3] PatrickTrau « www-ipst.u-strasbg.fr/pat/program/tpc_c.htm »
Université Sidi Mohamed Ben Abdellah
Faculté des Sciences Dhar El Mahraz Fès
Sciences Mathématiques et Applications (SMA)
3. INTRODUCTION
Réflexion
Manipuler les notes d’un étudiant:
3 Modules
Saisi de notes
Saisi de coefficients
Calcul de la moyenne
Affichage des modules validés et modules non-validés
...
Variable: ne permet de stocker qu’une seule donnée
(type)
Il faut faire le traitement au-fur-et-à-mesure très lourd
Pour mieux organiser notre code, il faut utiliser
des variables élaborées: TABELAUX 3
4. INTRODUCTION
Solution:
La plupart des langages de programmation
proposent des conteneurs permettant de stocker un
ensemble de données dans une « seule variable »
Et pour accéder au contenu, il suffit de la parcourir
En C, on trouve deux types;
Tableau: permet de stocker plusieurs données de même type
(Notes, coefficients, ...)
Structure: permet de stocker des données hétérogènes
4
5. TABLEAUX SIMPLES
Définition:
Un tableau est une variable composée de données de même
type, stockées en mémoire de manière adjacente (l’une
après l’autre).
Déclaration
type nom_du_tableau [nombre_d_elements];
Exemples:
int note[20] ; // tableau de type entier de 20 éléments
float poids[15], tailles[6];
char prenom[255];
5
6. TABLEAUX SIMPLES
Accès aux éléments
nomTableau[indiceElement]
En C, les éléments d’un tableau de taille N sont indexés de
0 à N-1
l’indice du premier élément est 0
et l’indice du Nième élément est N-1
6
7. TABLEAUX SIMPLES
Exemples:
int maListe[10];
maList[0]=25; //Affecter au 1er élément de maList la valeur 25.
maList[2]=3;
maList[9]=-30; //Affectation au dernier élément la valeur -30.
printf("%d", maList[0]); //affiche la valeur 25; le contenu du 1er élément
printf("%d", maList[2]); // affiche la valeur 3.
// Lecture de la console
scanf("%d", &maList [0]);
/*mémoriser dans le 1er élément (élément d’indice 0) du tableau un
entier saisi au clavier.*/ 7
8. TABLEAUX SIMPLES
Initialisation
Il est possible d’initialiser un tableau lors de sa déclaration:
type nomTableau[taille]= {Valeurs séparés par virgule};
Exemples:
int nbr[10]={15,10,2,3,4,-5,6,8,8,9};
/* tableau de 10 éléments initialisés respectivement par les
valeurs indiqués entre { };
nbr[0]=15 ... nbre[5]=-5 ... nbre[10]=9
*/
int nbr[]={15,10,2,3,4,-5,6,8,8,9};
// même déclaration que la précédente
int tab[10]={1,2,3}; /* les 3 premiers éléments sont initialisés par
les valeurs indiqués et les7 autres
éléments sont initialisés par 0 */
8
9. TABLEAUX SIMPLES
Initialisation (suite)
Lors de l’initialisation d’un tableau, on peut omettre la
taille du tableau (le nombre des éléments )
type nomTableau[]= {Valeurs séparés par virgule};
Le nombre d’éléments du tableau est égale au nombre de
valeurs indiquées dans la liste entre les accolades
Exemple:
int nbr[]={15,10,2,3,4,-5,6,8,8,9};
/* tableau de 10 éléments initialisés respectivement par les
valeurs indiqués entre { };
nbr[0]=15 ... nbre[5]=-5 ... nbre[10]=9
*/
9
10. TABLEAUX SIMPLES
Lecture et écriture dynamique
Pour accéder aux éléments du tableau d’une manière
dynamique, utiliser les boucles (for de préférence)
Exemple
int i, tab[5];
printf("Entrer les éléments du tableau :n");
for(i=0; i<5; i++)
scanf("%d", &tab[i]); // Lecture des éléments
printf("Les éléments du tableau sont:n");
for(i=0; i<5; i++)
printf("%dt", tab[i]); // Affichage des éléments
10
11. LES TABLEAUX SIMPLES
Exercice:
Ecrire un programme qui lit un tableau d’entiers au clavier et
qui affiche:
Tous les éléments du tableau
La somme des éléments
Les éléments dans un sens inverse
11
12. LES TABLEAUX MULTIDIMENSIONNELS
Définition:
Un tableau à plusieurs dimensions est défini comme
un tableau de tableaux.
Définir et utiliser des tableaux de dimensions 2, 3, …
dimensions.
Pour un tableau de N dimensions, il faut donner la
taille pour chaque dimension (N valeurs)
Déclaration:
type nom_tableau [N1] [N2] [N3] …[Nn] ;
12
13. TABLEAU À DEUX DIMENSIONS
Un tableau à deux dimensions peut être
interprété comme une matrice.
Un tableau à 2 dimensions de L lignes et C colonnes
contient donc L*C composantes.
L lignes
C colonnes
13
14. TABLEAU À DEUX DIMENSIONS
Déclaration
type NomTableau[nbLignes][nbColonnes];
Exemple
int t[10][20];
float M1[20][20], M2[50][100];
char liste[100][20];
15. TABLEAU À DEUX DIMENSIONS
Accès aux éléments
Considérons un tableau à 2D de n lignes et m colonnes.
les indices des lignes du tableau varient de 0 à n-1, et les
colonnes de 0 à m-1.
La composante de la 2ème ligne et 4ème colonne d’un
tableau T est notée: T[1][3].
Exemple:
int t[3][2]; // Matrice de 3x2
t[0][0]=5; // Mettre 5 à la 1ére ligne et 1ére colonne
t[2][1]=-3: // Mettre -3 à la 3éme ligne et 3éme colonne
15
16. TABLEAU À DEUX DIMENSIONS
Initialisation
Comme pour le cas simple, lors de la déclaration d'un
tableau multidimensionnel, on peut initialiser ses
éléments, en indiquant la liste des valeurs respectives
entre accolades.
A l'intérieur de la liste, les composantes de chaque ligne
du tableau sont aussi (pas obligatoire) comprises entre
accolades.
Exemple
int t[4][3]= { {1 , 3, 0} , {-4 , 9 , 2} , {6, 3 , -1} , {4, 0 , 5} };
int t[4][3]= { 1 , 3, 0 , -4 , 9 , 2 , 6, 3 , -1 , 4, 0 , 5 };
16
17. TABLEAU À DEUX DIMENSIONS
Remarques
Lors de l'initialisation, les valeurs sont affectées ligne par
ligne en passant de gauche à droite.
Comme pour le cas 1D, il n’est pas nécessaire d’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.
17
18. TABLEAU À DEUX DIMENSIONS
Affichage des éléments
Pour afficher les éléments des tableaux à 2 dimensions, on
utilise deux indices et la boucle for, souvent imbriquée, pour
parcourir les lignes et les colonnes.
Exemple
for(int i=0;i<NL; i++){
for(int j=0;j<NC; j++)
printf("%dt",Tab[i][j]);
printf("n");
}
// NL : le nombre de lignes
// NC : le nombre de colonnes 18
20. LES POINTEURS
Réflexion;
int i=5;
printf ("i=%d son adresse mémoire:%d", i,&i);
Va donner comme résultat aprés execution
i=5 son adresse mémoire:2293532
int i=5,j=-154;
printf ("j=%d son adresse mémoire:%dn", j,&j);
printf ("i=%d son adresse mémoire:%d", i,&i);
Va donner comme résultat aprés execution
j=-154 son adresse mémoire:2293528
i=5 son adresse mémoire:2293532
20
-154 5
jj
2293528 2293532 ………adresse
mémoire
iiVariable
21. LES POINTEURS
Définition
Variable: sert à stocker les données manipulées par un
programme. Lorsque l’on déclare une variable, un espace
mémoire lui sera réservé pour y stocker sa valeur.
L’emplacement de cet espace dans la mémoire est nommé
adresse.
Pointeur: est une variable qui désigne un emplacement
mémoire (une adresse) occupée par une donnée
21
2293532 5
pp
2293532 ……2290004adresse
mémoire
iiVariable
…
On dit que p pointe sur l’adresse mémoire occupée par la
variable i
22. LES POINTEURS
Déclaration:
un pointeur est déclaré au moyen de l’opération d’indirection «*».
Syntaxe :
type * Nom_du_Pointeur>;
Nom_du_Pointeur ne peut (doit) recevoir que des adresses de
variables du type Type
Exemple:
int i, j; // déclaration de deux variables de type entier
int *p; // déclaration d’un pointeur sur une variable entière
float *ptr; // déclaration d’un pointeur sur une variable float
char nom, *ptr;
// déclaration d’une variable de type char et un pointeur sur char.
22
23. LES POINTEURS
Initialisation:
Lorsqu’on déclare un pointeur sans l’initialiser, on ne sait
pas sur quoi il pointe.
Pointeur qui ne pointe sur rien
int *ptr = NULL;
Pointeur qui pointe sur une variable
int i=5;
int *p=&i;
Pointeurs qui pointent sur la même adresse
int i=5;
int *p=&i;
int *q=p; 23
2293532 5
22935322293528
pp ii
2293532 2293532 5
22935322293528
pp ii
2293524
qq
24. LES POINTEURS
Manipulation:
Exemple:
int i=5;
int *p=&i;
&i: l’adresse mémoire de la variable i
printf("%dn",&i); 2293528
p: l’adresse mémoire sur laquelle pointe p
printf("%dn",p); 2293528
*p: représente le contenu de la case mémoire sur laquelle p
pointe:
printf("%dn",*p); 5
&p: l’adresse mémoire de la variable p:
printf("%dn",&p); 2293532
25. LES POINTEURS
Manipulation (suite):
Pointeur qui ne pointe sur rien
int *p = NULL;
int i=5;
p=&i;
printf("*p=%dn",*p); *p=5
*p=80;
printf("i=%dn",i); i=80
int *q=p;
printf("*q=%dn",*p); *q=80
(*p)++; // eq. à i++;
25
5 2293528
22935322293528
ii pp
0
2293532
pp
22935322293528
ii pp
2293524
80 2293528
22935322293528
ii pp
qq
2293528 80 2293528
26. LES POINTEURS
Manipulation (suite):
Exercice: que produit le code suivant
int a=51;
int b=120;
int * ptr;
ptr = (a>b) ? &a : &b;
(*ptr)++;
printf("a=%d, b=%d, *pointeur=%d n", a,b,*ptr);
26
27. LES POINTEURS
Manipulation (suite):
Exercice: que produit le code suivant
int a=51;
int b=120;
int * ptr;
ptr = (a>b) ? &a : &b; // ptr pointe sur la case b
(*ptr)++; // incrément ele contenu de la case pointée par ptr
printf("a=%d, b=%d, *pointeur=%d n", a,b,*ptr);
Le résultat:
a=51, b=121, *pointeur=121
27
28. LES POINTEURS ET TABLEAUX
Réflexion
int tab[4]={1,58, 7};
28
1 58 7 0 0
2293496
tab[0]tab[0]
1 58 7 0 0
2293496
tabtab
tab[1]tab[1] tab[2]tab[2] tab[3]tab[3] tab[4]tab[4]
Equivalent à
Le nom d'un tableau représente l'adresse de son
premier élément
Équivalent à dire que le nom d'un tableau est
un pointeur constant sur le premier élément du tableau
29. LES POINTEURS ET TABLEAUX
Pointeurs et tableaux sont en étroite relation:
Exemple 1:
int tab[10]={1,58, 7}, i;
printf ("%dn",*(tab)); // 1: tab pointe sur le 1er élément
printf ("%dn",*(tab+1)); // 58: tab+1 pointe sur le 2éme élément
printf ("%d",*(tab+i)); // 7: tab+i pointe sur le iéme élément
Exemple 2:
int tab[10]={1,58, 7}, i;
int *ptr;
ptr=tab; // équivalent à ptr=&tabl[0];
printf ("%dn",*(ptr)); // 1: ptr pointe sur le 1er élément de tab
printf ("%dn",*(ptr+1)); // 58: ptr+1 point esur le 2éme élément de tab
i=2;
printf ("%d",*(ptr+i)); // 7: ptr+i point sur l’iéme élément de tab
29
30. LES POINTEURS ET TABLEAUX
Relation entre pointeur et tableau (suite):
Exercice:
Déclarer un tableau de 5 éléments {15, 8, -8, 7, 9}
Afficher en utilisant une boucle for tous les éléments du
tableau:
1. Utilisant les indexes
2. Utilisant les pointeurs
30
31. LES POINTEURS ET TABLEAUX
Relation entre pointeur et tableau (suite):
Solution
#include <stdio.h>
main()
{
int tab[5]={15, 8, -8, 7, 9}, i;
for (i=0; i<5; i++)
{
printf ("%dt",tab[i]);
}
printf("n");
for (i=0; i<5; i++)
{
printf ("%dt",*(tab+i));
}
}
31
32. OCCUPATION MÉMOIRE
Taille d’une variable
Pour toute variable créée, une zone mémoire lui sera
associée, servant à stocker son contenu
La taille dépend du type de la variable:
char : 1 octet
int : 2 ou 4 octets (selon l’architecture du système)
float : 4 octets
double : 8 octets
etc
32
33. OCCUPATION MÉMOIRE
Taille d’une variable
L’opérateur « sizeof()» retourne la taille en octets
d’un type ou d’une variable passée en paramètre.
sizeof( type) ou bien sizeof( nom_variable)
Exemple:
double x, tab[]={1,2,5,8};
printf("Sur mon système un ‘double’ fait %d octets", sizeof(x));
taille de la variable x: 8 octets
// équivalent à
printf("Sur mon système un ‘double’ fait %d octets", sizeof(double));
taille de la variable du type double: 8 octets
// Astuce: taille d’un tableau: sizeof(tab)/sizeof(type)
printf ("Taille du tableau est: %d", sizeof(tab)/sizeof(double));
33
34. ALLOCATION DYNAMIQUE
Cas d’un pointeur:
Contrairement aux variables, un pointeur n’a pas
d’existence tant qu’on ne l’a pas initialisé.
Il existe en C, des fonctions permettant d'allouer la
mémoire à un pointeur.
La fonction malloc de la bibliothèque « stdlib » permet
de réserver de la mémoire au cours d’exécution d’un
programme.
Syntaxe:
malloc( <NombreOctets> )
Elle renvoie l’adresse d’un bloc mémoire de taille indiquée
en argument <NombreOctets>.
Elle renvoie 0 dans le cas d’échec.
34
35. ALLOCATION DYNAMIQUE
Cas d’un pointeur: allocation (Réservation) de mémoire
Exemple 1: Sans allocation de mémoire
#include <stdio.h>
#include<stdlib.h>
main()
{
char *ptrChr;
printf("Entrer un texte de 10 caractéresn");
scanf("%s",ptrChr);
printf("Texte saisi: %sn",ptrChr);
}
Erreur d’exécution: après la saisi du texte par
l’utilisateur, le programme va générer une erreur (Bug).
Car le pointeur ptrChr n’a d’espace mémoire réservé 35
36. ALLOCATION DYNAMIQUE
Cas d’un pointeur: allocation (Réservation) de mémoire
Exemple 2: Avec allocation de mémoire
#include <stdio.h>
#include<stdlib.h>
main()
{
char *ptrChr;
//Réservation de la mémoire
ptrChr = (char*)malloc(255); /* lui réservé 255 octets en mémoire */
printf("Entrer un texte: n");
scanf("%s",ptrChr);
printf("Texte saisi: %sn",ptrChr);
}
Le texte saisi sera affiché sans problème 36
37. ALLOCATION DYNAMIQUE
Cas d’un pointeur: Libération de la mémoire réservée:
La fonction free de la biblio. « stdlib » permet la
libération de l’emplacement mémoire réservé par malloc.
Syntaxe:
free(<Pointeur>);
37
38. ALLOCATION DYNAMIQUE
Cas d’un pointeur: allocation/libération de mémoire
Exemple:
char *ptrChr;
int *ptrIn;
float *ptrNotes;
//Réservation de la mémoire
ptrChr = (char*)malloc(10); /* réserve 10 octets mémoire (10 caractères) */
ptrIn = (int*)malloc(20); /*réserve 20 octets, soit la place pour 5 entiers*/
ptrNotes =(float*)malloc(16); /*réserve 16 octets, soit la place pour 4 réels */
//Libération de la mémoire
free(ptrChr); /* libère l’espace mémoire réservé pour ptr*/
free(ptrIn); /* libère l’espace mémoire réservé pour le pointeur notes */
free(ptrNotes); /* libère l’espace mémoire réservé pour le pointeur notes */ 38