Vous êtes sur la page 1sur 36

Objectifs du cours

M d l : Algorithmique
Module Al ith i & Programmation
P ti 1 1. Projection des notions d’algorithmique vers un langage de programmation

2 Prise en main des éléments de base du Langage C


2.

3. Comprendre la syntaxe du langage C


Cours
4. Apprendre à écrire un programme simple en langage C
Programmation en langage C
2011 2012
2011-2012

SAIDI Rajaa
r.saidi@insea.ac.ma

Bibliographie Plan du cours (1/2)


™ Langage C ™ Chapitre 1- Introduction au langage C
z Brian W. Kernighan, Dennis M. Ritchie : Le langage C : Norme ANSI – éditions z Historique du langage C
D
Dunod,
d Septembre
S t b 2004
z Caractéristiques du langage C
z Robert Sedgewick : Algorithmes en langage C – édition DUNOD, 2005
z Étapes de la programmation en C
™ Exercices en C z C
Composantes
t d’un
d’ programme en C
z C. Delannoy : Programmer en langage C avec exercices corrigés, 5e édition
2009 ™ Chapitre 2- Types de base, Opérateurs et Expressions
z Les types simples
z Déclaration des variables simples
z Les opérateurs standards
z Priorité et associativité des opérateurs

™ Chapitre 3
3- Quelques fonctions particulières
z Les Entrées (Input)
z Les Sorties (Output)

3 4
Plan du cours (2/2)

™ Chapitre 4- Les structures de contrôle


z Structures de choix
z Structures itératives
™ Chapitre 5- Les tableaux
z T bl
Tableaux à une di
dimension
i Chapitre 1
z Tableaux à plusieurs dimensions
z Implémentation des algorithmes de tri
INTRODUCTION AU LANGAGE C
™ Chapitre 6- Les pointeurs
z Déclaration et initialisation d’un pointeur
p
z Opérations élémentaires sur les pointeurs
z Allocation dynamique de la mémoire
™ Chapitre 7- Les fonctions
z Définition, appel et déclaration d’une fonction
z Vi ibilité ett d
Visibilité durée
é dde vie
i ddes variables
i bl
z Passage des paramètres d’une fonction
5 6

Préliminaire Historique du langage C

™ Avant la phase d’écriture d’un programme et de son implémentation, il faut ™ 1972 : Dennis Ritchie (chercheur dans les laboratoires Bell) a conçu le
d’abord bien définir le problème (et les données associées) et c’est langage C pour développer une version portable du système d’exploitation
l’ l ith i
l’algorithmique quii permett de
d le
l résoudre
é d UNIX
z Algorithme : séquence d’opérations visant à la résolution d’un problème en un
p fini
temps ™ 1978 : une 1ère définition du langage est apparue avec l’ouvrage de Ritchie
ett Kernighan
K i h « TheTh C programming i l
language »
™ Une fois l’algorithme et les structures de données définis, on les code en un
g g informatique et on obtient un programme
langage g ™ Années 80 : le langage C est devenu de plus en plus populaire que ce soit
d
dans l monde
le d académique
dé i que celui
l i des
d professionnels
f i l
z Programme : suite d’instructions permettant de réaliser une ou plusieurs tâches,
de résoudre un problème, de manipuler des données
™ 1983 : l’organisme ANSI «American National Standards Institute »
™ Nombreux langages de plus haut niveau ont été définis : chargeait
h it une commission
i i d mettre
de tt au point
i t une définition
défi iti explicite
li it ett
indépendante de la machine pour le langage C
z la programmation structurée (C, Pascal, …)
z l programmation
la ti fonctionnelle
f ti ll (Lisp,…)
(Li ) ™ 1989 : définition
défi iti ded la
l norme ANSI-C
ANSI C
z la programmation logique (Prolog, …)
z La p
programmation
g scientifique
q ((Maple,
p , Matlab,…)
, )
z la programmation objet (Smalltalk, Eiffel, C++, Java, …)
7 8
Caractéristiques du langage C Étapes de la programmation en C

™ Universel : C n'est pas orienté vers un domaine d'applications spéciales ™ C est un langage compilé ( par opposition aux langages
interprétés). Un programme C est décrit par un fichier texte,
™ Proche de la machine : il offre des opérateurs qui sont très proches de appelé fichier source traduit en langage machine (langage
ceux du langage machine (ex. la gestion de la mémoire) binaire). Cette opération est effectuée par le compilateur C

™ Rapide : car très proche du langage machine ™ La compilation se décompose en


4 phases successives :
™ Indépendant de la machine : il peut être utilisé sur n'importe quel système
en possession d
d'un
un compilateur C Préprocesseur : transformation
purement textuelle (inclusion
™ Portable : en respectant le standard ANSI-C, il est possible d'utiliser le d’autres fichiers sources…)
même programme sur tout autre système (autre hardware,
hardware autre système C
Compilation
il ti : traduit
t d it le
l fichier
fi hi pour
d'exploitation) générer un code en assembleur
Assemblage : transforme le code
™ Extensible : le langage est animé par des bibliothèques de fonctions assembleur en un fichier binaire (
extensibles fichier objet)
Edition de liens : liaison des
différents fichiers objets et
production de l’exécutable
9 10

Composantes d’un programme en C

™ Les instructions du langage C sont obligatoirement encapsulées dans des


fonctions et il existe une fonction privilégiée appelée main qui est le point
d départ
de dé t ded tout
t t programme

Début du p
programme
g
Chapitre 2

#include <stdio.h> Inclusion des bibliothèques TYPES DE BASE, OPÉRATEURS ET EXPRESSIONS

main() Point d'entrée du programme

{ int i=3; Déclaration des variables

printf( Bonjour %d fois!\n


printf("Bonjour fois!\n", i); Affichage de données

//*Ce
Ce programme affiche Bonjour 3 fois!
fois!*// Commentaire

} Fin du programme 11 12
Types simples Types simples

™Un type définit l'ensemble des valeurs que peut prendre une Type Description Octets

variable,, le nombre d'octets à réserver en mémoire et les Entiers char caractères 1

opérateurs que l'on peut appliquer dessus int entiers 2 ou 4


short [int
[int]] entiers courts 2
™En C,
C il n'y a que deux types de base : long [[int
int]] entiers longs 4

z les entiers Réels float nombres décimaux 4


double nombres décimaux de précision supérieure 8
z l réels
les é l
long double nombres décimaux encore plus précis 10 ou 12

™ Remarques
z Un caractère (char) est un nombre entier (il s'identifie à son code ASCII). Par
conséquent, une variable de type char peut contenir une valeur entre -128 et
127 et elle peut subir les mêmes opérations que les variables du type short,
short int
ou long
z Si l'on ajoute le préfixe unsigned à l'une de ces variantes, alors on manipule des
entiers
ti non signés
i é

13 14

Définition d’une variable Définition d’une constante

™ Nom ™ En utilisant l'attribut const, la valeur d'une variable ne change pas au cours
z Unique pour chaque variable de l’exécution du programme
z C
Commence ttoujours
j par une llettre
tt
z Différenciation minuscule-majuscule ™ Exemples

™ Type const int MAX = 767 ; const char NEWLINE = '\n'


\n ;
z Conditionne le format de la variable en mémoire
™ La directive #define permet de donner un nom à une constante. Dans ce
™ Valeur cas le préprocesseur effectue le remplacement correspondant avant la
z Peut évoluer pendant l'exécution compilation
z initialisation grâce à l'opérateur d'affectation (=)

™ Déclaration d'une variable


™ Exemples
z Type nom_de_la_variable [= valeur];
#define TVA 20
™ Exemple
z int nb; char c = 'a';
#define PI 3.14159
float pi = 3.14; double r = 6.2879821365;

z

int a; a=TVA; /*a prend la valeur 20*/


15 16
Opérateurs, Expressions & Instructions Les opérateurs (1/5)

™ Les opérateurs sont des symboles qui permettent de manipuler des ™ Affectation simple
variables, c'est-à-dire effectuer des opérations ™ Sy
Syntaxe
ta e : <variable>
a ab e = <expression>
e p ess o ;
™ Une expression est un calcul qui donne une valeur comme résultat et ayant ™ Exemples
un type
constt int
i t LONG = 141 ; /* affectation
ff t ti de d valeurs
l constantes
t t */
™ Une expression peut comporter des constantes, des variables et des
appels de fonctions combinés entre eux par des opérateurs et former ainsi ™ On peut enchaîner des affectations. L'évaluation commence de la droite vers la
gauche
une expression
i complexe
l
™ Exemples
™ Toute expression suivie d'un point virgule devient une instruction
b=(a = 5 + 3)+1 a = 8 et b = 9

a=b=c=d équivalente à : a = (b = (c = d))

™ Opérateurs d'affectation étendue : += -= *= /= %=

™ Exemples

a = a + b s'écrit a += b
17 18

Les opérateurs (2/5) Les opérateurs (3/5)

™ Arithmétiques ™ Opérateurs particuliers de C


z addition (+), soustraction (-), multiplication (*) et division (/) ™ Opé
Opérateurs
ateu s d'incrémentation
d c é e tat o (++)
( ) et de déc
décrémentation
é e tat o ((--))
™ Relationnels ™ Post-incrémentation <var>++; équivalente à <var>=<var>+1;
z <, <= , > , >= , != , == (égalité) , =(affectation), ! (négation), || (ou
ou logique), &&
(ett logique),%(reste de la division) ™ Post-décrémentation
P t dé é t ti < <var>--;
> équivalente
é i l t à<
<var>=<var>-1;
> < >1
z le résultat de la comparaison est un entier valant ™ Dans une expression, la valeur de la variable <var> est d'abord utilisée telle quelle,
– 0 si le résultat de la comparaison est faux puis incrémentée (ou décrémentée)
– 1 si le résultat de la comparaison est vrai

™ Exemple ™ Pré-incrémentation ++<var>; équivalente à <var>=<var>+1;


a = 2+3 valeur de a : 5
a = 3%2 valeur de a : 1 ™ Pré-décrémentation --<var>; équivalente à <var>=<var>-1;
a = (6==5)
(6 5) valeur de a : 0 ™ Dans une expression, la valeur de la variable <var> est d'abord incrémentée (ou
a = (2!=3) valeur de a : 1 décrémentée), puis utilisée
a = (6<=3) valeur de a : 0
a =((3==3) || (6<=3)) valeur de a : 1
a =((3==3) && (6<=3)) valeur de a : 0
19 20
Les opérateurs (4/5) Les opérateurs (5/5)
™ Opérateurs particuliers de C ™ Opérateur séquentiel ( , )

e pe
™ Exemple e p
<expr1> , <expr2>,…,
e p , , <exprN>
e p

™ Avant chaque opération, i et j contiennent respectivement 3 et 15 ™ Exprime des calculs successifs dans une même expression

™ Exemple
E l
Opération équivalent Résultat
i++;++j; i=i+1;j=j+1 i=4 et j=16 L'expression : x = 5 , x + 6 a pour valeur 11
i=++j; j=j+1; i=j; i=16 et j=16 ™ Opérateur conditionnel (? :)
i=j++; i=j; j=j+1; i=15 et j=16
<expression> ? <expr1> : <expr2>
j=--i+5; i=i-1; j=i+5; i=2 et j=7
j=i--+5; j=i+5; i=i-1; i=2 et j=8 ™ <expression> est évaluée. Si sa valeur est non nulle, alors la valeur de <expr1> est
retournée. Sinon, c'est la valeur de <expr2> qui est renvoyée
i=i++; i=i; i=i+1 i=4
™ Exemple

c=a>b?a:b

™ si a est le plus grand, alors affectation à c le contenu de a sinon affectation à c le


21 contenu de b 22

Priorité et associativité des opérateurs Exercice 1


™ Lors de l'évaluation des différentes parties d'une expression, les opérateurs Donner la valeur de i, j, n aux endroits demandés
respectent certaines lois de priorité et d'associativité
#include<stdio.h>
Priorité Opérateur Associativité
™ Exemples main()
1 () Æ
{
Prenons a = 3 et b = 4, l’expression a *= b += 5 s'évalue : 2 ! ++ -- Å
i t i,
int i jj, n;
a *= ( b += 5 ) 3 */% Æ
Priorité Opérateur Associativité i=0;n=i++;
4 +-* Æ
a *= ( b = b + 5 ) 1 () Æ A:i=?n=?
5 == != Æ
2 ! ++ -- Å i=10; n=++i;
a *= ( b = 9 ) 6 && Æ
3 */% Æ B:i=?n=?
a *= 9 i=20; j=5; n=i++ * ++j; 7 = += *= Å
4 +- Æ
a=a*9 5 == != Æ C:i=?n=?
6 && Æ i=15; n=i+=3;
a = 27
7 = += *= Å D:i=?j=?n=?
27 i=3; j=5; n=i*=--j;
E:i=?j=?n=?
}
23 24
Exercice 2

Donner la valeur de n, p, q, r aux endroits demandés

#include<stdio h>
#include<stdio.h> Priorité Opérateur Associativité
main() 1 () Æ
{ int n=10,, p=5,
p , q=10,
q , r;; 2 ! ++ -- Å Chapitre 3
r=n== (p=q); 3 */% Æ
A:n=? p=? q=?r=? 4 +-* Æ
5 == != Æ QUELQUES FONCTIONS PARTICULIÈRES
n= p=q=5;
6 && Æ
n+=p+=q;
7 = += *= Å
B: n = ? p = ? q = ?

q=n<p
q p ? n++ : p
p++;;
C: n = ? p = ? q = ?

q= n>p ? n++ : p++;


D: n = ? p = ? q = ?
} 25 26

Affichage de la valeur d’une variable (1/4) Affichage de la valeur d’une variable (2/4)

™ Utilisation de la fonction printf ™ Utilisation de la fonction printf

™ Syntaxe : printf(
printf("format
format d’affichage"
d affichage , variables) ™ Syntaxe : printf(
printf("format
format d’affichage"
d affichage , variables)
ƒ format : texte, caractères de contrôle (‘\n’ , ‘\t’ , …) et spécificateurs de format ™ Exemple 1
ƒ spécificateurs de format :
int a = 120 ;
FORMAT TYPE Description int b = 60 ;
%d ou %i int entier relatif
printf("%i
i tf("%i plus
l %i estt %i\
%i\n",
" a, b,
b a + b) ;
//Affiche sur l'écran : 120 plus 60 est 180
%u Unsigned int entier naturel (unsigned)
%o int entier exprimé en octal ™ Exemple
E l 2
%x int entier exprimé en hexadécimal
char b = 'A' ; /* le code ASCII de A est 65 */
%c char caractère
printf("Le caractère %c a le code %i\n", b, b) ;
%f float ou double réel en notation décimale // Affiche sur l'écran : Le caractère A a le code 65
%e float ou double réel en notation exponentielle
%s char* chaîne de caractères

27 28
Affichage de la valeur d’une variable (3/4) Affichage de la valeur d’une variable (4/4)

™ Caractères de contrôle : ™ Utilisation de la fonction printf


Caractère de contrôle Signification
g
™ Action sur le gabarit d’affichage
d affichage
`\a` Bip sonore
`\b` Retour arrière ƒ Les entiers sont affichés par défaut sans espaces avant ou après

`\t` Tabulation horizontale ƒ Les flottants avec six chiffres après le point
`\n` Passage à la ligne suivante
ƒ Pour agir sur l’affichage, un nombre est placé après % et précise le nombre de
`\r`
\r Retour chariot caractères
è minimum
i i à utiliser
ili
`\0` Caractère nul Exemples
`\\`
\\ Trait oblique (antislash) printf("%f" , x );
`\?` Point d’interrogation x = 1.2345 1.234500
printf("%3d" , n );
`\"` Guillemets x = 12.3456789 12.345678
n = 20 ^20
20
`\f` Saut de page n=3 ^^3 printf("%10f" , x );
™ Exemple `\v` Tabulation verticale n = 2358 2358 x = 1.2345 ^^1.234500
char b = 'A' ; printf("\tLe caractère %c a le code %i\n", b, b) ; n = -5200 -5200 printf("%-10f" , x ); //cadrage à gauche
x = 1.2345 1.234500 ^^
29 30

Lecture d’une valeur saisie au clavier Affichage d’un caractère

™ Utilisation de la fonction scanf ™ Utilisation de la fonction putchar

™ Syntaxe : scanf(
scanf("format
format de lecture
lecture", &variables) ™ Syntaxe : putchar(variable) // variable de type int ou char

™ Exemple ™ Exemple
#include <stdio.h>
<stdio h>
main() char c = 'a' ;
{ int n, p; //déclaration des variables
char b = '\n' ;
printf("donner une valeur pour n : "); putchar('x') ;
scanf("%d",&n); // lecture de la valeur de n /* affiche la lettre x */
putchar('?') ;
//affichage de la valeur de n //* affiche le symbole ? *//
printf("Merci pour %d\n",n); putchar(b) ;
/* retour à la ligne */
p
printf("donner
( une valeur p
pour p : ");
) putchar(65) ;
scanf("%d",&p); // lecture de la valeur de p
/* affiche le caractère de code ASCII = 65 c.-à-d. la lettre A */
//affichage de la valeur de p putchar(c) ;
printf( Merci pour %d\n"
printf("Merci %d\n ,p);
p); //* affiche le caractère a *//
}
31 32
Lecture d’un caractère Exercice

™ Utilisation de la fonction getchar() ™ Ecrire un programme qui permute et affiche les valeurs de trois variables A,
B, C de type entier saisis par le clavier( A-->B, B-->C, C-->A)
™ Syntaxe : char variable = getchar()
™ Correction
™ Cette fonction peut accepter un caractère saisi au clavier, y compris un #include<stdio.h>
caractère spécial,
spécial et ll'afficher
afficher sur ll'écran
écran
main()
™ Exemple {
printf("donner une valeur pour le caractère c "); i t A,
int A BB, C;
C
char s =getchar(); //scanf("%c",&s); int AIDE;
printf("Entrer
p ( la valeur de A,, B et C :\t");
);
scanf("%d %d %d", &A,&B,&C);
printf("A=%d \t B=%d\t C=%d\n",A,B,C);
AIDE= A;
A=C; C=B;
B=AIDE;
printf("A=%d \t B=%d\t C=%d\n",A,B,C);
33 } 34

Structures de choix (1/3)

™ Contrôlent le déroulement de l’enchaînement des instructions à l’intérieur


d’un programme

™ Ces instructions peuvent être exprimées par


z Des instructions de branchement conditionnel : if ….else
Chapitre 4 z Des instructions de branchement multiple : switch
STRUCTURES DE CONTROLE

35 36
Structures de choix (2/3) Exercice 1

™ Branchement conditionnel : if ….else ™ Ecrire un programme qui affiche le plus grand de trois entiers saisis au
clavier (A,B,C)
™ Syntaxe
if( expression) ™ Correction
ƒ expression : expression quelconque.
instruction; #include<stdio.h>
p
Après évaluation,, si elle est vraie,,
ou main()
alors le 1er bloc d’instructions est
exécuté, sinon c’est le 2ème bloc qui { int A,B,C, Max;
if( expression)
{ Instruction1; est exécuté printf("entrer
p ( e e leses valeurs
a eu s des trois
o s entiers
e e s (A,
( , B,, C) : ");
);
… scanf("%d %d %d",&A,&B,&C);
}
else
ƒ bloc d’instructions : peut désigner if(A>B)
{ instruction2; une suite dd’instructions
instructions délimitées par Max = A;
… des accolades ou une seule instruction else Max = B; Max =(A>B?A:B)>C?(A>B?A:B):C;
} if(C>Max)
Max = C;
™ Exemple printf("le max de %d,%d et %d est : %d\n",A,B,C,Max);
if (a == b) a=1;
a 1; //si a égal à b j’affecte
j affecte 1 à a }
if (a == b) a=1; else a=0; //si a égal à b j’affecte 1 à a sinon j’affecte 0 à a
37 38

Exercice 2 Structures de choix(3/3)

™ Ecrire un programme qui résout l'équation AX+B=0 ™ Branchement multiple : Switch


z Bien évidemment, on n'oubliera pas tous les cas particuliers (notamment les cas
"tout x est solution" et "pas de solution") ™ Syntaxe
switch (expression) Teste si une expression prend une
™ Correction { valeur p parmi une suite de
#include<stdio.h> case constante_1 : [ suite_d'instructions_1 ] ; constantes, et effectue le
main() case constante_2 : [ suite_d'instructions_2 ]; branchement correspondant si
{ float A,B; .............. c’est le cas
case constante_n : [ suite_d'instructions_n ];
printf("Tapez la valeur de A :"); scanf("%f",&A);
default : suite_d'instructions ;
printf("Tapez la valeur de B :"); scanf("%f",&B); }
if(!A) /* if(A==0)*/
if(A 0)*/
™ Exemple
{
if(!B) /* if(B==0) */ int a;
printf("Tout X est solution"); switch
it h (a)
( )
else printf("Pas de solution"); { case 7 : a=2; //si a égal à 7 j’affecte 2 à a
} case 4 : a
a=3;
3; //si a égal à 4 j’affecte
j affecte 3 à a
else printf("Une seule solution : %f", -B/A); default : a=0; //sinon j’affecte 0 à a
} }
39 40
Structures itératives (1/3) Structures itératives (2/3)

™ Instructions itératives : while ™ Instructions itératives : do while


while(( expression
p ) on vérifie la condition avant d’exécuter
d exécuter do on exécute la liste d’instructions
d instructions avant
{ la liste d’instructions { de vérifier la condition
instructions; instructions;
… …
} }
while( expression );
™ Exemple
int a=0; ™ Exemple
while(a<4) //tant que a<4 j’exécute les instructions suivantes
{ int a=0;
a++; do //faire les instructions suivantes
printf ("La valeur de a :%d \n", a); {
} a++; // j’incrémente
j’i é t adde 1
printf ("La valeur de a :%d \n", a);
}
while(a<4);
hile(a<4) //tant que
q e a<4

41 42

Structures itératives(3/3) Exercice 1

™ Instructions itératives : for ™ Ecrire un programme qui calcule n! d’un entier saisi par le clavier. Utiliser
une boucle while puis une boucle for
for( exp1 ; exp2 ; exp3 ) exp1 : effectue les initialisations nécessaires
{ avant l’entrée dans la boucle ™ Correction
instructions; exp2 : est le test de continuation de la boucle ; le
… // Avec la boucle while
test est évalué avant ll’exécution
exécution du corps de la //Avec la boucle for
} #include <stdio.h>
boucle #include <stdio.h>
main()
exp3 : est exécutée à la fin du corps de la boucle main()
{
{
int n,i=1,fact= 1;
int n,i,fact= 1;
™ Exemple printf("ENTRER UN ENTIER : ");
printf("ENTRER UN ENTIER: ");
int a; Remarques :
R scanf("%d",&n);
f("%d" & )
scanf("%d",&n);
for( a=0; a<4 ; a++ ) ƒ En pratique, exp1 et exp3 contiennent while (i<=n)
for (i=1;i<=n;i++)
{ souvent plusieurs initialisations séparées {
fact= fact * i;
fact
printf
i f ("La
("L valeur
l de
d a :%d
%d \n",
\ " a);
) par des virgules fact= fact * i;
} printf("\nn = %d n! = %d",n,fact);
ƒ Les expressions exp1 et exp3 peuvent i++;
}
être absentes ((les p
points virgules
g doivent }
cependant apparaître) : for (;exp2;) printf("\nn = %d n! = %d",n,fact);
}
43 44
Exercice 2 Instructions break et continue (1/2)

™ Ecrire un programme qui affiche tous les diviseurs d’un entier n saisi par le ™ Instruction break
clavier. Utiliser la boucle do…while z L’instruction break peut être employée à l’intérieur de n’importe quelle boucle
(for ; while ; do…while ; switch)
™ Correction
z Elle permet l’abandon de la structure et le passage à la première instruction qui
#include <stdio.h> suit la structure
main() z En cas de boucles imbriquées, break fait sortir de la boucle la plus interne
{
int div=1,n; ™ Exemple
printf("ENTRER UN ENTIER: "); scanf("%d",&n);
printf("\nLISTE DES DIVISEURS DE %d :",n); int i, j ;
do for (i = 1 ; i<=10 ; i++)
{ {
if(n%div==0) for (j = 1 ; j<=10 ; j++)
printf("\t%d",div); {
if(j == 5) break ;
div++;
}
printf("%d\t", i * j) ;
while(div<=n); }
} printf("\n") ;
}
45 46

Instructions break et continue (2/2) Exercice 1

™ Instruction continue ™ Que fait ce programme?


z L’instruction continue peut être employée à l’intérieur d’une structure de type #include <stdio.h>
boucle (for ; while ; do…while ) main()
z Elle permet l’abandon de l’itération courante et fait passer directement à { int n=0;
l’itération suivante d’une boucle do
z L’instruction continue concerne la boucle la plus interne {
if(n%2==0) { printf("%d est pair \n ",n);
n+=3;
continue;
™ Exemple }
Valeurs Affichage
int i, j ; if(n%3==0) { printf("%d est multiple de 3 \n ",n);
i=2 et j=3 i : 2 et j : 3 n+=5;
5
……//Initialisations i : 1 et j : 2
for ( ; i>0 && j>0; i--,j--) }
i=6 et j=3 i : 6 et j : 3 if(n%5==0) { printf("%d est multiple de 5 \n ",n);
{
i : 4 et j : 1 break;
break
if(i == 5) continue;
i=3 et j=5 i : 3 et j : 5 }
printf("i : %d et j : %d\n", i, j) ; n+=1;
if(j == 5) break ; }
} while(1);
}
47 48
Exercice 2

™ Écrire un programme qui fournit la liste des nombres premiers inférieurs à


50

™ Correction
#include <stdio.h> Chapitre 5
main()
{
int n; /* variable destinée à contenir les entiers inférieurs à 50 */
int i; LES TABLEAUX
printf("1, 2"); /* Les deux premiers nombres premiers sont affichés */

/* Pour les entiers entre 3 et 50, on vérifie s'ils ont un diviseur autre que 1 */
for (n = 3; n <= 50; n+=2)
{
f (i = 2;
for 2 i*i <= n; ii++))
if (n%i==0) break;
if (i*i > n) printf(", %d", n);
}
}
49 50

Définition Tableaux à 1 dimension (vecteur)

™ Ensemble de variables de même type, de même nom caractérisées par un ™ Déclaration


index
type nom_tableau [dimension] // la dimension doit être une constante
™ La déclaration d’un tableau réserve un espace de mémoire contiguë dans
lequel les éléments du tableau peuvent être rangés ™ Exemples
™ Exemple char X[80]; // Tableau de caractères de dimension 80
T 3
int T[10]; // Tableau d’entiers de dimension 10
7
98
5 T 6 76 34 97 54 32 0 8 13 25
63
8
77

51 52
Tableaux à 1 dimension (vecteur) Tableaux à 1 dimension (vecteur)

™ Initialisation ™ Accès aux éléments du tableau


type nom_tableau [N]= {valeur1, valeur2,…, valeurN}; Nom_tableau[indice]
– Exemple
int X[10] = {9,8,7,6,5,4,3,2,1,0}; char T[4] = {‘v’,‘b’, ‘a’, ‘k’}; z Exemple

™ Remarques
Indice 0 1 2 3 ….
z Si la dimension n'est pas indiquée explicitement lors de l'initialisation, alors
X[2] = 10; Valeur 9 8 10 6 ….
ll'ordinateur
ordinateur réserve automatiquement le nombre d
d'octets
octets nécessaires
– Exemple
int A[ ] = {10, 20, 30, 40, 50}; //taille en octet de (int)*nombre d’éléments
z Si la liste de constantes ne contient pas assez de valeurs pour tous les ,le premier élément commence à l'indice 0 !!
éléments, les éléments restants sont initialisés à zéro
– Exemple
int A[5] = {10, 20, 30}; // équivalent à : int A[5] = {10, 20, 30, 0,0};
z Si le nombre de constantes est supérieur à la dimension du tableau, le
compilateur déclare une erreur
– Exemple
int A[2] = {10, 20, 30}; // Erreur 53 54

Exercice 1 Exercice 2

™ Écrire un programme qui calcule la moyenne de toutes les valeurs d’un ™ Ecrire un programme qui lit la dimension N d'un tableau T de type int
tableau de 4 réels {2.0, 16.5, 58.56, 19.92} (dimension maximale : 50), remplit le tableau par des valeurs entrées au
clavier
l i ett affiche
ffi h le
l tableau
t bl
™ Correction
™ Effacer ensuite toutes les occurrences de la valeur 0 dans le tableau T et
#include <stdio.h>
<stdio h> t
tasser l éléments
les élé t restants.
t t Afficher
Affi h le
l tableau
t bl résultant
é lt t
main()
{ int i = 0;
float moyenne,
moyenne sommeTotale = 0.0; 0 0;
/* On initialise notre tableau avec 4 valeurs de type float*/ ™ Structure du programme
float T[4] = {2.0, 16.5, 58.56, 19.92};
f (i = 0
for 0; i < 4
4; ii++)) //
//Déclaration des variables
{ //Lecture de la dimension du tableau
printf("Valeur de T[%d] = %f\n", i, T[i]); //Lecture des valeurs du tableau
sommeTotale += T[i]; //Calcul de la somme des valeurs //Affi h
//Affichage d valeurs
des l d tableau
du t bl
//Suppression des zéros
}
//Affichage des valeurs du tableau résultat
moyenne
y = sommeTotale / 4;; //Calcul de la moyenne
y
printf("\n Moyenne des valeurs du tableau : %f", moyenne);
}
55 56
Exercice 2 : Correction Recherche dans un tableau : Recherche séquentielle
#include <stdio.h>
main() ™ Principe de la recherche séquentielle
{int N,i,j, T[50]; // Déclaration des variables z recherche de x en parcourant les éléments de t un à un
//Lecture de la dimension du tableau z par ordre croissant (ou bien décroissant) des indices
printf("Donner la dimension du tableau (<50) :"); scanf("%d",&N);
z jusqu’au premier indice k tel que t[k] = x : RECHERCHE AVEC SUCCÈS
//Lecture des valeurs du tableau
for(i=0;i<N;i++) z ou bien
bi jusqu’à
j ’à avoir
i parcouru l’i
l’intervalle
t ll [a,
[ b] en entier
ti sans trouver
t x:
{ printf("T[%d] :", i); scanf("%d",&T[i]); } RECHERCHE AVEC ÉCHEC
//Affichage des valeurs du tableau
f (i 0 i N i )
for(i=0;i<N;i++)
{ printf("%d\t", T[i]); } ™ Hypothèse : Soit k appartient à [a, b] et supposons que x n’appartient pas à
//Suppression des zéros t[a..k − 1]
for(i=0;i<N;i++)
{ if(T[i]==0)
{ for(j=i;j<N-1;j++)
{ T[j]=T[j+1]; } // Décalage des éléments du tableau
N--; i--;
} z Si t[k] = x, alors recherche terminée avec SUCCÈS
} //Affichage des valeurs du tableau résultat….
résultat z Si t[k] ≠ x, alors passer à l’élément
l élément suivant, s’il
s il y en a un !
……..suite du programme z Sinon recherche terminée avec ÉCHEC
57 58

Exercice : implémentation de la recherche séquentielle Recherche dans un tableau : Recherche dichotomique


™ Principe de la recherche dichotomique (dans un tableau trié)
™ Implémenter la méthode de recherche séquentielle en utilisant les
données suivantes : z calcul de l’indice du milieu m = (a+b)/2
z sii t[m]
t[ ] = x alors
l : RECHERCHE AVEC SUCCÈS
/* Déclarations */ Structure du programme
z sinon si t[m] < x alors recherche dans t[m + 1..b]
int A[50]; /* tableau donné */ /* Déclarations */
sinon recherche dans t[a..m − 1]
int VAL; /* valeur à rechercher */ /* Saisie des données */
z

int POS; /* position de la valeur */ /* Affichage du tableau */ ™ Exemple


int N; /* dimension */ /* Recherche de la position de la valeur */ 1 15
i t i;
int i /* indice
i di courantt */ //* Edition du résultat *//

/* Recherche de la position de la valeur */


POS
OS = -1;;
for(i=0 ; (i<N)&&(POS==-1) ; i++)
if(A[i]==VAL) POS=i;
//* Edition du résultat *//
if (POS==-1)
printf("La valeur recherchée ne se trouve pas dans le tableau.\n");
else
printf("La valeur %d se trouve à la position %d. \n", VAL, POS);
59 60
Exercice : implémentation de la recherche dichotomique Exercice : implémentation de la recherche dichotomique

™ Implémenter la méthode de recherche séquentielle en utilisant les /* Initialisation des limites du domaine de recherche */
données suivantes : INF=0;
/* Déclarations */ SUP=N-1;
/* Recherche de la position de la valeur */
int A[50]; /* tableau donné */ POS=-1;
int VAL; /* valeur à rechercher */ while ((INF<=SUP) && (POS==-1))
int POS; /* position de la valeur */
{
int N; /* dimension */
i t I;
int I /* indice
i di courantt */
MIL (SUP INF)/2;
MIL=(SUP+INF)/2;
int INF, MIL, SUP; /* limites du champ de recherche */ if (VAL < A[MIL])
SUP=MIL-1;
St
Structure
t du
d programme else
/* Déclarations */ if (VAL > A[MIL])
/* Saisie des données */ INF=MIL+1;
/* Affichage
Affi h d
du ttableau
bl */ else
/* Initialisation des limites du domaine de recherche */ POS=MIL;
/* Recherche de la position de la valeur */ }
/* Edition du résultat */

61 62

Avantage de la recherche dichotomique Insertion d’un élément dans un tableau (1/2)

™ Dans le pire des cas d'une recherche séquentielle, il faut traverser tout le ™ Écrire un programme qui insert un élément E à la position POS d’un
tableau avant de trouver la valeur ou avant d'être sûr qu'une valeur ne se tableau de N entiers
t
trouve pas dans
d l tableau
le t bl /* Déclarations */
™ Lors de la recherche dichotomique, on élimine la moitié des éléments du int A[50]; /* tableau donné */
t bl
tableau à chaque
h exécution
é ti d la
de l boucle.
b l Ainsi,
Ai i la
l recherche
h h se termine
t i int E; /* valeur à insérer*/
beaucoup plus rapidement int POS; /* position de la valeur */
int N;; /* dimension */
™ La
L recherche
h h dichotomique
di h t i d i t extrêmement
devient tê t avantageuse
t pour la
l int i; /* indice courant */
recherche dans de grands tableaux triés

™ Exemple
E l St
Structure
t du
d programme
z Lors de la recherche dans un tableau de 1024 éléments : /* Déclarations */
– le p
pire des cas p
pour la recherche séquentielle
q peut entraîner 1024 exécutions de
p /* Saisie des données */
la boucle /* Affichage
Affi h d
du ttableau
bl */
– le pire des cas pour la recherche dichotomique peut entraîner 10 exécutions de /* Saisie de la valeur à insérer et dans quelle position*/
la boucle /* Insertion de la valeur E à la position POS */
/* Affichage du tableau */

63 64
Insertion d’un élément dans un tableau(2/2) Fusion de deux tableaux triés (1/2)

/* Déclarations */ ™ Soit T1 et T2 deux tableaux triés (tri croissant). Ecrire un programme qui
fusionne T1 et T2 en un unique tableau T3 trié
int A[50]; //* tableau donné *//
int E; /* valeur à rechercher */ /* Déclarations */
int POS; /* position de la valeur */ int T1[50]; /* tableau 1 donné */
int N; //* dimension *//
i t T2[50];
int T2[50] /* ttableau
bl 2 donné
d é */
int i; /* indice courant */
int T3[100]; /* tableau de fusion */
/* … */
//* Saisie de la valeur à insérer et dans quelle position*/
position / int N1,N2,N3; /* dimensions */
printf("Valeur a insérer : "); int i,j,k; /* indices courants */
scanf("%d", &E );
do{{
printf("\n\nPosition d'insertion : "); St
Structure
t du
d programme
scanf("%d", &POS ); /* Déclarations */
} while(POS<0
( || POS>N);
) /* Saisie des données */
/* Insertion de E à la position POS */ /* Affichage des tableaux T1 et T2 */
for(i=N;i>POS;i--) /* Fusion des tableaux*/
A[i]=A[i-1]; /* Affichage du tableau T3*/
A[POS]=E;N++;
/* …*/
65 66

Fusion de deux tableaux triés (2/2) Tri d’un tableau


/* Déclarations */ ™ Soit A, un tableau de N éléments possédant une relation d'ordre total (ex.
int T1[50]; /* tableau 1 donné */
intt T2[50];
[50]; //* tableau
tab eau 2 donné
do é *//
entiers, réels, caractères). Trier A désigne l’opération de reclassement
int T3[100]; /* tableau de fusion */ d éléments
des élé t de
d A de d façon
f à ce qu’ils
’il soient
i t dans
d un ordre
d croissant
i t (ou
(
int N1,N2,N3; /* dimensions */ décroissant), c-à-d :
int i,j,k; /* indices courants */
/* … */ A[0] ≤ A[1] ≤ A[2] ≤ A[3] ≤ … ≤ A[N-1]
A[N 1] ou
/*insérer les éléments de T1 dans T3*/
for(i=0;i<N1;i++) A[0] ≥ A[1] ≥ A[2] ≥ A[3] ≥ … ≥ A[N-1]
T3[i] T1[i]
T3[i]=T1[i];
N3=N1;
/*insérer les éléments de T2 dans T3*/
j ;
j=0;
for(i=0;i<N2;i++)
™ Exemple
{ z Soit A, le tableau suivant :
while (T3[j]<T2[i])
{ j++; 8 4,
8, 4 19,
19 2,
2 7,
7 13,
13 5,
5 16
if (j==N3) break;
} z Après le tri croissant, A devient :
( ; j; ) /*insertion de l’élément courant de T2 dans T3*/
for(k=N3;k>j;k--)
T3[k]=T3[k-1]; 2, 4, 5, 7, 8, 13, 16, 19
T3[j]=T2[i];N3++;
}/* …*/ 67 68
Tri d’un tableau Tri par sélection : Principe

™ Les principales méthodes de tri se subdivisent en 3 classes ™ Soit un tableau de N éléments indicés de 0 à N-1. On suppose que les m
z Tri par sélection premiers éléments (0 à m-1) sont triés
z Tri à bulles
™ On cherche la position imin du plus petit élément parmi les éléments m à N-
z Tri par insertion 1. On le permute avec l’élément m. Le tableau se trouve donc trié de
l'indice 0 à l'indice m

™ On parcourt ainsi l'ensemble du tabelau de l’élément m=0 à l’élément N-2

™ Illustration
z En gras, les éléments déjà triés, en rouge, les éléments à permuter
18 10 3 25 9 2
2 10 3 25 9 18
2 3 10 25 9 18
2 3 9 25 10 18
2 3 9 10 25 18
2 3 9 10 18 25
69 70

Tri par sélection : Implémentation en langage C (1/2) Tri par sélection : Implémentation en langage C (2/2)

/* Déclarations */ int A[50]; /* tableau donné */


int A[50]; /* tableau donné */ int N; /* dimension */
i t N;
int N /* di
dimension
i */ i t j;
int j /* indice
i di courantt pour chercher
h h lle minimum
i i */
int j; /* indice courant pour chercher le minimum */ int i; /* indice courant pour parcourir le tableau */
int i; /* indice courant pour parcourir le tableau */ int AIDE; /* pour permuter deux valeurs*/
int AIDE; /* pour permuter deux valeurs*/ int imin; /* pour sauvegarder l'indice du minimum*/
int imin; /* pour sauvegarder l'indice du minimum*/
/*--------------- Tri ppar sélection---------------------------------*/
for (i=0; i<N-1; i++)
18 10 3 25 9 2
{ //recherche de l'indice du minimum
Structure du programme 2 10 3 25 9 18
imin=i;
imin i;
/* Déclarations */
for (j=i+1; j<N; j++) 2 3 10 25 9 18
/* Saisie des données */
/* Affichage du tableau T */ if (A[j]<A[imin]) 2 3 9 25 10 18
/* Tri par sélection*/
é */ imin=j; 2 3 9 10 25 18
/* Affichage du tableau trié*/ //permuter T[imin] avec T[i]
2 3 9 10 18 25
if (imin!=i)
{ AIDE
AIDE=A[imin];
A[i i ] A[imin]=A[i];
A[i i ] A[i] A[i]
A[i]=AIDE;}
AIDE }
}
71 72
Tri à bulles : Principe Tri à bulles : Implémentation en langage C (1/2)

™ Le principe consiste à parcourir les éléments de /* Déclarations */


18 10 3 25 9 2
l'ensemble de i=0 à N-1 en permutant les int A[50]; /* tableau donné */
10 18 3 25 9 2 int N; /* dimension */
élé
éléments
t consécutifs
é tif non ordonnés
d é
10 3 18 25 9 2 int i; /* indice courant pour parcourir le tableau */
™ L’élément le plus grand se trouve alors en bonne 10 3 18 25 9 2 int AIDE; /* pour permuter deux valeurs*/
int en_desordre;
en desordre; //* variable booléenne pour savoir si le tableau est trié ou non*/
non /
position.
iti O recommence la
On l procédure
éd pour 10 3 18 9 2
25 2
int dim; /*variable pour décrémenter la dimension du tableau*/
l'ensemble de i=0 à N-2 sauf si aucune 10 3 18 9 2 25
permutation n'a été nécessaire à l’étape 3 10 18 9 2 25
précédente 3 10 18 9 2 25
3 10 9 18 2 25 Structure du programme
™ Les éléments les plus grands se déplacent ainsi
3 10 9 2 18 25 / Déclarations *//
/*
comme des bulles vers la droite du tableau /* Saisie des données */
3 10 9 2 18 25
/* Affichage du tableau T */
™ Illustration 3 9 10 2 18 25
//* Tri à bulles*/
bulles /
z en rouge, les deux éléments à comparer 3 9 2 10 18 25 /* Affichage du tableau trié*/
z en gras, les éléments en bonne place 3 9 2 10 18 25
3 2 9 10 18 25
2 3 9 10 18 25
73 74

Tri à bulles : Implémentation en langage C (2/2) Tri par insertion : Principe

/* Déclarations */ ™ On prend 2 éléments et on les met dans l'ordre. On prend un troisième


18 10 3 25 9 2
int A[50]; /* tableau 1 donné */ élément qu'on insère dans les 2 éléments déjà triés, etc..
int N; /* dimension */ 10 18 3 25 9 2
int i; /* indice courant pour parcourir le tableau */ 10 3 18 25 9 2 ™ Un élément d’indice m va être inséré dans l'ensemble déjà trié des
int AIDE; /* pour permuter deux valeurs*/ 10 3 18 25 9 2 éléments 0 à m-1. Ce qui donnera m+1 éléments triés (0 à m)
int en_desordre;
en desordre; //* variable booléenne pour savoir si le tableau 10 3est18trié ou
9 non*/
non
2
25 /2
int dim; /*variable pour décrémenter la dimension du tableau*/ ™ L'insertion consiste à chercher l’élément de valeur immédiatement
10 3 18 9 2 25
/*--------------- Tri à bulles---------------------------------*/
3 10 18 9 2 25 supérieure ou égale à celle de l’élément à insérer. Soit k l'indice de cet
en desordre = 1; dim
en_desordre dim=N;
N;
élé
élément,t on décale
dé l lesl élé
élémentst k à m-1
1 vers k+1
k 1 à m ett l'onl' place
l
while(en_desordre) 3 10 18 9 2 25
{ l’élément à insérer en position k
3 10 9 18 2 25
en_desordre = 0;;
3 10 9 2 18 25 ™ C'est
C' t le
l plus
l rapide
id ett le
l plus
l utilisé
tili é pour un petit
tit nombre
b ded valeurs
l à trier
ti
for(i= 0 ; i < dim- 1 ; i++)
{ 3 10 9 2 18 25
18 10 3 25 9 2
(
if(A[i] > A[i+1])) 3 9 10 2 18 25 ™ Illustration
10 18 3 25 9 2
{ AIDE = A[i+1]; A[i+1] = A[i]; A[i] = AIDE; //Permutation
3 9 2 10 18 25 z En rouge, l‘élément à insérer dans la partie triée
en_desordre = 1; 3 10 18 25 9 2
3 9 2 10 18 25
} 3 10 18 25 9 2
3 2 9 10 18 25
} 3 9 10 18 25 2
2
dim--; //ce n’est pas la peine d’aller jusqu’à la fin du tableau 3 9 10 18 25
2 3 9 10 18 25
} 75 76
Tri par insertion : Implémentation en langage C (1/2) Tri par insertion : Implémentation en langage C (2/2)

/* Déclarations */ /* Déclarations */
int T[50]; /* tableau donné */ int A[50]; /* tableau donné */
i t N;
int N /* di
dimension
i */ int N; /* dimension */
int i,j,p; /* indices courants */
int i,j,p; /* indices courants */
int x; /* valeur à insérer */
int x; /* valeur à insérer */
/*--------------- Tri par insertion---------------------------------*/
Structure du programme
for (i = 1; i < N; i++)
i )
/* Déclarations */ {
/* Saisie des données */ x = A[i]; //valeur à insérer
/* Affichage du tableau T */ p = i-1;;
/* Tri par insertion*/ while (A[p] > x && p >= 0)
/* Affichage du tableau trié*/ { p--; } //recherche de l'indice d'insertion
p++;
for (j = i-1; j >= p; j--)
{
A[j+1] = A[j];
}
A[p] = x;
77 } 78

Tableaux à 2 dimensions et plus Exercice 1

™ Il s'agit d'un tableau de tableaux ™ Ecrire un programme C qui transfère une matrice M à deux dimensions L et
z Déclaration C (dimensions maximales : 10 lignes et 10 colonnes) dans un vecteur V à
– type nom_tableau[dim1][dim2]…[dimn]
une dimension
di i L*C

z Exemples ™ Exemple : abcd


– int T[2][2];
– int mat[6][10]; ef gh ==> (a b c d e f g h i j k l)
– char X[100][60][80];
[ ][ ][ ]; Indice 0 1 i j k l
z Initialisation
0 1 0 1 Structure du programme :
– int T[2][2]={{12,73},{48,59}}; Valeur
12 73 48 59 /* Déclarations
Dé l ti */
™ Accès aux éléments
/* Saisie des données */
z nom_tableau[ind1][ind2]…[indn]
z Exemples /* Affichage du tableau 2-dim */
– X[30][15][20] = 'c'; /* Transfert des éléments ligne par ligne */
– mat[5][6]
[ ][ ] =13;;
– printf("%d ", T[1][0]); // Affiche 48 /* Affichage du tableau 1-dim */

79 80
Correction Exercice 2
/* Déclarations */
int M[10][10]; /* tableau à 2 dimensions */ ™ Ecrire un programme qui effectue la transposition tA d'une matrice A de
int V[100]; /* tableau à 1 dimension */ dimensions L et C en une matrice de dimensions C et L
int L,L C; //* dimensions *//
int I, J,k=0; /* indices courants */ z La matrice transposée sera mémorisée dans une deuxième matrice B
/* Saisie des données */
z La matrice A sera transposée par permutation des éléments
printf("Nombre de lignes (max.10) : "); scanf("%d", &L );
printf("Nombre
printf( Nombre de colonnes (max (max.10)
10) : ");
); scanf(
scanf("%d"
%d , &C ); a e i
for (I=0; I<L; I++) a b c d
for (J=0; J<C; J++) b f j
{printf("M[%d][%d] : ",I,J); scanf("%d", &M[I][J]);} ™ Exemple
p e f g h ==>
/* Affichage
ff du tableau 2-dim */
printf("\nTableau origine :\n\n");
c g k
i j k l
for (I=0; I<L; I++)
{ for ((J=0; J<C; J++)) d h l
printf("\t%d", M[I][J]); St
Structure
t d programme
du
printf("\n");
/* Déclarations */
}
//* Transfert des éléments ligne par ligne *//
/* Saisie
S i i des
d données
d é */
for (I=0; I<L; I++)
for (J=0; J<C; J++) /* Affichage de la matrice */
{V[k] = M[I][J];k++;}
/* Affichage du tableau 1 1-dim
dim */ /* Transposition de la matrice A */
printf("\nTableau resultat : ");
for (I=0; I<L*C; I++) /* Affichage du résultat */
printf("%d ", V[I]); 81 82

Correction
/* Affectation de la matrice transposée à B */
for (I=0; I<L; I++)
for (J=0; J<C; J++)
B[J][I]=A[I][J];
/* Edition du résultat, L et C sont inversées */
printf("\nMatrice resultat :\n\n");
for (I
(I=0;
0; I<C; I++)
{ Chapitre 6
for (J=0; J<L; J++)
printf("%d", B[I][J]); LES POINTEURS
printf("\n");
}

/* Transposition de la matrice A par permutation des éléments [I][J] à gauche de la


diagonale principale avec les éléments [J][I] à droite de la diagonale*/
DMAX = (L>C) ? L : C;
for ((I=0; I<DMAX; I++))
for (J=0; J<I; J++)
{
AIDE = A[I][J];
A[I][J] = A[J][I];
A[J][I] = AIDE;
}
83 84
Définition et intérêts Déclaration & Initialisation (1/2)

™ Définition ™ Déclaration
z Un pointeur est une variable qui contient l’adresse d’une autre variable z Syntaxe : <type> *<identificateur_pointeur>
– lle pointeur
i t pointe
i t sur la
l variable
i bl z Exemple :
– le pointeur fait référence à la variable pointée int *p; // c’est un pointeur non initialisé du type entier
p A
™ Intérêts – Lors de la déclaration d’un pointeur d’un type donné, il ne pointe sur aucune
z Allouer de la mémoire dynamique, ce qui permet la gestion de structures de variable précise. On dit qu’il est un pointeur non initialisé
taille variable ((ex. tableau de taille variable))
™ Initialisation
I iti li ti
z Permettre le passage par référence pour des paramètres des fonctions
(chapitre 7) z Syntaxe : <identificateur_pointeur> = & <identificateur_variable>
z Exemplep :
z Réaliser des structures de données récursives (listes et arbres)
int A=2; int *p;
z ... p A
p = &A;
printf("\nA
printf( \nA :%d,
:%d Adresse de A:%x
A:%x", A,p);
A p);
// A : 2, Adresse de A : 22ff74
– Lors de l’initialisation,, le p
pointeur reçoit
ç l’adresse de la variable à p
pointer. Cela se
fait par le paramètre d’adressage (&)
– Un pointeur est toujours lié à un type de données. Il ne peut pas recevoir
85 l’adresse d’une variable de type différent 86

Déclaration & Initialisation (2/2) Exemples

™ Constante NULL ™ Exemple 1 p = NULL p=3F p=3F p=3F


z La constante NULL est la valeur standard pour un pointeur vide (ne pointe sur int i=10, j=50;
… … … …
rien) int *p = NULL;
j =50 | 4F j =50 j =10 j =10
z Exemple : int *p = NULL; p=&i;
i =10
10 | 3F i =10 i =10 i =12
™ Opérateurs & et * j = *p;
*
z L’opérateur <*> désigne le contenu de la variable adressée/pointée *p = j+2; a b c d
z L’opérateur
L opérateur <&> est un opérateur unair qui fournit ll’adresse
adresse de son opérande ™ Exemple 2
z Exemples : float a , *p; /*supposons que ces variables sont représentées en mémoire à partir
int *p = NULL; Adresse Valeur de l’adresse 01BF*/
int i=3;
i 3; F33 i=3 p = &a;
printf("Entrer une valeur :");
p = &i; // mettre l’adresse de i dans p Adresse Valeur scanf("%f",p); // on saisie la valeur 1.4
p F33 i=3 printf("\nAdresse
i tf("\ Ad d a = %x
de % Contenu
C t d a = %f",p,*p);
de %f" * )
*p += 0.4;
*p = 5; //modifier la valeur de la variable pointée par p
printf("\na = %f *p = %f ", a,*p);
Adresse Valeur
p F33 i=5 Adresse de a = 01BF Contenu de a= 1.400000

87
a=1.800000 *p=1.800000 88
Exercice Opérations sur les pointeurs

Trouvez les erreurs dans les suites d’instructions suivantes : ™ Exemple

a)) int
i t *p
* , x = 34;
34 *p
* = x; t
type x,y, *px,
* *
*py;
*p = x est incorrect parce que le pointeur p n’est pas initialisé
px= &x, py=&y; px x py y

b) double *q; int x = 17 , *p = &x; q = p; Les expressions suivantes sont équivalentes :


q = p est incorrect. q et p deux pointeurs sur des types différents Exp1 Exp2
y = *px+1 y = x+1
c) int x, *p; &x = p;
&x = p incorrect. &x n’est pas une variable qui peut figurer à gauche d’une *px= *px+2 x = x+2
affectation px /=3
*px x /=3
(*px)++ x++
((*px)--
px) xx--
px-py nombre d’octets entre les 2 adresses
px==py
p py p
comparaison d’adresses
px = py px et py pointent sur la même donnée
89 90

Pointeurs et tableaux 1D Exercice

™ Un tableau est une zone de mémoire référencée par l’adresse de son premier ™ Ecrire un programme qui vérifie si un tableau de caractères CH est un palindrome
élément qui peut être désigné par un pointeur en utilisant des pointeurs au lieu des indices numériques
z Le nom T du
L d ttableau
bl estt un pointeur
i t constant
t t sur le
l premier
i élé
élémentt d
du ttableau
bl z U palindrome
Un li d estt un mott quii reste
t lle même
ê qu'on
' lle lilise d
de gauche
h àd
droite
it ou d
de d
droite
it
z T et &T[0] contiennent l’adresse du premier élément du tableau à gauche :
T==&T[0] Exemples : PIERRE ==> n'est pas un palindrome
™ Exemple
p 0 1 2 3 ….
z

z int *p, T[10]; p 9 8 10 6 …. OTTO==> est un palindrome


z p = T //équivalent à p = &T[0]
E
Expression
i E
Exp2
i 2ti
Désignation
Dé /* Déclarations */
*(p+i) contenu de la case T[i] char CH[101]; /* chaîne donnée */
char *P1,*P2; /* pointeurs d'aide */
(p+i) adresse de la case T[i] (&T[i])
int PAL; /* indicateur logique vrai si CH est un palindrome */
p = &T[i] p pointe sur le ième élément du tableau
p++
p p pointe sur l’élément T[i+1] du tableau
Structure du programme
p+=n p pointe sur l’élément T[i+1+n] du tableau
/* Saisie des données */
T+i Adresse du ième élément du tableau T
//* Contrôler si CH est un palindrome *//
*(T+i) contenu de la case T[i] /* Affichage du résultat */
T=p Erreur! T est un pointeur constant
91 92
Correction Pointeurs et tableaux 2D (1/2)

/* Saisie des données */ ™ Cas d’une matrice T[L][C] : Tableau de tableaux


printf("Entrez une ligne de texte (max.100 caracteres) :\n"); z Le nom T est un pointeur constant sur le premier tableau
gets(CH); z T[i] est un pointeur constant sur le premier élément du ième
è tableau
/* Placer P2 sur la dernière lettre de la chaîne */ z T et T[0] contiennent la même adresse mais leur manipulation n’est pas la même
for (P2=CH; *P2; P2++) puisqu’ils ne représentent pas le même type de pointeur
; T[0] &T[0][0]
T[0]==&T[0][0] T[i] &T[i][0]
T[i]==&T[i][0]
P2--; 0 1 i …

//* Contrôler si CH est un palindrome *// …


0 1 … 0 1 … 0 1 …
PAL=1; T
12 3 15 6
for (P1=CH ; PAL && P1<P2 ; P1++,P2--)
iff (*P1
(* != **P2)) PAL=0;
/* Affichage du résultat */
™ Exemple
if (PAL)
z int *p
p, T[10][10];
printf("\nLa chaine \"%s\" est un palindrome.\n", CH);
z p = T[0] //équivalent à p = &T[0][0]
else
printf("\nLa
printf( \nLa chaine \\"%s\"
%s\ nn'est
est pas un palindrome
palindrome.\n
\n", CH);

93 94

Pointeurs et tableaux 2D (2/2) Exercice


int T[L][C]; //matrice de L lignes et C colonnes
p 0 12 ™ Ecrire un programme qui lit 4 suites d'une longueur égale à 4 et les mémorise dans
int *p; p= T[0]; //équivalent à ( p = &T[0][0]) une matrice Suites. Inverser l'ordre des chiffres à l'intérieur des 4 suites à l'aide de
0 1 3
deux pointeurs P1 et P2
P2. Afficher les suites inversées
Expression Désignation
Exp2 p+1 …
*p contenu de la case T[0][0] C-1 9
p+1
+1 pointe sur T[0][1]
0 15
*(p+1) contenu de la case T[0][1]
p+C
1 6 /* Déclarations */
1
p+C pointe sur T[1][0] … i t Suites[4][4];
int S it [4][4] /* matrice
t i d'entiers
d' ti */
p+C+1 pointe sur T[1][1] C-1 8
int AIDE; /* pour la permutation des chiffres*/
T[i][j] *(p+i*C+j) (i dans [0,L-1] , j dans [0,C-1]) …
int *P1, *P2; /* pointeurs d'aide */
0 1 .. j .. C-1 0 10
i int i,j; /* indices courants */
0 12 3 .. .. .. 9 1 13
1 /* Structure du programme */
15 6 .. .. .. 8 j 4
p+i*C+j
.. .. .. .. .. .. .. C-1 99 /* Saisie des données */
T=
T i 10 13 .. 4 .. 99 … /* Inverser l'ordre des chiffres à l'intérieur des suites */
.. .. .. .. .. .. .. L-1
/* Affichage des suites inversées */
L-1 .. .. .. .. .. .. 95 96
Correction Déclarations supplémentaires de pointeurs
/* Saisie des données */ /* Inverser l'ordre des chiffres de chaque suite */
™ Tableau de pointeurs
printf("Entrez 4 suites \n"); for (i=0; i<4; i++)
z Syntaxe = <type> *identificateur_tableau [taille]
for (i=0; i<4; i++) { P1 = P2 = Suites[i];
– Déclare un tableau de [taille] pointeurs de type <type>
{ P2+=3; /* Placer P2 à la fin de la suite */
– Exemple
printf("\nsuite %d (max.4 chiffres) : ", i); while (P1<P2)
char
c a *p[30];
p[30]; // tableau
ab eau de 30 po
pointeurs
eu s de type
ype cchar
a
for(j=0;j<4;j++) {
scanf("%d",(Suites[i]+j)); AIDE = *P1;
™ Pointeur de tableaux
} *P1 = *P2; • Syntaxe = <type> (*identificateur_pointeur) [taille]
/*Affichage de la matrice*/ *P2 = AIDE; – Déclare un pointeur identificateur_pointeur sur des tableaux de [taille]
éléments de type <type>
for (i=0; i<4; i++) P1++; P2--;
– Exemple
{ }
int (*p)[30] ; // pointeur sur des tableaux de 30 éléments de type int
for(j=0;j<4;j++) }
printf("%d\t", *(Suites[i]+j)); /* Affichage des suites inversées */
™ Pointeur de pointeurs
printf("\n"); for (i=0; i<4; i++) • Syntaxe = <type> **identificateur
identificateur_pointeur
pointeur
} { for (j=0;j<4;j++) – Déclare un pointeur identificateur_pointeur qui pointe sur des pointeurs de type
<type>
printf("%d\t", *(Suites[i]+j));
– Exemple
E l
printf("\n");
int **p ; // pointeur sur des pointeurs de type int
}
97 98

Allocation de mémoire Allocation avec initialisation à 0

™ L’allocation de la mémoire pour un pointeur peut se faire ™ La fonction calloc permet d'allouer une zone mémoire dont tous les
• En transmettant l’adresse d’une variable (p=&a); éléments seront initialisés à 0
• En allouant un espace mémoire à l’aide de la fonction « malloc » qui se trouve dans la ™ Syntaxe
librairie <stdlib.h> : Allocation dynamique
<identificateur_pointeur> = (type *)calloc(nb_elements, sizeof(type));
™ Syntaxe : <identificateur_pointeur> = (type *)malloc(sizeof(type));
• De manière similaire à malloc, calloc retourne un pointeur pointant une zone de
<identificateur_pointeur> = (type *)malloc(constante); nb_element * sizeof(type) octets allouée en mémoire, dont tous les bits seront initialisés à
0 ou retourne un pointeur nul en cas d
0, d’echec
echec
• La fonction « malloc » prend une zone d’une taille donnée (sizeof(type)) dans l’espace ™ Exemple
mémoire libre réservé au programme et affecte l’adresse du début de la zone au pointeur int *p,i;
• S’il n’y a pas assez d’espace, la fonction retourne le pointeur NULL p = (int*) calloc (5, sizeof(int)); // Allocation de 20 octets initialisés à 0 et affecter
l’adresse du début à p;
for (i=0;i<5;i++)
™ Exemple
printf("\nEntier : %d ADRESSE: %x",*(p+i),p+i);
char *c;
c = (char*) malloc(20); // Allocation de 20 octets et affecter l’adresse du début à c;

99 100
Modification de zone allouée Modification de zone allouée : Exemple

™ Il arrive fréquemment qu'un bloc alloué n'ait pas la taille suffisante pour int *ptr = (int*)malloc(10 * sizeof(int));
accueillir de nouvelles données. La fonction realloc est utilisée pour if (ptr != NULL)
changer
h (
(agrandir
di ou réduire)
éd i ) la
l taille
t ill d'une
d' zone allouée
ll é par malloc,
ll calloc,
ll { /* ... */
ou realloc /* On se rend compte qu'on a besoin d'un peu plus de place. */
™ Syntaxe int *tmp
tmp = (int
(int*)) realloc(ptr,
realloc(ptr 20 * sizeof(int));
<identificateur_pointeur> = (type *)realloc(ancien_pointeur,nouvelle_taille); if (tmp != NULL)
{
• realloc tentera de réajuster la taille du bloc pointé par ancien_pointeur à la ptr = tmp;
nouvelle_taille spécifiée
/* On continue */
• En cas de succès,, realloc alloue un espace
p mémoire de taille nouvelle_taille,,
}
copie le contenu pointé par ancien_pointeur dans ce nouvel espace (en
tronquant éventuellement si la nouvelle taille est inférieure à la précédente), }
puis libère l'espace pointé par ancien_pointeur et retourne un pointeur vers la
nouvelle zone mémoire
• Cas de : ptr = (int*)realloc(ptr, 20 * sizeof(int));
• En cas d'échec, cette fonction ne libère pas l'espace mémoire actuel, et
retourne une adresse nulle • si realloc échoue, la valeur de ptr est alors nulle, et on aura perdu la
• Si nouvelle_taille vaut zéro, l'appel est équivalent à free(ancien_pointeur) référence vers l'espace de taille 10 * sizeof(int) qu'on a déjà alloué.
Ce type d'erreur s'appelle une fuite mémoire
• Si ancien_pointeur est nul, l'appel est équivalent à malloc(nouvelle_taille) 101 102

Libération de mémoire Exercice 1

™ La fonction « free » permet de libérer l’espace mémoire alloué dynamiquement au ™ Saisir un texte. Ranger les caractères en mémoire en utilisant un pointeur. Lire le
pointeur contenu de la mémoire en utilisant le même pointeur et y compter le nombre
d'espaces
d espaces et de lettres ‘e’
e

• Syntaxe : free(<identificateur_pointeur>); /*Déclarations*/


char *adr_deb; // Adresse mémoire de rangement des caractères
<identificateur_p
pointeur>=NULL;; //pour
p éviter les erreurs char c; //Caractère lu
int i,imax; //Indices courants
int compt_e = 0,compt_esp = 0; //Compteurs
• Exemple
/ Structure du programme *//
/*Structure
char *c; /* Saisie et rangement du texte en utilisant un pointeur */
c = (char*) malloc(20); /* Lecture et affichage des adresses des caractères lus en comptant les 'e' et les ' ' */
/* Affichage des résultats */
….
free(c);
c=NULL;

103 104
Correction Exercice 2
char *adr_deb,c;
int i,imax,compt_e = 0,compt_esp = 0;
™ Écrire un programme qui remplit un tableau dynamique d’entiers à 2
dimensions (3,3)
adr_deb = (char*) malloc(30);/* texte d'au plus 30 caractères */
/*Déclarations*/
/* Saisie et rangement du texte */
printf("\n
printf( \n ADRESSE DU TEXTE: %x (ATTRIBUEE PAR LE COMPILATEUR)
COMPILATEUR)",adr_deb);
adr deb);
int L=3, C=3; //dimensions de la matrice
printf("\n ENTRER UN TEXTE: "); int **M; //matrice dynamique
for (i=0;((c=getchar())!='\n');i++) int i,j; //Indices courants
*(adr_deb + i) = c;
imax = i;/* borne superieure */ /*Structure
/*St t d programme */
du
/*Allocation de la mémoire*/
/* Lecture de la mémoire pour compter les 'e' et les ' ' */
for (i
(i=0;i<imax;i++)
0;i<imax;i++)
/* Saisie et rangement des éléments de la matrice */
{ /* Affichage de la matrice lue */
c = *(adr_deb+i);
printf("\nCARACTERE: %c ADRESSE: %x",c,adr_deb+i);
if (c=='e')
( ' ') compt_e++;
if (c==' ') compt_esp++;
}

/* Affichage du résultat */
printf("\nNOMBRE DE e: %d \nNOMBRE d'espaces: %d\n",compt_e,compt_esp);
free(adr_deb); 105 106

Correction

int L=3, C=3,i,j;


int **M;
M = (int**)malloc(L
(i t**) ll (L * sizeof(int*));
i f(i t*))
for (i = 0; i < L; i++)
M[i] = (int*)malloc(C * sizeof(int)); //*(M+i) = (int*)malloc(C * sizeof(int));
for (i = 0; i < L; i++) Chapitre 7
for (j = 0; j < C; j++)
{p
{printf("\nM[%d][%d]:",i,j);
( [ ][ ] , ,j); LES FONCTIONS
scanf("%d",M[i]+j); // scanf("%d",&M[i][j]);
}
printf("\n-----------------Affichage
printf( \n Affichage Matrice
Matrice------------\n");
\n );
for (i = 0; i < L; i++)
{ for (j = 0; j < C; j++)
printf("%d\t"
printf( %d\t ,*(M[i]+j));
(M[i]+j)); //printf(
//printf("%d\t"
%d\t ,M[i][j]);
M[i][j]);
printf("\n");
}
f (i = 0;
for 0 i < L;
L i++)
i )
free(M[i]);
free(M); 107 108
Introduction Fonctions : Définition, Déclaration & Appel

™ Une fonction ou procédure ou encore sous programme est une suite ™ Définition
d'instructions élémentaires qui représente une seule action. Elle est la Type_arg_ret nom_fonction( type arg1, type arg2, …type argn)
b
base d langages
des l structurés
t t é {
instructions; Avec valeur de retour
™ Réalisation d'un algorithme : décomposition en une suite de fonctions return…;
simples
i l pouvantt réaliser
é li une ou plusieurs
l i f
fonctions
ti b
beaucoup plus
l }
compliquées OU
void nom_fonction( type arg1, type arg2, …type argn)
™ Une
U fonction
f ti estt caractérisée
té i é par un appell ett un retour
t : {
z L'appel est effectué par le programme principal main() ou une autre procédure instructions;
return…; Sans valeur de retour
z Le retour s
s'effectue
effectue après la dernière action de la fonction appelée
}

™ Déclaration (Prototype d’une fonction)


Type arg ret nom_fonction(
Type_arg_ret nom fonction( type arg1,
arg1 type arg2,
arg2 …type
type argn);

™ Appel d’une fonction


Type arg ret <Nom_Variable>
Type_arg_ret <Nom Variable>= nom_fonction(
nom fonction( Param1, Param2, …Param
Paramn);
nom_fonction( Param1, Param2, …Paramn); //Fonction sans valeur de retour

109 110

Fonctions : Définition, Déclaration & Appel Fonctions : Règles d'utilisation

™ Exemple ™ Une fonction ne peut pas fournir comme résultat des tableaux, des chaînes
int min(int a, int b); Prototype de de caractères ou des fonctions, mais il est cependant possible de renvoyer
la fonction un pointeur
i t sur le
l premier
i élé
élément t d’un
d’ t bl
tableau ou d’une
d’ chaîne
h î d
de
main() min
caractères
{ int x,y;
scanf(''%d
scanf( %d %d '', &x,&y);
&x &y);
™ Si une fonction
f ti n’a
’ pas ded paramètres,
èt on peutt déclarer
dé l l liste
la li t des
d
printf ('' %d '',min(x,y));
} Programme paramètres comme (void) ou simplement comme ()
principal
p p z ex : int main(){...}
(){ } // équivalent
q à int main(void){...}
( ){ }

int min(int a, int b) ™ Il est interdit de définir des fonctions à l’intérieur d’une autre fonction
{ Définition de ((comme en Pascal))
if (a <b) return a; la fonction
else return b; min ™ En principe, l’ordre des définitions de fonctions dans le texte du programme
}
ne jjoue ppas de rôle,, mais chaque
q fonction doit être déclarée ou définie
avant d’être appelée : L'appel d'une fonction doit être situé après sa
définition ou son prototype

™ L'ordre, le type et le nombre des arguments doivent être respectés lors de


l'appel de la fonction
111 112
Exercice Correction

™ Ecrire une fonction Premier ayant en argument un entier et qui renvoie par int Premier(int x) main()
un return un booléen : 1 si l'entier est premier 0 sinon. Tester cette fonction { {
int r=1, d=2; int a, N;
™ Ecrire une fonction NPremier ayant comme paramètre un entier N et qui while(r && d*d<=x) printf("Tapez a :"); scanf("%d",&a);
renvoie le N-ième nombre premier. Tester cette fonction if(x%d==0) r=0; if(Premier(a))
else d++; printf("%d est premier",x);
return r; else
} printf("%d
p ( %d n es
est pas ppremier",x);
e e , );
printf("\nTapez la valeur de N :");
int Npremier(int N) scanf("%d",&N);
{ printf("\n
printf( \n le %d eme nombre premier est
int nb=0, i=2; : %d", N,Npremier(N));
while(nb!=N) }
{
if(Premier(i)) nb++;
i++;
}
return i-1;
113 } 114

Portée (visibilité) des variables Exemple


int a; int a, b;
main() main()
{ {
int a = 1, b = 2; a++, b++; int a = 1, b = 2;
{
a++, b++;
char b = 'A';
A; a a++,, b
b++;;
} printf("\n1er
i tf("\ 1 bl bloc a : %d\tb : %d",a,b);
%d" b)
} {
char b = 'A';
™ Selon l’endroit où l’on déclare une variable, celle-ci pourra être accessible (visible) a++, b++;
partout dans le code ou seulement dans une partie de celui-ci (à l’intérieur d’une printf("\n2eme bloc a : %d\tb : %c",a,b);
fonction (ou d’un bloc d’instructions)), on parle de la portée ou visibilité de la {
variable
i bl
int a = 100;
z Lorsqu’une variable est déclarée dans le code même, c’est-`a-dire à l’extérieur de toute
a++, b++;
fonction ou de tout bloc d d’instructions
instructions, elle est accessible de partout dans le code printf("\n3eme
printf( \n3eme bloc a : %d\tb : %c
%c",a,b);
a b);
(n’importe quelle fonction du programme peut faire appel à cette variable). On parle alors
de variable globale }
}
z Lorsque l’on déclare une variable à l’intérieur d’une fonction ou d’un bloc d’instructions
(entre des accolades), sa portée se limite à l’intérieur du bloc dans lequel elle est
déclarée. On parle de variable locale 115
} 116
Durée de vie des variables Portée (visibilité) et durée de vie (1/3)
void Fonction()
{ ™variable globale : variable déclarée en dehors des fonctions
int nbrAppel= 0; /*………….*/
nbrAppel++;
(variable par défaut statique)
}
int n;
™ La durée de vie d
d'une
une variable est le temps pendant lequel cette variable a une
void
id fonction
f ti ();
()
existence en mémoire. En C 3 catégories de variables :
void fonction ()
z variables statiques (permanentes) : occupent un espace mémoire durant toute l'exécution
du programme (segment de données).
données) Elles sont initialisées à zéro par le compilateur et {
elles sont caractérisées par le mot-clef static n++;
z variables automatiques (temporaires) : se voient allouer un espace mémoire de façon printf("appel numero %d\n",n);
d
dynamique
i (
(segmentt de il ) Elles
d pile). Ell ne sontt pas initialisées.
i iti li é L
Leur espace mémoire
é i estt }
libéré à la fin d'exécution de la fonction secondaire et elles sont caractérisées par le mot-
clef auto main() n est initialisée à 0 par le compilateur
pp numero 1
appel
variables dynamiques : allouées et libérées explicitement par le programmeur, à l'aide des {
z
appel numero 2
fonctions malloc (calloc / realloc) et free int i; appel numero 3
for ((i = 0; i < 5; i++)) appel numero 4
, - En l'absence des mots clés static et auto, la variable sera prise par défaut de fonction(); appel numero 5
type automatique
- Une variable globale est par défaut static 117
} 118

Portée (visibilité) et durée de vie (2/3) Portée (visibilité) et durée de vie (3/3)

™ Variable locale : variable déclarée à l'intérieur d'une fonction (ou d'un bloc void fonction ();
d'instructions) (variable par défaut temporaire) void fonction ()
{
static int n;
int n = 10; n++;
void fonction (); printf("appel
printf( appel numero %d\n
%d\n",n);
n);
void fonction () }
{ main()
i t n = 0;
int 0 { n est initialisée à 0 par le compilateur
int i; appel numero 1
n++;
for (i = 0; i < 5; i++) appel numero 2
printf("appel numero %d\n",n); appel numero 3
} fonction(); appel numero 4
main() } appel numero 5
n est initialisée à 0 par le compilateur
{ appel numero 1
int i; appel numero 1
appel numero 1 ™ Il est possible de déclarer une variable locale de classe statique qui reste
for (i = 0; i < 5; i++)
appel numero 1 locale
oca e à u
unee fonction
o ct o mais
a s sa valeur
a eu est co
conservée
se ée dd'un
u appe
appel au su
suivant
a t
fonction();
appel numero 1
}
119 120
Exercice Correction

™ Déterminer le maximum d'un tableau T de N entiers de trois façons différentes : #define N 10 /*Fonction qui retourne l'adresse du
/*Fonction qui retourne la valeur du maximum*/
z l ffonction
la ti MAX1(i
MAX1(intt Tab[N])
T b[N]) retourne
t lla valeur
l maximale
i l maximum*//
maximum int MAX3(int Tab[N])
int*
z la fonction MAX2(int Tab[N]) retourne l'indice de l'élément maximal
int MAX1(int Tab[N]) {
{ int *max=NULL,i;
z la fonction MAX3 (int Tab[N]) retourne l'adresse de l'élément maximal
int max
max=Tab[0],i;
Tab[0],i; max=Tab;//OU
max Tab;//OU max
max=&Tab[0];
&Tab[0];
z la fonction Echange(int Tab[N]) échange le maximum avec le premier élément du tableau for(i=0;i<N;i++) for(i=0;i<N;i++)
if(Tab[i]>max) max=Tab[i]; if(Tab[i]>*max) max=&Tab[i];
return max;; return max;;
Exemple d’exécution } }
/*Fonction Echange*/
/*Fonction qui retourne l'indice du void Echange(int Tab[N])
maximum*/ {
int MAX2(int Tab[N]) int temp;
{ int imax = MAX2(Tab);
int i=0,ind=0; temp=Tab[0];
for(i=1;i<N;i++) Tab[0]=Tab[imax];
if(Tab[ind]<Tab[i]) Tab[imax]=temp;
i d i
ind=i; }
return ind;
121
} 122

Appel d’une fonction Appel d’une fonction : Exemple

int Premier(int x)
Type_retour fonction(Type1 arg1 , Type2 arg2,…)
{
{ //* ...*// int r=1, d=2;
return resultat ; while(r && d*d<=x)
} if(x%d==0) r=0;
else d++;
main () return r;
{ /* …………….. */ }
Type_retour Val = fonction(parametre1, parametre2,…);
main()
/* appel de la fonction avec les paramètres nécessaires
{
ici : parametre1 et parametre2 */ int a, N;
printf("Tapez a :"); scanf("%d",&a);
if(Premier(a))
/* …………….. */
printf("%d est premier",x);
else
} /* fi
fin d
du bl
bloc main
i */ printf("%d
i tf("%d n estt pas premier",x);
i " )
}
123 124
Fonctions : passage d’arguments par valeur Fonctions : passage d’arguments par adresse
void permutter(int *pa, int *pb)
void permutter(int a, int b) {
{ int temp;
p;
int temp; temp = *pa;
pa; *pa
pa = *pb;
pb; *pb=
pb= temp; Action sur les p
paramètres
temp = a; a = b; b= temp; Aucune action
A i sur lles x et y
}
} paramètres x et y
main() main()
{ { x=3
x 3
x=3
3 int x=3; int y =5;
int x=3, y =5;
y=5
y=5
printf("Avant :\nx=%d\ty=%d ",x,y); printf("Avant :\nx=%d\ty=%d ",x,y);
*(&x)=3
(&x)=3 *(&x)=5
(&x)=5
a=3 a=5 permutter(&x,&y);
permutter(x,y); *(&y)=5 *(&y)=3
b=5 b=3
printf("\nApres
printf( \nApres :\nx=%d\ty=%d ",x,y);
x y); x=5
x 5
printf("\nApres :\nx=%d\ty=%d ",x,y); x=3
3 a=5 Variables
} temporaires } y=3
y=5 b=3
™ Passage d’arguments
d arguments par valeur ™ Passage d
d'arguments
arguments par adresse
z Recopie en mémoire des paramètres dans des paramètres temporaires z On passe non pas la valeur de la variable mais son adresse
– Toute modification des paramètres dans la fonction est sans effet sur les paramètres z Il est possible par les pointeurs de modifier le contenu de l'adresse, donc la
initiales variable
i bl initiale
i iti l
– Quand on quitte la fonction, les paramètres temporaires sont effacés de la mémoire z Permet de modifier plusieurs arguments à la fois dans une fonction
125 126

Exercice 1 Tableau à 1D comme paramètre (1/2)

™ Donner la séquence des affichages produits par l'exécution du programme suivant : ™ Le nom du tableau représente en fait l'adresse du tableau . Si nous voulons modifier un
élément du tableau, il suffit de transmettre en paramètre le nom du tableau
int f1 ( int n ) { printf("%d\n",n
p ( , == 0 ); return n;}
;} (éventuellement la taille)
int f2 ( int n ) { printf("%d\n",n = 0 ); return n;}
™ Dans la liste des paramètres d’une fonction, on peut déclarer un tableau par le nom suivi
void f3 ( int *n ) { *n = *n + 1; } de crochets : <type> <nom>[ ]

int f4 ( int *n ) { (*n)++ ; return *n ; } ™ ou simplement par un pointeur sur le type des éléments du tableau : <type> *<nom>

()
main() ™ Exemple
p :
{ void initialisation (int T[ ], int Taille)
{ int i;
int a =1, b = 2;
f (i=
for (i 0 ; i < Taille
T ill ; i++)
i )
a = f1( a ) ; b = f2( 1 ) ; T[i]=1;
( = %d , b = %d\n", a , b ));
printf("a } OU
main() main()
f3( &a ) ; b = f4( &a ) ; { const int N = 10;
{ int tab[10]; int *tab;
printf("a = %d , b = %d\n ", a , b );
initialisation(tab 10);
initialisation(tab,10); t b = (int*)malloc(N
tab (i t*) ll (N * sizeof(int));
i f(i t))
} } initialisation(tab,N);
}
127 128
Tableau à 1D comme paramètre (2/2) Exercice 1

™ Quand une fonction admet un paramètre de type tableau, il y a deux cas ™ Ecrire une fonction, nommée VerifierRelationR, qui retourne 1 si le tableau d’entiers
possibles : T reçu en paramètre vérifie la relation (R), 0 sinon. Les paramètres de la fonction
sont le tableau T et sa taille N

z soit les différents tableaux qui lui sont passés en paramètre effectif ont des ™ Un tableau T vérifie la relation (R) si chaque élément de T sauf le premier est la
tailles différentes, et dans ce cas la taille doit être un paramètre supplémentaire somme d d’un
un certain nombre d d’éléments
éléments consécutifs qui le précèdent
de la fonction immédiatement, c’est-à-dire :
void initialisation (int tab[ ], int N){…}
™ Soit k tel que 1 <= k <= N -1, il existe i , 0 <=i <= k -1 tel que

T[k] = T[k -1] + ... + T[i +1] + T[i] (R)

z soit les différents tableaux q


qui lui sont p
passés en p
paramètre effectif ont tous la
même taille, et dans ce cas la taille peut apparaître dans le type du paramètre 0 1 2 3 4 5 6 7 8
effectif : ™ Ex : si T = 2 2 4 6 10 24 34 34 68

#define N 10 ™ alors T vérifier la relation (R). En effet :

void initialisation (int tab[N]){…} ™ T[1]=T[0] ; T[2]=T[1]+T[0] ; T[3]=T[2]+T[1] ; T[4]=T[3]+T[2] ;

™ T[5]= T[4]+T[3]+T[2]+T[1]+T[0] ; T[6]=T[5]+T[4] ; T[7]=T[6] ; T[8]=T[7]+T[6] ;

129 130

Correction Exercice 2 : Décomposition d’un entier en facteurs premiers

int VerifierRelationR (int T[ ] , int N) ™ Ecrire une fonction void decompose(int facteur[ ], int N, int *taille) qui construit le
{ tableau des facteurs premiers de l’entier N
int i,k,som; ™ Ecrire un programme C qui fait appel à la fonction decompose
for(k=1;k<N;k++)
™ Modifier la fonction decompose par une nouvelle fonction decompose_ptr déclarée
{
comme suit : void decompose_ptr(int *facteur, int N, int *taille);
som=0;
for(i=k-1;i>=0;i--) ™ Exemple :
{ ™ N = 18 = 2*3*3 facteur = 2 3 3
som+=T[i];
On donne :
if (som==T[k])
( T[k]) break;
b k
//retourne 1 si x est premier et 0 sinon
if(som>T[k])return 0; int Premier(int x)
if(i==0
( && som<T[k])
[ ]) return 0;; { int r=1, d=2;
} while(r && d*d<=x)
if(x%d==0) r=0;
} else d++;
return 1;
1 return r;
} }
131 132
Correction (1/3) Correction (2/3)
int Premier(int x) void Affiche(int T[ ], int L) void decompose_ptr (int *facteur, int N, int *taille) main()
{ int r=1, d=2; { { {
while(r && d
d*d<=x)
d<=x) int i; int i,k=0;
i k=0; int L,
L N;
if(x%d==0) r=0; printf("\n TABLEAU DE DECOMPOSITION \n "); for(i=2;i<=N;i++) int *P;
else d++; for (i=0; i<L; i++) if((N%i)==0 && Premier(i)) printf("NOMBRE A DECMPOSER :");
return r; printff ("%d\t",T[i]);
(% \ ) { scanf("%d",
f( % &N);
& )
} } *(facteur+k)=i; P=(int*) malloc (20*sizeof(int));
void decompose(int facteur[ ], int N, int *taille) main() k++; decompose_ptr(P,N,&L);
{ int i,k=0; { N=N/i; Affiche(P, L);
for(i=2;i<=N;i++) int T[100], L, N; i--; free(P);
if((N%i)==0 && Premier(i)) printf("NOMBRE
printf( NOMBRE A DECMPOSER :");
: ); } }
{ facteur[k]=i; k++; scanf("%d", &N); *taille=k;
N=N/i; i--; decompose(T,N,&L); }
} Affi h (T L);
Affiche(T, L)
*taille=k; }
}

133 134

Correction (2/3) : Allocation dans la fonction decompose_ptr Correction (2/3) : Allocation dans la fonction decompose-ptr

void decompose_ptr(int **facteur, int N, int *taille) main() ™ Dans la fonction Decompose_ptr, si on déclare facteur comme int*, lors de
{ int i,k=0,*temp; { l'exécution du main, un pointeur va être alloué (C'est surtout une réservation) avec
*facteur=(int*)
facteur=(int ) malloc (sizeof(int)); int L,
L N; l’instruction int *P
for(i=2;i<=N;i++) int *P; ™ Puis on appelle Decompose_ptr en lui passant ce pointeur P
if((N%i)==0 && Premier(i)) printf("NOMBRE A DECMPOSER :"); decompose_ptr(P,N,&L);. En fait, on passes une copie de ce pointeur non
initialisé c
initialisé, c-à-d
à d on lui passe une adresse invalide en entrée
{ temp=(int*) realloc (*facteur,(k+1)*sizeof(int)); scanf("%d",
f( % &N);
& )
if (temp) decompose_ptr(&P,N,&L); ™ Dans Decompose_ptr, on affecte à la copie du pointeur une nouvelle adresse de
la zone allouée avec malloc (realloc). En sortie de fonction, la copie est
{ Affiche(P, L);
supprimée , et on perd ll'adresse
"supprimée" adresse et le contenu du tableau créé par facteur.
facteur Et
*facteur = temp; } quand ensuite on veut afficher le tableau facteur dans le main, on aura des valeurs
(*facteur)[k]=i; invalides, c-à-d le contenu de l’adresse qui n'a pas été initialisée. Passée par
k++; valeur (copie) à la fonction Decompse
Decompse-ptrptr, elle n
n'a
a pas changée de valeur depuis
N=N/i; le début du main
i--; ™ Il faut que l’on passe l'adresse du pointeur dans le main. Il faut que la fonction
} Decompose ptr prenne en argument un int
Decompose_ptr int**. Dans le main,
main on passeras non pas
else printf("erreur d'allocation");
le pointeur, mais son adresse (&P) decompose_ptr(&P,N,&L);. Et lors de
l'affectation à partir de malloc (realloc) et de la manipulation, il faudra référencer le
}
pointeur ((*facteur)
facteur)
*taille=k;
}
135 136
Tableau à 2D comme paramètre Exercice

™ Lorsque l'on passe un tableau à plusieurs dimensions en argument à une fonction, ™ Ecrire une fonction, nommée EstTriangulaireSuperieure, qui retourne 1 si la matrice
le nombre de lignes est sans importance car on passe en réalité son adresse. Par carrée d’entiers A (de 30 colonnes au maximum) reçue en paramètre est
contre la fonction doit connaître les autres dimensions pour connaître ll'organisation
contre, organisation triangulaire supérieure,
supérieure 0 sinon.
sinon Les paramètres de la fonction sont la matrice
du tableau carrée A, le nombre des lignes et des colonnes L

™ Exemple : //* fonction permettant la mise à 1 de tableaux de 15 éléments *// ™ Matrices triangulaires supérieures sont des matrices carrées dont les valeurs sous
void Initialisation(int T[ ][15], int nbl) la diagonale principale sont nulles
{ int i, j; ™ Pour tout i>j aijj=0
for(i=0; i < nbl; i++)
for(j=0; j < 15; j++)
T[i][j] = 1;
}
main()
{
int Matrice[20][15];
Initialisation(Matrice 10);
Initialisation(Matrice,
}
137 138

Correction Pointeur sur une fonction


int EstTriangulaireSuperieure(int A[ ][30] , int L) void Affiche(int A[ ][30], int L)
™ Le langage C offre la possibilité de passer une fonction comme paramètre
{ int i , j ; { int i , j ;
d'une autre fonction. On utilise un mécanisme de pointeur
for( i = 1 ; i < L ; i++ ) for( i = 0 ; i < L ; i++ )
for(j=0 ; j<i ; j++) { ™ Un pointeur sur une fonction ayant pour prototype
if( A[i][j] != 0 ) return 0 ; for(j=0 ; j<L ; j++) Type fct (type-1,…,type-n);
return 1 ; printff ("%d\t",A[i][j]);
(% \ )
} printf("\n"); est de type
void Saisie(int A[ ][30], int L) } Type
yp ((*)(type-1,…,type-n);
)( yp , , yp );
{ }
int i , j ; main() ™ Dans le corps de la fonction qui utilise une fonction comme paramètre
for( i = 0 ; i < L ; i++ ) { int M[30][30]; Type retour fonction(Type1 arg1 , Type2 arg2,…, Type ((*fct)
Type_retour fct) (Type
(Type-1,
1, …,Type-n))
…,Type n))
for(j=0 ; j<L ; j++) Saisie(M, 5); Affiche(M, 5); { /* ...*/ Type Val = (*fct)(param-1, param-2, …, param-n) ; /* ...*/ }
{ if( EstTriangulaireSuperieure(M, 5))
printff ("\nA[%d][%d]:",
(\ % % i, j);
) printf("M
i tf("M estt triangulaire
ti l i supérieure");
éi ") ™ Déclaration
scanf("%d", &A[i][j]); else
Type_retour fonction(Type1, Type2 ,…, Type (*) (Type-1, …,Type-n))
} printf("M n’est pas triangulaire supérieure");
} }

139 140
Pointeur sur une fonction : Exemple

int somme(int, int);


int produit(int , int);
int operateur_binaire(int, int, int (*)(int, int));
main()
{
int a =5, b=9;
printf("%d\n"
printf( %d\n ,operateur_binaire(a,b,somme));
operateur binaire(a b somme));
printf("%d\n",operateur_binaire(a,b,produit));
}
int somme (int a, int b)
{ return a + b; }
int produit (int a, int b)
{ return a * b; }
int operateur_binaire (int a, int b, int (*f)(int , int))
{ return (*f)(a,b); }
141

Vous aimerez peut-être aussi