3. Unprogramme
• Un programme informatique est un ensemble d'opérations destinées à être exécutées
par un ordinateur pour réaliser en général trois choses :
1. Il lit des données en entrée.
2. Il effectue des calculs.
3. Il écrit des données en sortie.
• Il existe de nombreuses approches (paradigmes) de programmation. Parmi elles:
• La programmation procédurale (ou Impérative) est basé sur le principe de l'exécution étape par
étape des instructions.
• Exemple de langages de programmation: C, Pascal, Fortran, Cobol, etc.
• La programmation orientée objet est basé sur le principe de découpage de programme en
plusieurs modules isolés les uns des autres et l’introduction de la notion des objets qui contient
des variables et des fonctions en rapport avec un sujet ou un métier.
• Exemple de langages de programmation: Java, C++, C#, etc.
Prof. Y.BOUKOUCHI / AIAC 4Introduction
4. Unprogramme
• Un programmeur crée des programmes informatiques.
• Le programmeur doit pour cela expliquer à l’ordinateur dans un langage de programmation, quelles
sont les données et quelles sont les méthodes à appliquer pour traiter ces données.
• Une fois que le programmeur a écrit son programme, qui est du texte en langage C, il doit compiler
le programme pour créer un fichier exécutable(en binaire) par l’ordinateur.
• Un programme source est un code écrit par un programmeur dans un langage de programmation.
• Un programme binaire décrit les instructions à exécuter par un microprocesseur sous
forme numérique..
Prof. Y.BOUKOUCHI / AIAC 5Introduction
6. Unpeud’histoire
• Le langage C a été inventé aux Bells Labs en 1972 par Dennis Ritchie pour permettre l'écriture
du système d'exploitation UNIX, alors développé par Ken Thompson et Dennis Ritchie.
• Par la suite en 1978, Brian W. Kernighan documenta très activement le langage, pour finalement
publier avec Ritchie le livre de référence The C Programming Language
• En 1989, l'organisme national de normalisation des USA (ANSI) normalisa le C (C89)
Ken
Thompson
Brian
Kernighan
Dennis
Ritchie
Prof. Y.BOUKOUCHI / AIAC 7Le langage C
7. Environnementdedéveloppement
• Il existe plusieurs outils pour réaliser un projet en C:
• DEV C++
• CodeLite
• Code::Blocks.
• Microsoft Visual C++.
• Xcode.
• Qt Creator
• Il existe aussi des sites en ligne:
• www.codechef.com/ide
• www.jdoodle.com/c-online-compiler
• www.ide.geeksforgeeks.org
Prof. Y.BOUKOUCHI / AIAC 8Le langage C
8. Structured’unprogrammeC
• #include <stdio.h>: c’est une
bibliothèque lié à la gestion des entrées
et sorties (STanDard Input Output), elle
contient, entre autres, la déclaration de
la fonction printf permettant d'afficher
du texte formaté.
• main(): c’est la fonction principale,
appelée au démarrage du programme.
• Le return 0 indique seulement que la
valeur 0 est retournée au système (ce
qui indique que le programme se
termine sans erreur).
Exemple 1 : Afficher un mot
Prof. Y.BOUKOUCHI / AIAC 9Le langage C
#include <stdio.h>
int main() {
printf("Bienvenue à l'AIAC");
return 0;
}
9. Structured’unprogrammeC
1. int n est la déclaration d’une variable
n de type entier.
2. scanf permet la lecteur des données
au clavier.
3. Le format d’affichage et de lecture %d
correspond à des nombres entier
(type int).
4. Dans printf, lors de l’affichage, le %d
est remplacé par la valeur de n.
Exemple 2 : Lire un nombre
Prof. Y.BOUKOUCHI / AIAC 10Le langage C
#include <stdio.h>
int main() {
int n;
printf("Veuillez entrer un nombre entier :");
scanf("%d",&n);
printf("Vous avez tapé %d, félicitation!", n);
return 0;
}
10. Structured’unprogrammeC
• Le symbole = de l’affectation signifie
qu’une variable prend la valeur du
résultat d’un calcul.
• Il correspond à une opération de
recopie d’une donnée.
• Les phrases comprises entre /∗ et ∗/
sont des commentaires. Elles n’ont
pas d’influence sur le déroulement
du programme.
Exemple 3 : Calculer et mémoriser le résultat
Prof. Y.BOUKOUCHI / AIAC 11Le langage C
#include <stdio.h>
int main() {
float x,y; /* déclaration de deux variables x et y */
printf("Veuillez entrer un nombre réel:");
scanf("%f",&x);/* lecture au clavier de la valeur de x */
y = 2*x; /* on met dans y le double du contenu de x */
printf("Le double du nombre tapé vaut %f n", y);
return 0;
}
11. /***************************/
/* Projet C – Auteur: Y.B. */
/* Date : 20/09/18 */
/***************************/
// commentaire
int main(void)
{
/* corps du programme*/
déclaration des variables;
instruction1 ;
instruction2 ;
….
}
begin
end
Prof. Y.BOUKOUCHI / AIAC 12Le langage C
Structured’unprogrammeC
• "main" : Cela signifie "principale", ses instructions
sont exécutées.
• void main(void): La fonction main ne prend
aucun paramètre et ne retourne pas de valeur.
• int main(void): La fonction main retourne une
valeur entière à l'aide de l'instruction return (0
si pas d’erreur).
• int main(int argc, char *argv[]): On obtient
alors des programmes auxquels on peut
adresser des arguments au moment où on
lance le programme.
• Entre accolades "{" et "}" on mettra la succession
d'actions à réaliser.(Bloc)
• Il y a 2 types de commentaires : /* ... */ et //
14. • Dans un programme, il apparaît des variables qui permettent de donner des noms à
des données.
• Chaque variable doit avoir un type (entier, réel, caractère, suite de caractères, ou
type plus complexe).
• Chaque variable doit avoir un identificateur unique qui est le nom de la variable.
• Une déclaration de variable a toujours sous la forme suivante :
type identificateur;
• ou bien la forme avec l’initialisation :
type identificateur = valeur;
• On peut aussi déclarer plusieurs variables d’un même type séparées par des
virgules. Exemple
• float x, y=2.0; /* nombres réels. y a pour valeur initiale 2.0 */
• int n; /* nombre entier */
Prof. Y.BOUKOUCHI / AIAC 15Les variables et les Types
Lesvariables
15. • Type entier int
• est une représentation des nombres entiers.
• généralement codé sur 4 octets (32 bits).
• Types réels float ET double
• Les types float et double permettent de représenter des nombres réels avec une certaine
précision (suivant une représentation des nombres appelée virgule flottante ou nombre
flottant).
• Le type double (codé sur 8 octets) est plus précis que le type float (codé sur 4 octets).
• La valeur maximale d’un double est d’environ 10308 alors que celle d’un float est de l’ordre
de 1038
• La bibliothèque math.h contient les fonctions de calcul scientifique pow (puissance),
sqrt (racine carrée), cos, sin, tan, etc.
Prof. Y.BOUKOUCHI / AIAC 16Les variables et les Types
Lestypes
16. • Le type char:
• Le type char (character) est un type caractère codé sur 1 octet.
• C’est la plus petite donnée qui puisse être stockée dans une variable.
• Une variable de type char peut être considérée soit comme un nombre, soit comme un
caractère que l’on peut afficher.
• Pour désigner par exemple le caractère Z dans un programme:
• on peut soit écrire ’Z’ (entre quotes),
• soit écrire 90 qui est le code ASCII du caractère Z.
• Dans les deux cas, il s’agit du même caractère et de la même donnée qui peut être stockée dans la
même variable de type char.
• LES TYPES unsigned
• Aux types int et char correspondent des types unsigned int et unsigned char qui
représentent uniquement des valeurs positives.
• Un unsigned int sur 4 octets va de 0 à 232− 1.
• Un unsigned char sur 1 octet va de 0 à 28− 1 (c’est-à-dire de 0 à 255).
Prof. Y.BOUKOUCHI / AIAC 17Les variables et les Types
Lestypes
17. Lesconstantes
• Une constante est une valeur qui n’est pas susceptible de varier lors de
l’exécution d’un programme.
• On peut donner un nom à une constante par un #define au début du
programme.
Prof. Y.BOUKOUCHI / AIAC 18Les variables et les Types
#define PI 3.14159265358979323846 // Constante de type float
#define G 9.81 // Constante de type float
#define H 4816 // Constante de type int
/* Voici aussi une constante de type chaîne de caractères : */
#define MESSAGE1 "Erreur, vous devez mettre le #define hors du main !"
18. Lesconversions
• Étant données deux variables de même type, on peut recopier le contenu d’une
variable dans l’autre par une affectation (signe =).
• Plus généralement, on peut copier dans une variable la valeur de toute une
expression.
• Si les deux variables sont de types différents, l’opération d’affectation = va réaliser,
lorsque c’est possible, une conversion. Si la conversion n’est pas possible, le
compilateur affichera un message d’erreur.
int a;
a = 10;
int b = 0;
double val = 23.3;
char carac = 'G';
Prof. Y.BOUKOUCHI / AIAC 19Les variables et les Types
20. Lesconversionsimplicites:Conversionsd’untypeàl’autre
Affectation des valeur d’un type à des variables d’un autre :
Pas de problèmes en descendant la pyramide, mais dans le sens inverse :
Données tronquées
Exemple :
Explication :
int a = 8;
double b = a;// b = 8
float c = 0.32;
long d = c;// d = 0
Prof. Y.BOUKOUCHI / AIAC 21Les variables et les Types
Lesconversions
unsigned long a = 65523;
unsigned char b = a; // b = 243
6552310 = 1111 1111 1111 00112
= 1111 00112
21. Conversion implicite
Conversion explicite (cast)
int a = 10;
long b = a;
(typeSouhaité)donnée
char a = 10;
double b = (double)a;
• Toujours ,il y a une perte d’information.
• Le compilateur nous donne un message
d’avertissement (warning), à moins que
l’on effectue un cast, appelé aussi
conversion explicite, en indiquant le
type souhaité entre parenthèses
Prof. Y.BOUKOUCHI / AIAC 22Les variables et les Types
Lesconversionsexplicite:(Cast)
Lesconversions
23. Unebibliothèque
• Une bibliothèque est un ensemble de fonctionnalités ajoutées à un langage de
programmation. Chaque bibliothèque a un thème.
• Par exemple (en langage C):
• la bibliothèque math.h contient les fonctions mathématiques de calcul numérique
et des constantes comme M_PI pour représenter le nombre π ;
• la bibliothèque time.h contient les types et fonctions permettant de gérer la durée
(date et heure, temps d’exécution du programme...) ;
• la bibliothèque float.h contient les limites et constantes des types float et double ;
• La bibliothèque (Standard Input Output) stdio.h contient les types et fonctions
permettant de gérer les entrées-sorties (saisies au clavier, affichage de texte, mais
aussi fichiers...).
• etc.
Prof. Y.BOUKOUCHI / AIAC 24Entrées-Sorties : stdio.h
24. l’affichagededonnées
Afficher des caractères
a) Pour afficher un caractère on peut utiliser la fonction putchar :
• putchar(’A’); /* Affiche un ’A’*/
• putchar(65); /* Affiche aussi un ’A’*/
b) Pour afficher une chaine de caractères on peut utiliser la fonction puts :
• puts("coucou !");
c) La fonction puts va automatiquement à la ligne après l’affichage. Pour
afficher un message sans aller à la ligne, on peut utiliser printf:
• printf("coucou !");
Prof. Y.BOUKOUCHI / AIAC 25Entrées-Sorties : stdio.h
25. Afficher d’autres données
• Pour afficher des nombres entier, réels, etc. il faut spécifier un format, c’est à dire qu’il
faut préciser comment le résultat doit être affiché.
• La fonction printf est une fonction d’affichage formatée, ce qui signifie que les
données sont converties selon le format particulier choisi.
• Sa syntaxe est
printf("chaîne de contrôle ",expression-1, ..., expression-n);
• La chaîne de contrôle contient le texte à afficher et les spécifications de format
correspondant à chaque expression de la liste.
• %d décimale
• %f décimale avec virgule fixe
• %c char caractère
• %s chaîne de caractères
• %o octale
• %x hexadécimale
%d n p
Prof. Y.BOUKOUCHI / AIAC 26Entrées-Sorties : stdio.h
l’affichagededonnées
26. Un exemple d’affichage
Prof. Y.BOUKOUCHI / AIAC 27Entrées-Sorties : stdio.h
l’affichagededonnées
#include <stdio.h>
int main(void){
char caract='W';
printf("%cn", caract);
int nombre=2018;
printf("%dn", nombre); // nombre
float x=134000.12345678;
double y=134000.12345678;
printf("%fn", x); // float
printf("%lfn", y); //float ou double avec plus de précision (plus de chiffres après la virgule)
printf("%.3fn", x); // en spécifiant le nombre de chiffres après la virgule
printf("%en", x); // un réel avec puissance de 10
printf("%sn", "coucou !"); // afficher une chaîne de caractères
system("pause");
return 0;
}
Caractères spéciaux utiles
'n' Nouvelle ligne
'r' Retour chariot
't' Tabulation horizontale
'0' Caractère nul
'' Backslash
''' Apostrophe
'"' Guillemet
27. Lalectureauclavier
• La fonction getchar permet de lire un caractère.
• La fonction scanf permet de saisir des données au clavier et de les stocker aux adresses
spécifiées par les arguments de la fonctions.
scanf("chaîne de contrôle",argument-1,...,argument-n)
• La chaîne de contrôle indique le format dans lequel les données lues sont converties.
• %d décimale
• %o octale
• %f décimale avec virgule fixe
• %x hexadécimale
• %c char caractère
• %s chaîne de caractères
• On peut lire plusieurs valeurs dans un même appel à scanf, en séparant les %d, %f,...
par des espaces.
• scanf("%f %lf", &f1, &f2);
• Attention: Utilisation d’un getchar pour manger un retour chariot.
%d &i
Prof. Y.BOUKOUCHI / AIAC 28Entrées-Sorties : stdio.h
33. Lesopérationslogiques
Opérateur Opération
== Egalité
!=
>
<
>=
Inégalité
Strictement supérieur
Strictement inférieur
Supérieur ou égal
<= Inférieur ou égal
Prof. Y.BOUKOUCHI / AIAC 34Structures Conditionnelles
relation fausse, c = 0c = a == b
relation vraie, c = 1c = a != b
relation vraie, c = 1c = a > b
relation fausse, c = 0c = a < b
relation vraie, c = 1c = a >= b
relation fausse, c = 0c = a <= b
Exemples
int a = 10;
int b = 3;
int c;
34. Opérateur Opération
&& Et logique
||
!
Ou logique
Négation logique
Comme pour les opérateurs de
comparaison, la valeur retournée par
ces opérateurs est un int qui vaut 1 si
la condition est vraie et 0 sinon.
int a = 10;
int b = 3;
int c = (a != b && a > b);
// c = 1 car 10 != 3 ET 10 > 3
Lesopérationsbooléens
Prof. Y.BOUKOUCHI / AIAC 35Structures Conditionnelles
C1 C2 C1 && C2
VRAI VRAI VRAI
VRAI FAUX FAUX
FAUX VRAI FAUX
FAUX FAUX FAUX
C1 C2 C1 || C2
VRAI VRAI VRAI
VRAI FAUX VRAI
FAUX VRAI VRAI
FAUX FAUX FAUX
C1 !C1
VRAI FAUX
FAUX VRAI
35. Lastructureif…else
• Les structures conditionnelles permettent de déterminer quelles
instructions seront exécutées et dans quel ordre.
• Pour qu'un programme soit capable de prendre des décisions, on utilise
dans le code source des conditions
• Ces conditions permettent de tester des variables.
• une condition est soit vraie, soit fausse
Prof. Y.BOUKOUCHI / AIAC 36Structures Conditionnelles
Syntaxe1:
if (condition)
operation;
Syntaxe2:
if (condition)
operation1;
else
operation2;
36. • Un else se rapporte toujours au dernier if rencontré
Des accolades sont nécessaires pour associer un else à un if antérieur
Prof. Y.BOUKOUCHI / AIAC 37Structures Conditionnelles
Lastructureif…else
37. Conditionimbriqué
Lorsqu'on a plusieurs cas à tester, on peut enchaîner les if ... else
Prof. Y.BOUKOUCHI / AIAC 38Structures Conditionnelles
Lastructureif…else
38. Laconditionswitch…case
• Le switch permet de distinguer plusieurs cas selon les valeurs d’une variable alors
que permet de distinguer seulement deux cas.
• L'instruction switch ... case sert à traiter des choix multiples en fonction de la valeur
d'une expression entière.
• Ainsi, il permet de simplifier l'écriture de conditions qui testent plusieurs valeurs
possibles pour une même variable.
Prof. Y.BOUKOUCHI / AIAC 39Structures Conditionnelles
39. • Default à la fin correspond au else, elle s'exécute si aucun des tests précédents n'est vérifié.
• Switch ne permet de tester que l'égalité. Vous ne pouvez pas tester « Si le nombre d'enfants est
supérieur à 2 » avec switch : il faut dans ce cas utiliser if.
• Switch ne peut travailler qu'avec des nombres entiers (int, unsigned int, char). Il est impossible de
tester des nombres décimaux (double).
Prof. Y.BOUKOUCHI / AIAC 40Structures Conditionnelles
Laconditionswitch…case
40. Prof. Y.BOUKOUCHI / AIAC 41Structures Conditionnelles
int main(void){
char choix;
puts("Menu : faites un choix:n");
puts("Afficher la liste des clients ----------> a");
puts("Afficher les données d’un client --> b");
puts("Saisir un client -------------------------> c");
puts("Quitter -----------------------------------> d");
choix = getchar();
switch(choix)
{
case 'a' : puts("Affichage de la liste des clients"); /* mettre ici le code d’affichage des clients */
break;
case 'b' : puts("Affichage des données d’un client"); /* mettre ici le code de saisie et d’affichage */
break;
case 'c' : puts("Saisie des données du client"); /* mettre ici le code de saisie des données */
break;
case 'd' :
break;
default : puts("Erreur de saisie du choix !");
}
return 0;
}
43. • Les boucles (les itérations) vous permettent de répéter les mêmes
instructions plusieurs fois dans votre programme.
• Les boucles sont répétées tant qu'une condition est vraie.
• Il existe 3 types de boucles à connaître :
• while (condition){};
• do ... while(condition) ;
• for(initialisation, condition, incrémentation).
• La boucle for est généralement utilisée lorsqu'on sait combien de fois on
souhaite répéter les instructions.
• tandis que while et do... while sont plutôt utilisées lorsqu'on souhaite
répéter des instructions jusqu'à ce qu'une condition spécifique soit vérifiée.
Prof. Y.BOUKOUCHI / AIAC 44Les boucles
44. Labouclewhile
• Dans la boucle while, le programme répète un bloc d’instructions tant qu’une
certaine condition est vraie.
• Tout ce qui est entre accolades sera répété tant que la condition est vérifiée.
while (condition)
{
/* Instructions à répéter */
}
Prof. Y.BOUKOUCHI / AIAC 45Les boucles
45. • L'instruction est d'abord exécutée, puis l'expression est évaluée. Si elle est vraie,
on reboucle sur l'exécution de l'instruction.
• À la différence de la boucle while, l'instruction est toujours exécutée au moins
une fois
do
{
/* Instructions */
} while (condition);
Laboucledo...while
Prof. Y.BOUKOUCHI / AIAC 46Les boucles
46. • Ce type de boucle, que l'on retrouve fréquemment, permet de condenser :
• une initialisation ;
• une condition ;
• une incrémentation.
1. L'instruction1 est d'abord exécutée (initialisation ).
2. Puis, tant que l'expression est vraie, on exécute le bloc d’instructions.
3. puis l'instruction2 (instruction de progression).
for (instruction1; condition ; instruction2)
{
/* bloc d’instructions; */
}
Labouclefor
Prof. Y.BOUKOUCHI / AIAC 47Les boucles
49. • Un tableau permet de mémoriser plusieurs données du même type.
• Contrairement aux variables simples, les tableaux permettent de stocker des
données nombreuses en mémoire centrale.
• On déclare un tableau (statique) par
typeElements nomTableau[NOMBRE_ELEMENTS];
• Dans une telle déclaration, le nombre d’éléments du tableau est
obligatoirement une constante.
• exemple :
• int tab[100];
• char chaine[150];
• int tb1[10] ;
Déclarationd’untableau
Prof. Y.BOUKOUCHI / AIAC 50Les tableaux
50. • Les éléments d’un tableau sont comme des cases rangées successivement
dans la mémoire centrale.
• Les éléments d’un tableau sont numérotés par des indices (de 0 à N-1).
• Modification du contenu d’un élément :
tab[3] = 19 ;
Utilisation de la valeur d’un élément :
x = tab[3] + 1 ;
x = tab[3] + 1 ;
??????19???
9876543210
Accèsauxéléments
Prof. Y.BOUKOUCHI / AIAC 51Les tableaux
??????????
51. Comme les autres types de variables, les éléments du tableau peuvent être initialisés lors de la
déclaration du tableau. On met pour celà les valeurs des éléments entre accolades {} séparés par des
virgules.
int tab[10] = { 21, 32, -4, 1, 37, 88, 9, -1, 0, 7} ;
70-1988371-43221
9876543210
0000001-43221
9876543210
1-43221
3210
• Initialisation d’une partie du tableau : int tab[10] = { 21, 32, -4, 1} ;
• Initialisation sans spécifier la taille : int tab[ ] = { 21, 32, -4, 1} ;
Initialisationlorsdeladéclaration
Prof. Y.BOUKOUCHI / AIAC 52Les tableaux
52. • Le programme suivant permet de
mémoriser différentes valeurs
saisies au clavier et de les réafficher
dans l’ordre où elles ont été saisies.
• Le nombre de valeurs, ou nombre
d’éléments du tableau, est fixé à 5.
Nombred’élémentsfixé
Prof. Y.BOUKOUCHI / AIAC 53Les tableaux
#include <stdio.h>
#define NB_ELEM 5 /* Nombre d’éléments du tableau */
int main(void){
int i; /* indice */
float tableau[NB_ELEM]; /* déclaration du tableau */
for (i=0 ; i<NB_ELEM ; i++){
printf("Entrez l’élément %d : ", i);
scanf("%f", &tableau[i]); /* lecture d’un élément */
}
for (i=0 ; i<NB_ELEM ; i++){
printf("l’élément numéro %d vaut %fn", i, tableau[i]);
}
system("pause");
return 0;
}
53. • Le programme suivant permet
aussi de lire des éléments au
clavier et de les réafficher, mais
cette fois le nombre d’éléments
est lu au clavier.
• Ce nombre d’éléments doit
toutefois rester inférieur à une
valeur maximale constante fixée
(NB_ELEM_MAXI).
Nombred’élémentsvariableborné
Prof. Y.BOUKOUCHI / AIAC 54Les tableaux
#include <stdio.h>
#define NB_ELEM_MAXI 100 /* Nombre maximum d’éléments du tableau */
int main(void){
int n, i; /* nombre d’éléments et indice */
float tableau[NB_ELEM_MAXI]; /* déclaration du tableau */
printf("Entrez le nombre d’éléments à taper : ");
/* lecture du nombre d’éléments au clavier (variable) */
scanf("%d", &n);
if (n > NB_ELEM_MAXI){ /* test d’erreur */
puts("Erreur, nombre trop grand !");
return 1; }
for (i=0 ; i<n ; i++){
printf("Entrez l’élément %d : ", i);
scanf("%f", &tableau[i]); /* lecture d’un élément */ }
for (i=0 ; i<n ; i++){
printf("l’élément numéro %d vaut %fn", i, tableau[i]); }
return 0;
}
54. • Comme tous les langages, C autorise
les tableaux à plusieurs indices (à
plusieurs dimensions).
• Déclaration :
type nomtab [N][M][P];
• Par exemple, la déclaration : int t[5][3]
réserve un tableau de 15 (5 x 3) éléments.
• Un élément quelconque de ce tableau
est repéré par leur indices :
nomTab[i][j][k]…
• Déclaration et initialisation :
int tab [3] [4] =
{ { 1, 2, 3, 4 } , { 5, 6, 7, 8 }, { 9,10,11,12 } }
Lestableauxàplusieursindices
Prof. Y.BOUKOUCHI / AIAC 55Les tableaux
#include <stdio.h>
int main(){
int tab[3][4]={{11,12,13,14},
{21,22,23,24},
{31,32,33,34}};
int i,j;
for(i=0;i<3;i++){
for(j=0;j<4;j++){
printf("tab[%d,%d]=%dn",i+1,j+1,tab[i][j]);
}
}
system("pause");
return 0;
}
tab[1,1]=11
tab[1,2]=12
tab[1,3]=13
tab[1,4]=14
tab[2,1]=21
tab[2,2]=22
tab[2,3]=23
tab[2,4]=24
tab[3,1]=31
tab[3,2]=32
tab[3,3]=33
tab[3,4]=34
Appuyez sur une touche
pour continuer...
57. • Lorsqu’un programme comprend de nombreuses lignes de code dans le programme
principal main, il serait illisible, comprendrait trop de variables, etc.
• Alors, on décompose les problèmes en sous-problèmes et le programme en sous-
programmes qui résolvent les sous-problèmes.
• En langage C, l’outil pour créer des sous-programmes est la notion de fonction.
• Définition d'une fonction
typeRetour nom-fonction ( type1 param1, …, typeN paramN)
{
/*déclarations de variables locales */
/* suite d'instructions */
}
• typeRetour désigne le type de la valeur qu'elle retourne, si la fonction ne renvoie
pas de valeur elle est de type void. Dans ce cas on parle de procédure.
• Si la liste des paramètres est vide ou void, la fonction ne prend pas de paramètre.
Définition
Prof. Y.BOUKOUCHI / AIAC 58Les fonctions
58. • Fonctions avec arguments et retournant une valeur.
• type fonction(int x, int y, char ch)
• float somme(float x, float y, float z)
• int maxTab(int tab[])
• Fonctions sans arguments et ne retournant pas de valeur.
• void fonction(void) ou void fonction()
• void lireMessage()
• void afficheErreur()
• Fonctions avec arguments ne retournant pas de valeur.
• void fonction(int x, int y, char ch)
• void afficherList(char list[])
• void ecrireFichier(File *pfi)
Définition
Prof. Y.BOUKOUCHI / AIAC 59Les fonctions
59. Exemple
Prof. Y.BOUKOUCHI / AIAC 60Les fonctions
Un programme qui lit un nombre x au
clavier et calcule f(x):
f (x) = (x3− 2x + 1) sin(3x + 1)
#include <stdio.h>
#include <math.h>
int main(void){
float x, y; /* on calcule y=f(x) */
puts("Veuillez taper une valeur de x :");
scanf("%f", &x);
y = (x*x*x-2*x+1)*sin(3*x+1);
printf("on a : f(%f) = %fn", x, y);
return 0;
}
#include <stdio.h>
#include <math.h>
float Lire(void) /* Fonction Lire, permet de lire une valeur */
{ float d; /* déclaration d’une variable locale d */
puts("Veuillez taper une valeur :");
scanf("%f", &d);
return d; /* on renvoie la valeur de d */
}
float CalculF(float x) /* Fonction CalculF, calcule une valeur de la fonction */
{ return (x*x*x-2*x+1)*sin(3*x+1);
}
void Affiche(float y) /* Fonction Affiche, permet d’afficher une valeur */
{ printf("La valeur calculée est %fn", y);
/* une fonction void ne retourne rien */
}
int main(){
float x, y; /* Fonction main, programme principal */
x = Lire(); /* appel de la fonction Lire */
y = CalculF(x); /* calcul de f(x) */
Affiche(y); /* appel de la fonction Affiche */
return 0;
}
60. Variables globale
• Sont des variables partagées par plusieurs
fonctions;
• On dit que leur portée (leur espace de validité) est
limitée à la partie du programme source qui suit
leur déclaration
Variables locales
• Sont déclarées à l’intérieur de la définition d’une
fonction. On ne peut les utiliser qu’à l’intérieur de
cette fonction.
• Leur portée est donc limitée à cette fonction.
• Si l’on trouve une variable de même nom ailleurs
dans le programme, il ne s’agit pas de la même
variable, mais d’une variable homonyme.
LesvariablesLocalesetGlobales
Prof. Y.BOUKOUCHI / AIAC 61Les fonctions
Exemple 2
int n ;
main()
{
int p ;
....
}
fct1 ()
{
int p ;
int n ;
}
Exemple 1
main()
{
....
}
int n ;
float x ;
fct1 (...)
{
....
}
fct2 (...)
{
....
}
P
o
r
t
é
e
N
P
P
61. Leprototyped’unefonction
Prof. Y.BOUKOUCHI / AIAC 62Les fonctions
Une déclaration de fonction est le prototype de cette fonction suivi d’un point virgule.
une déclaration peut être répétée plusieurs fois dans le programme.
Le prototype d’une fonction indique essentiellement :
• Le nom de la fonction,
• Les paramètres de la fonction et leur type,
• Le type de retournée par la fonction.
typeRetour nomFonction ( ListeParalétres);
Exemple:
• int puissance(int n, int p);
• Float moyenneNote(int tab[]);
Une définition de fonction est le prototype suivi du corps de la fonction entre accolades.
La définition apparaître une seule fois dans le programme.
typeRetour nomFonction ( ListeParalétres){
/*déclarations de variables locales */
/* suite d'instructions *
}
62. Exemple
Prof. Y.BOUKOUCHI / AIAC 63Les fonctions
Un programme qui lit deux nombres
x et p et calcule la puissance xp
#include <stdio.h>
/*Il est recommandé d’utiliser des déclarations globales pour
les prototypes*/
float puissance(float x, int p); // déclaré globale
int main(void){
// déclaré locale à main : float puissance(float x, int p);
float x; int p;
printf("Taper une valeur de x :");
scanf("%f", &x);
printf("Taper une valeur de p :");
scanf("%d", &p);
printf("%.2f puissance %d = %.2fn",x,p,puissance(x,p));
return 0;
}
float puissance(float x, int p){
float r=1; int i;
for(i=0;i<p;i++)
r=r*x;
return r;
}
Taper une valeur de x :4
Taper une valeur de p :5
4.00 puissance 5 = 1024.00
Appuyez sur une touche pour continuer...
#include <stdio.h>
float puissance(float x, int p){
float r=1; int i;
for(i=0;i<p;i++) r=r*x;
return r;
}
int main(void){
float x; int p;
printf("Taper une valeur de x :");
scanf("%f", &x);
printf("Taper une valeur de p :");
scanf("%d", &p);
printf("%.2f puissance %d =
%.2fn",x,p,puissance(x,p));
return 0;
}
63. Lemécanismedetransmissiond’arguments
Prof. Y.BOUKOUCHI / AIAC 64Les fonctions
• Dans langage C les arguments d’une
fonction sont toujours transmis par valeur -
une copie de la valeur de l’argument
effectif.
• Impossible à une fonction de modifier la
valeur d’un objet reçu en argument.
• Pour contourner cette difficulté de modifie
la valeur d’un objet apparaissant en
argument (sauf s’il s’agit d’un tableau), il
existe plusieurs possibilités:
• utiliser un pointeur sur l’objet à modifier;
• se servir de la valeur de retour de la
fonction;
• utiliser des variables globales.
#include <stdio.h>
void echange1(int x, int y);
int main(){
int a=5, b=10;
printf("Avant a=%d et b=%dn",a,b);
echange1(a,b);
printf("Apres a=%d et b=%dn",a,b);
}
void echange1(int x,int y){
int temp;
temp=x;
x=y;
y=temp;
}
Avant a=5 et b=10
Apres a=5 et b=10
Appuyez sur une touche pour continuer...
64. Lemécanismedetransmissiond’arguments
Prof. Y.BOUKOUCHI / AIAC 65Les fonctions
#include <stdio.h>
int a,b;
void echange2(void);
int main(){
a=5; b=10;
printf("Avant a=%d et b=%dn",a,b);
echange2();
printf("Apres a=%d et b=%dn",a,b);
}
void echange2(){
int temp;
temp=a;
a=b;
b=temp;
}
Avant a=5 et b=10
Apres a=10 et b=5
Appuyez sur une touche pour continuer...
#include <stdio.h>
void echange1(int x, int y);
int main(){
int a=5,b=10;
printf("Avant a=%d et b=%dn",a,b);
echange1(a,b);
printf("Apres a=%d et b=%dn",a,b);
}
void echange1(int x,int y){
int temp;
temp=x;
x=y;
y=temp;
}
Avant a=5 et b=10
Apres a=5 et b=10
Appuyez sur une touche pour continuer...
Utilisation des
variables
globales
65. Desfonctionsrécursives
Prof. Y.BOUKOUCHI / AIAC 66Les fonctions
Le langage C autorise la récursivité des appels de
fonctions. Celle-ci peut prendre deux aspects :
• récursivité directe : une fonction comporte,
dans sa définition, au moins un appel à elle-
même,
• récursivité croisée : l’appel d’une fonction
entraîne celui d’une autre fonction qui, à son
tour, appelle la fonction initiale (le cycle
pouvant d’ailleurs faire intervenir plus de deux
fonctions).
#include <stdio.h>
int factorielle(int);
int main(){
int n=5,f;
f=factorielle(n);
printf("%d!=%dn",n,f);
}
int factorielle(int n){
int f=1;
if(n>0)
return n*factorielle(n-1);
else
return 1;
}
68. • La mémoire centrale d’un ordinateur est
composée d’un très grand nombre d’octets.
Chaque octet est repéré par un numéro
appelé adresse de l’octet.
• Chaque variable dans la mémoire occupe des
octets contigus. Par exemple, un int occupe 4
octets qui se suivent.
• L’adresse de la variable est l’adresse de son
premier octet.
Mémoirecentraleetadresses
Prof. Y.BOUKOUCHI / AIAC 69Adresses, pointeurs et passage par adresse
Variable Adresse Mémoire
Octet/8bits
c 1001000 ‘A’
1001001
i 1001002
2018
1001003
1001004
1001005
1001005
1001007
1001008
1001009
1001010
1001011
69. • On peut connaître l’adresse d’une variable par
l’opérateur &.
• &i /* adresse de la variable x : adresse de son premier octet */
Adressed’unevariable
Prof. Y.BOUKOUCHI / AIAC 70Adresses, pointeurs et passage par adresse
Variable Adresse Mémoire
Octet/8bits
c 1001000 ‘A’
1001001
i 1001002
2018
1001003
1001004
1001005
1001005
1001007
1001008
1001009
1001010
1001011
la valeur de c est A et son adresse est 2686791
la valeur de i est 2018 et son adresse est 2686784
la valeur de f est 55.90 et son adresse est 2686780
Appuyez sur une touche pour continuer...
#include <stdio.h>
int main(){
char c='A';
int i=2018;
float f=55.9;
printf("la valeur de c est %c et son adresse est %dn",c,&c);
printf("la valeur de i est %d et son adresse est %dn",i,&i);
printf("la valeur de f est %.2f et son adresse est %dn",f,&f);
system("pause");
return 0;
}
70. • L’adresse d’une variable peut être mémorisée dans
une variable.
• Les variables dont les valeurs sont des adresses
s’appellent des pointeurs.
• On déclare un type pointeur par l’opérateur *
• On déclare :
• un pointeur sur int par le type int*,
• un pointeur sur float par le type float*,
• Etc.
• On accède à la donnée pointée par un pointeur
(valeur de x dans l’exemple précédent) par une
étoile.
• int*p; /*on déclare le pointeur p qui pointe sut int */
• p=&i; /* on affecte au pointeur p l’adresse de i*/
• *p=2019; /* on modifier le contenu de l’adresse*/
Variabledetypepointeur
Prof. Y.BOUKOUCHI / AIAC 71Adresses, pointeurs et passage par adresse
Variable Adresse Mémoire
Octet/8bits
c 1001000 ‘A’
1001001
i 1001002
2018
1001003
1001004
1001005
1001005
1001007
1001008
p 1001009 1001002
1001010
1001011
71. Variabledetypepointeur
Prof. Y.BOUKOUCHI / AIAC 72Adresses, pointeurs et passage par adresse
Variable Adresse Mémoire
Octet/8bits
c 1001000 ‘A’
1001001
i 1001002
2018
1001003
1001004
1001005
1001005
1001007
1001008
p 1001009 1001002
1001010
1001011
la valeur de i :2
Donner une valeur:45
la nouvelle valeur de i:45
la valeur de *p:45
Appuyez sur une touche pour continuer...
#include <stdio.h>
int main(){
int i=2;/* déclaration d’une variable i */
int *p; /* déclaration d’un pointeur p */
p = &i; /* p pointe sur i */
/* la valeur de p est l’adresse de i */
printf("la valeur de i :%dn", *p); /* affichage de valeur de *p */
printf("Donner une valeur:");
scanf("%d", p); /* lecture de la valeur de i au clavier */
printf("la nouvelle valeur de i:%dn", i); /* affichage de la nouvelle
valeur de i */
printf("la valeur de *p:%dn", *p); /* affichage de la valeur de *p */
system("pause");
return 0;
}
72. • Attention:
• Ne pas confondre l’usage de l’étoile lors de la
déclaration d’une variable de type pointeur avec
l’usage de l’étoile qui permet d’accéder à l’objet
pointé par le pointeur.
• Ne pas confondre la valeur d’un pointeur p, qui est
une adresse, et la valeur de l’objet pointé par p, qui
n’est en général pas une adresse, par exemple un int
dans le cas d’un pointeur de type int*.
• lorsque p pointe sur i, la valeur de p est l’adresse de
i, toute modification de *p modifie i et toute
modification de i modifie *p. La raison est que *p et
i sont sur le même emplacement mémoire dans la
mémoire RAM.
Variabledetypepointeur
Prof. Y.BOUKOUCHI / AIAC 73Adresses, pointeurs et passage par adresse
Variable Adresse Mémoire
Octet/8bits
c 1001000 ‘A’
1001001
i 1001002
2018
1001003
1001004
1001005
1001005
1001007
1001008
p 1001009 1001002
1001010
1001011
*p
73. • Lorsqu’on passe un paramètre à une fonction, la
fonction ne peut pas modifier la variable.
• La variable est automatiquement recopiée et la
fonction travaille sur une copie de la variable.
• La modification de la copie n’entraîne pas une
modification de la variable originale. C’est le
passage de paramètre par valeur.
Passagedeparamètreparvaleur
Prof. Y.BOUKOUCHI / AIAC 74Adresses, pointeurs et passage par adresse
#include <stdio.h>
void permutation(int x, int y){
int z;
z=x;
x=y;
y=z;
printf("Au cours de permutation a=%d et b=%dn",x,y);
}
int main(){
int a=2;
int b=5;
printf("Avant permutation a=%d et b=%dn",a,b);
permutation(a,b);
printf("Après permutation a=%d et b=%dn",a,b);
system("pause");
return 0;
}
Avant permutation a=2 et b=5
Au cours de permutation a=5 et b=2
Après permutation a=2 et b=5
Appuyez sur une touche pour continuer...
Variable Adresse mémoire
a 2080090 2
b 2080094 5
Variable Adresse mémoire
x 2080100 2
y 2080104 5
z 2080108
Une Copie de la valeur
74. • L’idée du passage par adresse est de passer en
paramètre non pas une copie de la valeur d’une
variable, mais un pointeur qui pointe sur cette
variable.
• Ainsi, Lorsqu’on modifie la mémoire à cette
adresse, la donnée est modifiée, car on travaille
bien sur l’emplacement mémoire de cette
variable.
Passagedeparamètreparadresse
Prof. Y.BOUKOUCHI / AIAC 75Adresses, pointeurs et passage par adresse
#include <stdio.h>
void permutation(int *x, int *y){
int z;
z=*x; // le contenu de l’adresse
*x=*y;
*y=z;
printf("Au cours de permutation a=%d et b=%dn",*x,*y);
}
int main(){
int a=2;
int b=5;
printf("Avant permutation a=%d et b=%dn",a,b);
permutation(&a,&b);
printf("Après permutation a=%d et b=%dn",a,b);
system("pause");
return 0;
}
Avant permutation a=2 et b=5
Au cours de permutation a=5 et b=2
Après permutation a=5 et b=2
Appuyez sur une touche pour continuer...
Variable Adresse mémoire
a 2080090 2
b 2080094 5
Variable Adresse mémoire
x 2080100 2080090
y 2080104 2080094
z 2080108
Une Copie de l’adresse
75. • Il existe un symbole noté NULL , dont la valeur représente conventionnellement un pointeur
ne pointant sur rien,
• c’est-à-dire auquel n’est associée aucune adresse.
• Cette valeur peut être affectée à un pointeur de n’importe quel type, par exemple:
• int *pi= NULL;
• char *pc= NULL;
• double *pd= NULL;
• Etc.
• Exemples d’utilisation de NULL:
• Pour l’initialisation d’une variable pointeur
• Dans des listes chaînées
• En valeur de retour d’une fonction
LepointeurNULL
Prof. Y.BOUKOUCHI / AIAC 76Adresses, pointeurs et passage par adresse
76. • L’allocation dynamique de mémoire
permet de créer des tableaux dont la
taille mémoire est variable en fonction
des besoins, et de libérer cette mémoire
après utilisation.
• La fonction malloc réserve des octets
pour une utilisation par le programme.
• Le nombre d’octets est passé en
paramètre à la fonction malloc.
• On utilise la fonction sizeof qui calcule le
nombre d’octets nécessaires
• La fonction malloc retourne l’adresse du
premier octet réservé (un pointeur).
• Après utilisation de la mémoire, la
mémoire doit impérativement être
libérée avec la fonction free.
Lestableauxdynamiques
Prof. Y.BOUKOUCHI / AIAC 77Adresses, pointeurs et passage par adresse
#include <stdio.h>
#include <stdlib.h> /* pour utiliser malloc */
int main(void)
{ int nb,i;
int *tab; /* adresse du tableau (type pointeur) */
printf("Entrez la taille du tableau : ");
scanf("%d", &nb);
/* le nombre d’éléments connu, on alloue le tableau */
tab = (int*) malloc (nb * sizeof(int) ); /* allocation */
puts("Entrez les éléments du tableau :");
for (i=0 ; i<nb ; i++) // la saisie des éléments du tableau
scanf("%d", &tab[i]);
for (i=0 ; i<nb ; i++) // l’affichage du tableau
printf("tab[%d] = %dn", i, tab[i]);
free(tab); /* libération de mémoire obligatoire */
return 0;
}
Entrez la taille du tableau : 3
Entrez les ÚlÚments du tableau :
29
10
2018
tab[0] = 29
tab[1] = 10
tab[2] = 2018
77. • Exemple
• Ecrire la fonction RentrerTableau qui
lit le nombre d’éléments d’un
tableau, réserve de l’espace
mémoire pour des float, lit les
éléments du tableau au clavier et
retourne l’adresse du tableau.
• Le nombre d’éléments du tableau
doit être passé par adresse pour
être transmis au main.
Lestableauxdynamiques
Prof. Y.BOUKOUCHI / AIAC 78Adresses, pointeurs et passage par adresse #include <stdio.h>
#include <stdlib.h> /* pour utiliser malloc */
/* fonction retournant un pointeur de type float* */
float* RentrerTableau(int *addrNbreElements)
{ int n, i; float *tab; /* adresse du tableau (type pointeur) */
printf("Entrez la taille du tableau : "); scanf("%d", &n);
*addrNbreElements = n; /* passage par adresse, renvoi de n */
/* le nombre d’éléments connu, on alloue le tableau */
tab = (float*) malloc ( n * sizeof( float ) ); /* allocation */
puts("Entrez les éléments du tableau :");
for (i=0 ; i<n ; i++)
scanf("%f", &tab[i] );
return tab; /* on retourne l’adresse du tableau */
}
void Affichage(float *tab, int nb) /* affiche un tableau tab */
{ int i;
for (i=0 ; i<nb ; i++) printf("tab[%d] = %.2fn", i, tab[i]);
}
int main(void)
{ int nb; float *tab;
tab = RentrerTableau(&nb);/* on récupère l’adresse du tableau dans tab */
Affichage(tab, nb);
free(tab); /* libération de mémoire obligatoire */
return 0; }
Entrez la taille du tableau : 3
Entrez les ÚlÚments du tableau :
14.55
18.75
13.25
tab[0] = 14.55
tab[1] = 18.75
tab[2] = 13.25
80. • En langage C, il n’existe pas de véritable type chaîne.
• Une chaîne de caractères est un tableau de caractères se terminant par le
caractère spécial ’0’ .
• Le caractère ’0’ sert à repérer la fin de la chaîne, évitant d’avoir à connaître le
nombre de caractères de la chaîne.
• Cela signifie qu’une chaîne de n caractères occupe en mémoire un
emplacement de n+1 octets.
Représentationd’unechaine
Prof. Y.BOUKOUCHI / AIAC 81Les chaines de caractères
0ruojNob
76543210
1N
81. • Calculer la longueur d’une chaine de caractères
Représentationd’unechaine
Prof. Y.BOUKOUCHI / AIAC 82Les chaines de caractères
#include <stdio.h>
int longueur(char chaine[]); // int longueur(char *chaine);
int main(){
char nom[31];
int Long;
printf("Veuillez entrer votre nom: ");
scanf("%s", nom); /* lecture de la chaîne. pas de & */
Long = longueur( nom);
printf("Votre nom est : %sn", nom);
printf("Sa longueur est : %dn", Long);
return 0;
}
int longueur(char chaine[]){ // int longueur(char *chaine){
int i;
for(i=0; chaine[i]!='0';i++);
return i;
}
Veuillez entrer votre nom: BOUKOUCHI
Votre nom est : BOUKOUCHI
Sa longueur est : 9
Appuyez sur une touche pour continuer...
82. • char ch[20] ;
• ch = "bonjour"; //invalide
• ch est une constante
pointeur qui correspond
à l’adresse que le
compilateur a attribuée
au tableau ch ;
Initialisationdetableauxdecaractères
Prof. Y.BOUKOUCHI / AIAC 83Les chaines de caractères
• C autorise à initialiser votre tableau de caractères à
l’aide d’une chaîne constante.
• char ch[20] = "bonjour" ;
• char ch[20] = { 'b','o','n','j','o','u','r','0' }
• char message[] = "bonjour" ;
• Initialisation de tableaux de pointeurs sur des
chaînes.
• char * jour[7] = { "lundi", "mardi", "mercredi",
"jeudi", "vendredi", "samedi", "dimanche" } ;
83. Initialisationdetableauxdecaractères
Prof. Y.BOUKOUCHI / AIAC 84Les chaines de caractères
#include <stdio.h>
main(){
char * jour[7]={"lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"};
int i ;
printf("donnez un entier entre 1 et 7 : ");
scanf("%d",&i);
printf("le jour numéro %d de la semaine est %sn", i, jour[i-1]);
}
donnez un entier entre 1 et 7 : 4
le jour numÚro 4 de la semaine est jeudi
Appuyez sur une touche pour continuer...
84. Lireetécriredeschaînes
Prof. Y.BOUKOUCHI / AIAC 85Les chaines de caractères
• Le langage C offre plusieurs possibilités de lecture ou d’écriture de chaînes :
• l’utilisation du code de format %s dans les fonctions printf et scanf ;
• les fonctions spécifiques de lecture (gets) ou d’affichage (puts) d’une chaîne (une seule à la fois).
• Les fonctions printf et scanf permettent de lire ou d’afficher simultanément plusieurs
informations de type quelconque. En revanche, gets et puts ne traitent qu’une chaîne à
la fois.
• De plus, la délimitation de la chaîne lue ne s’effectue pas de la même façon avec scanf et
gets. Plus précisément :
• avec le code %s de scanf, on utilise les délimiteurs habituels (l’espace ou la fin de ligne). Cela
interdit donc la lecture d’une chaîne contenant des espaces. De plus, le caractère délimiteur n’est
pas consommé : il reste disponible pour une prochaine lecture ;
• avec gets, seule la fin de ligne sert de délimiteur. De plus, contrairement à ce qui se produit avec
scanf, ce caractère est effectivement consommé : il ne risque pas d’être pris en compte lors d’une
nouvelle lecture.
85. Lireetécriredeschaînes
Prof. Y.BOUKOUCHI / AIAC 86Les chaines de caractères
#include <stdio.h>
main(){
char nom[20], prenom[20], adresse[50];
printf("quelle est votre adresse : ");
gets (adresse);
printf ("donnez votre nom et votre prénom : ");
scanf ("%s %s", nom, prenom);
printf ("bonjour cher %s %s qui habitez à ", prenom, nom);
puts (adresse);
system("PAUSE");
}
quelle est votre adresse : 123, Rue Ghaza, Salam, Casablanca
donnez votre nom et votre prénom : BOUKOUCHI Youness
bonjour cher Youness BOUKOUCHI qui habitez à 123, Rue Ghaza, Salam, Casablanca
Appuyez sur une touche pour continuer...
86. • La bibliothèque string.h contient des fonctions de traitement des chaînes de
caractères.
• strcpy
• La fonction strcpy copie une chaîne dans une autre.
• char* strcpy(char* destin, char*source);
• strcat
• La fonction strcat concatène deux chaînes de caractères.
• char* strcat(char* s1, char* s2);
• strlen
• La fonction strlen retourne la longueur d’une chaîne de caractères.
• size_t strlen(char* s);
• strcmp
• Le fonction strcmp permet de comparer deux chaînes pour l’ordre alphabétique.
• int strcmp(char* s1, char *s2);
• Le résultat est < 0 si s1 < s2, égal à 0 si s1=s2, et il est > 0 si s1 > s2.
• Etc.
Labibliothèque<string.h>
Prof. Y.BOUKOUCHI / AIAC 87Les chaines de caractères
88. • Une structure est un type qui permet de stocker plusieurs données, de même
type ou de types différents, dans une même variable de type structure.
• C'est une collection des données qui peuvent être de types différents (entières,
flottantes, tableaux, pointeurs, etc...).
• Ces données sont appelés les membres (ou les champs) de la structure.
Définitiond’unestructure
Prof. Y.BOUKOUCHI / AIAC 89Les structures
Voiture
Numéro: chaine de caractères
Date circulation: Date
Couleur: chaine de caractères
Marque: chaine de caractères
Personne
Nom : chaine de caractères
Prénom: chaine de caractères
Age: entier
Notes: tableaux des réels
Compte
Numéro: entier
Solde: réels
Date création: structure Date
Date
Jour: entier
Mois: entier
Année: entier
89. • Une structure est définie avec le mot clef struct, à la fois dans la définition du
type et dans la déclaration des variables.
• La déclaration d’une variable de type struct se fait comme pour une autre
variable.
Déclarationd’unestructure
Prof. Y.BOUKOUCHI / AIAC 90Les structures
/* Définition d’une structure */
struct point {
/* les champs se déclarent comme des variables*/
/* mais on ne peut pas initialiser les valeurs */
/* trois champs x, y, z */
float x,y;
float z;
};
/* Déclaration d’une variable de type point*/
struct point P;
/* Définition d’une structure */
struct nom_de_la_structure {
type_membre1 nom_membre1 ;
type_membre2 nom_membre2 ;
…
type_membreN nom_membreN ;
};
/* Déclaration d’une variable de type struct */
struct nom_de_la_structure variable;
90. • Grâce à un typedef, on peut donner un nom au type structure pour éviter la
répétition fastidieuse du mot clef struct dans la déclaration des variables.
Déclarationd’unestructure
Prof. Y.BOUKOUCHI / AIAC 91Les structures
/* Définition d’un type Point3D */
typedef struct point
{ /* déclaration d’un */
float x,y,z; /* nouveau type par typedef */
}Point3D;
/* Déclaration d’une variable P de type
Point3D */
Point3D P;
/* Version 1*/
/* Définition d’un type nomType */
typedef struct nomStructure
{
// liste des membres;
}nomType;
/* Version 2*/
/* Définition d’un type nomType */
typedef struct
{
// liste des membres;
}nomType;
91. • Accès aux membres par l’opérateur « . »
• nomVariable.champ
• compte1.solde = 3834.56;
• y=comptes[33].solde;
• Dans le cas des structures imbriquées:
• nomVariable.nomChamp1.nomChamp.nomChamp3.etc.
• compte1.dernierVersement.jour = 15;
• personnes[12].dateNaissance.mois = 11;
• printf("nDate d’emprunt %d/%d/%dn", m.emprunt.jour, m.emprunt.mois, m.emprunt.an);
Accèsauxmembres
Prof. Y.BOUKOUCHI / AIAC 92Les structures
92. • Une structure peut être membre d'une
autre structure
struct date {
int jour;
int mois;
int annee;
};
struct compte {
int no_compte ;
char nom[80];
float solde;
struct date dernier_versement;
};
• Remarque : ordre de déclaration des structures
Structureimbriquée
Prof. Y.BOUKOUCHI / AIAC 93Les structures
typedef struct {
int jour; int mois; int annee;
} Date ;
typedef struct { /* définition de la structure*/
int noCompte ; float solde;
Date dateCreation;
}Compte;
main(){
Compte c;
c.noCompte=2004001;
c.solde=550.78;
c.dateCreation.jour=11;
c.dateCreation.mois=10;
c.dateCreation.annee=2018;
printf("Numéro :%dn",c.noCompte);
printf("Solde :%.2fn",c.solde);
printf("Date :%d-%d-%dn",c.dateCreation.jour,
c.dateCreation.mois,c.dateCreation.annee);
}
Numéro :2004001
Solde :550.78
Date :23-11-2017
Appuyez sur une touche pour continuer...
93. • En C, on peut utiliser une structure de deux manières :
• en travaillant individuellement sur chacun de ses champs ; Chaque champ d’une
structure peut être manipulé comme n’importe quelle variable du type correspondant.
• en travaillant de manière globale sur l’ensemble de la structure (Affectation : c1 = c2):
• Lors de l’affectation, il y a une copie « champs à champs » des informations de la
structure source vers la structure destination
• Pas de comparaison c1==c2 ( il faut comparer chaque membre)
• Initialisations de structures
• il est possible d’initialiser explicitement une structure lors de sa déclaration.
• struct compte c1 = {12345,"Youness",2690.45,{11,10,2018}}
Utilisationd’unestructure
Prof. Y.BOUKOUCHI / AIAC 94Les structures
94. • La syntaxe de déclaration d’un tableaux:
• struct nomStructure nomTableau [DIM _Max]
• typeStructure nomTableau [DIM_Max]
Tableauxdestructures
Prof. Y.BOUKOUCHI / AIAC 95Les structures
#define MAX_COMPTES 10
typedef struct { /* définition de la structure*/
int numero ;
char nom[50];
char specialite[60];
}Prof;
Prof listProfs[MAX_COMPTES];
main(){
int i,nbrProfs=2; /* le nombre effectif des comptes*/
Prof prof1={201,"Youness BOUKOUCHI","Informatique"};
Prof prof2={220,"Asmae BOUJIBAR","Planétologie"};
listProfs[0]=prof1;
listProfs[1]=prof2;
for(i=0;i<nbrProfs;i++){
printf("Numéro :%dn",listProfs[i].numero);
printf("Nom :%sn",listProfs[i].nom);
printf("Sospécialité :%sn",listProfs[i].specialite);
}
}
Numero :201
Nom :Youness BOUKOUCHI
Sospecialite :Informatique
Numero :220
Nom :Asmae BOUJIBAR
Sospecialite :Planetologie
Appuyez sur une touche pour continuer...
95. • L'adresse de début d'une structure s'obtient à l'aide de l'opérateur &
• Compte c1={3030,"Youness",800.75} ; // c1 est de type Compte
• Compte * pc; //pc est un pointeur sur une variable de type Compte
• pc = &c1; // pc reçois l’adresse de c1
• Quand la structure est un pointeur, on utilise l’operateur « -> » pour accéder aux
membres . L’écriture p->champs est synonyme de (*p).champs, où p est un pointeur sur
une structure
• printf("Numéro :%dn", pc->noCompte);
• printf("Nom :%sn", pc->nom);
• printf("Solde :%.2fn", (*pc).solde);
• pc->noCompte=4040;
• strcpy(pc->nom,"Youness BOUKOUCHI");
• pc->solde=15000.00;
Adressed’unestructures
Prof. Y.BOUKOUCHI / AIAC 96Les structures
typedef struct {
int noCompte ;
char nom[80];
float solde;
} Compte;
96. • Les membres d'une structure peuvent être passés comme paramètres à des fonctions avec
ou sans modification
Transmissiond’unestructure
Prof. Y.BOUKOUCHI / AIAC 97Les structures
// sans modification=> passage par valeur
void verserCompte(float solde, float montant) {
solde = solde + montant;
}
int main(){
Compte c={30030,"Youness",0.00};
verserCompte(c.solde,1000);
printf("Solde :%.2fn",c.solde);
// Solde:0.00
}
// avec modification=> passage par adresse
void verserCompte(float *solde, float montant) {
* solde = * solde + montant;
}
int main(){
Compte c={30030,"Youness",0.00};
verserCompte(& c.solde,1000);
printf("Solde :%.2fn",c.solde);
// Solde:1000.00
}
97. • Une structure peuvent être passés comme paramètres à des fonctions avec ou sans
modification
Transmissiond’unestructure
Prof. Y.BOUKOUCHI / AIAC 98Les structures
// sans modification=> passage par valeur
void verserCompte(Compte cpt, float montant) {
cpt.solde = cpt.solde + montant;
}
int main(){
Compte c={30030,"Youness",0.00};
verserCompte(c,1000);
printf("Solde :%.2fn",c.solde);
// Solde:0.00
}
// avec modification=> passage par adresse
void verserCompte(Compte*cpt, float montant) {
cpt-> solde = cpt->solde + montant;
}
int main(){
Compte c={30030,"Youness",0.00};
verserCompte(& c,1000);
printf("Solde :%.2fn",c.solde);
// Solde:1000.00
}
98. • La valeur de retour d'une fonction peut être une structure ou une adresse d’une structure
Transmissiond’unestructure
Prof. Y.BOUKOUCHI / AIAC 99Les structures
// type de retour => une structure
Compte verserCompte(Compte cpt, float montant)
{
cpt.solde = cpt.solde + montant;
return cpt;
}
int main(){
Compte c={30030,"Youness",0.00};
c=verserCompte(c,1000);
printf("Solde :%.2fn",c.solde);
// Solde:1000.00
}
// type de retour => une adresse
Compte * verserCompte(Compte cpt, float montant)
{
cpt.solde = cpt.solde + montant;
return &cpt;
}
int main(){
Compte c={30030,"Youness",0.00};
Compte *pc;
pc=verserCompte(c,1000);
printf("Solde :%.2fn",pc->solde);
// Solde:1000.00
}
100. • Dans un ordinateur, il y a deux sortes de mémoire : la mémoire centrale
et la mémoire disque.
• Les données stockées en mémoire centrale ne durent que le temps de
l’exécution d’un programme.
• Pour mémoriser des données de manière permanente, il faut les stocker
sur un disque (disque dur, clef USB, carte mémoire, etc.).
• Un fichier est une série de données stockées sur un disque ou dans un
périphérique de stockage.
• Un fichier texte est un fichier qui contient du texte ASCII. On peut visualiser le contenu
d’un fichier texte avec un éditeur de texte.
• Un fichier binaire contient du code binaire. On ne peut pas visualiser son contenu avec
un éditeur de texte.
Unfichier
Prof. Y.BOUKOUCHI / AIAC 101Les fichiers
101. • On appelle lecture dans un fichier le transfert de
données du fichier vers la mémoire centrale.
• On appelle écriture dans un fichier le transfert de
données de la mémoire centrale vers le fichier.
• Pour pouvoir utiliser les fichiers, on doit inclure la
bibliothèque d’entrées-sorties : #include<stdio.h>
• Pour lire ou écrire dans un fichier, nous avons besoin
d’un pointeur de fichier qui permet de désigner le
fichier dans lequel nous souhaitons lire ou écrire.
• Un pointeur de fichier est de type FILE *.
• On déclare un tel pointeur comme toute autre variable :
FILE *fp; /* déclaration d’un pointeur de fichier fp */
Déclarationd’unfichier
Prof. Y.BOUKOUCHI / AIAC 102Les fichiers
Fichier
L
e
c
t
u
r
e
E
c
r
i
t
u
r
e
Mémoire
Centrale (RAM)
fprintf()
fread()
fscanf()
fwrite()
102. • il faut lier le pointeur de fichier à un fichier sur le disque. On appelle cette
opération l’ouverture du fichier.
• On utilise la fonction fopen qui a deux paramètres:
• Le premier paramètre est le nom du fichier, ou plus exactement le chemin vers le
fichier dans l’arborescence des répertoires.
• Le deuxième paramètre est le mode d’accès , exemple : r, w, a, etc.
• La fonction fopen retourne le pointeur NULL en cas d’erreur d’ouverture de fichier.
• Exemple
• fp = fopen("monfichier.txt" ou "monfichier.dat","r"); /* (exemple de chemin relatif : répertoire local) */
• fp = fopen("/home/remy/algo/monfichier.txt","w"); /* (exemple de chemin absolu sous Unix ou Linux) */
• fp = fopen("C:remyalgomonfichier.txt","a"); /* (exemple de chemin absolu sous Windows) */
• Pour fermer le fichier on utilise la fonction fclose qui prend en paramètre le
pointeur de fichier: fclose(fp);
Prof. Y.BOUKOUCHI / AIAC 103
Ouvertureetfermetured’unfichier
Les fichiers
103. Prof. Y.BOUKOUCHI / AIAC 104
Lesdifférentsmodesd’accès
Les fichiers
"r" ouverture d'un fichier en lecture
"w" ouverture d'un fichier en écriture
"a" ouverture d'un fichier en écriture à la fin
"r+" ouverture d'un fichier en lecture/écriture
"w+" ouverture d'un fichier en lecture/écriture
"a+" ouverture d'un fichier en lecture/écriture à la fin
"rb" ouverture d'un fichier binaire en lecture
"wb" ouverture d'un fichier binaire en écriture
"ab" ouverture d'un fichier binaire en écriture à la fin
"r+b" ouverture d'un fichier binaire en lecture/écriture
"w+b" ouverture d'un fichier binaire en lecture/écriture
"a+b" ouverture d'un fichier binaire en lecture/écriture à la fin
"rt" ouverture d'un fichier texte en lecture
"wt" ouverture d'un fichier texte en écriture
"at" ouverture d'un fichier texte en écriture à la fin
"r+t" ouverture d'un fichier texte en lecture/écriture
"w+t" ouverture d'un fichier texte en lecture/écriture
"a+t" ouverture d'un fichier texte en lecture/écriture à la fin
Ces modes d'accès ont pour
particularités :
• Si le mode contient la lettre r, le
fichier doit exister.
• Si le mode contient la lettre w, le
fichier peut ne pas exister. Dans ce
cas, il sera créé. Si le fichier existe
déjà, son ancien contenu sera
perdu.
• Si le mode contient la lettre a, le
fichier peut ne pas exister. Dans ce
cas, il sera créé. Si le fichier existe
déjà, les nouvelles données seront
ajoutées à la fin du fichier
précédent.
104. Lire des données formatées:
• le fichier doit préalablement avoir été ouvert en mode "r", "r+", "w+", ou "a+".
• Pour lire des données numériques ou autres dans un fichier texte, on utilise la
fonction fscanf qui prend en paramètres:
1. le pointeur de fichier,
2. la chaîne de format avec des %d, %f,...
3. les adresses des variables avec des &
• La fonction fscanf retourne le nombre de variables effectivement lues, qui peut
être inférieur au nombre de variables dont la lecture est demandée en cas
d’erreur ou de fin de fichier.
• le format de fichier est la manière dont les données sont organisées dans un
fichier.
Prof. Y.BOUKOUCHI / AIAC 105
FichierTexte
Les fichiers
fp format &varaiables
105. Lire des données formatées:
• Exemple : Chargement d’un fichier
d’entiers en mémoire centrale (dans
un tableaux d’entier). On suppose
que dans un fichier texte sont écrits
des nombres entiers séparés par des
espaces :
• 5 12 -66 87 -14 12 -etc.
Prof. Y.BOUKOUCHI / AIAC 106
FichierTexte
Les fichiers
tableau[0] = 5
tableau[1] = 12
tableau[2] = -66
tableau[3] = 87
tableau[4] = -14
tableau[5] = 12
Appuyez sur une touche pour continuer...
#include <stdio.h>
#include <stdlib.h> /* pour utiliser la fonction exit */
#define NB_ELEM_MAX 100
int ChargeFichier(int tableau[NB_ELEM_MAX])
{ FILE *fp; int i=0;
fp = fopen("monfichier.txt", "rt"); /* ouverture du fichier : */
if (fp ==NULL) /* gestion d’erreur */
{ puts("Erreur d’ouverture de fichier :");
puts("Fichier inexistant ou permissions insuffisantes");
exit(1); /* termine le programme avec code d’erreur */
}
while (i < NB_ELEM_MAX && fscanf(fp, "%d", tableau[i])==1)
i++; /* incrémentation : pareil que i=i+1 */
fclose(fp); /* fermeture du fichier */
return i; /* on retourne le nombre d’éléments lus */
}
void Affiche(int tableau[], int n)
{ int i;
for (i=0 ; i<n ; i++)
printf("tableau[%d] = %dn", i, tableau[i]);
}
int main()
{ int tab[NB_ELEM_MAX]; int n; n = ChargeFichier(tab);
Affiche(tab, n); return 0; }
106. Ecrire des données formatées:
• le fichier doit préalablement avoir été ouvert en mode "w", "a", "r+", "w+" ou
"a+".
• Pour écrire des données numériques ou autres dans un fichier texte, on utilise
la fonction fprintf qui prend en paramètres:
1. le pointeur de fichier,
2. la chaîne de format avec le texte à écrire et les %d, %f, etc.
3. Les variables à écrire séparées par des virgules.
Prof. Y.BOUKOUCHI / AIAC 107
FichierTexte
Les fichiers
fp chaine variables
107. Lire des données formatées:
• Exemple : Voici un programme qui lit un
fichier texte contenant des nombres
entiers, et écrit un fichier texte
contenant les entiers triples (chaque
entier est multiplié par 3).
Prof. Y.BOUKOUCHI / AIAC 108
FichierTexte
Les fichiers
#include <stdio.h>
int TripleFichier()
{
FILE *fpr, *fpw; /* deux pointeurs pour deux fichiers */
int n; /* pour lire */
fpr = fopen("fichierLecture.txt", "rt");
fpw = fopen("fichierEcriture.txt", "wt");
if (fpr==NULL || fpw==NULL) /* gestion d’erreur */
return 1; /* code d’erreur retourné au main */
while (fscanf(fpr, "%d", &n)==1) /* lecture d’un entier */
fprintf(fpw, " [%d] ", 3*n); /* écriture du triple */
fclose(fpr); /* fermeture des deux fichiers */
fclose(fpw);
return 0; /* pas d’erreur */
}
int main()
{ int codeErr;
codeErr = TripleFichier(); /* on récupère le code d’erreur */
if(codeErr != 0)
puts("Erreur d’ouverture de fichier !");
return 0;
}
108. Ecriture dans un fichier binaire
• La fonction fwrite possède quatre arguments :
1. l’adresse d’un bloc d’informations(variable);
2. la taille d’un bloc en octets;
3. le nombre de blocs de cette taille que l’on souhaite
transférer dans le fichier;
4. le fichier (fp).
• La fonction fwrite retourne le nombre de blocs
effectivement écrits.
• La fonction sizeof donne la taille de chaque type (ou
bloc).
• Par exemple: sizeof(char) vaut 1, sizeof(float) vaut 4.
Prof. Y.BOUKOUCHI / AIAC 109
Fichierbinaire
Les fichiers
&variable taille fichier
#include <stdio.h>
main(){
int n ;
FILE * fp ;
fp = fopen ("monfichier.data", "w");
do {
printf("donnez un entier : ") ;
scanf("%d", &n) ;
if (n) // si n !=0
fwrite (&n, sizeof(int), 1, fp) ;
}while (n) ;
fclose (fp);
}
donnez un entier : 5643
donnez un entier : 7654
donnez un entier : 9879
donnez un entier : 0
109. Lecture dans un fichier binaire
• La fonction fread possède quatre arguments:
1. l’adresse d’un bloc d’informations(variable);
2. la taille d’un bloc, en octets;
3. le nombre de blocs;
4. le fichier (fp).
• La fonction fread retourne le nombre de blocs
effectivement lus.
• La fonction feof (fp) prend la valeur vrai (c’est-à-
dire 1) lorsque la fin du fichier a été rencontrée.
• feof est utilisée comme une condition d’arrêt de
la boucle de lecture
Prof. Y.BOUKOUCHI / AIAC 110
Fichierbinaire
Les fichiers
&variable taille fichier
#include <stdio.h>
main(){
int n ;
FILE * fp ;
fp = fopen ("monfichier.data", "r") ;
while( fread (&n, sizeof(int), 1, fp)&&! feof(fp))
printf ("%dn", n) ;
fclose (fp);
}
5643
7654
9879
110. • Il y a deux techniques de gestion de fichiers :
• l’accès séquentiel consiste à parcourir les informations séquentiellement;
• l’accès direct consiste à se placer directement sur l’information souhaitée.
• La fonction fseek permet de se positionner à un endroit précis dans un fichier;
• Lorsqu’on écrit sur un emplacement, la donnée qui existait éventuellement à cet
emplacement est effacée et remplacée par la donnée écrite.
• Le prototype de la fonction fseek permettant de se positionner est:
• La fonction modifie la position du pointeur fichier fp d’un nombre d’octets égal à offset à
partir de l’origine.
• L’origine peut être :
• SEEK_SET : on se positionne par rapport au début du fichier ;
• SEEK_END : on se positionne par rapport à la fin du fichier ;
• SEEK_CUR : on se positionne par rapport à la position courante actuelle (position avant l’appel de fseek).
Prof. Y.BOUKOUCHI / AIAC 111
Positionnementdansunfichier
Les fichiers
int File*fp long offset int origine
111. • La fonction modifieNombre prend un entier i en
paramètre permet à l’utilisateur de modifier le
(i+1)ème entier du fichier.
Prof. Y.BOUKOUCHI / AIAC 112
Positionnementdansunfichier
Les fichiers
#include <stdio.h>
void modifieNombre(int i, FILE *fp)
{int n, nouveau;
fseek(fp, i*sizeof(int), SEEK_SET); /* positionnement */
fread(&n, sizeof(int), 1, fp); /* lecture */
printf("L’ancien entier vaut %dn", n);
puts("Veuillez entrer la nouvelle valeur");
scanf("%d", &nouveau);
fseek(fp, -sizeof(int), SEEK_CUR); /* recul d’une case */
fwrite(&nouveau, sizeof(int), 1, fp); /* écriture */
}
void remplirFichier(FILE * fp)
{ int n,p=0 ;
printf("Taper des entiers different de 0.n") ;
do { printf("Entier %d : ",p) ;
scanf("%d", &n) ;
p++;
if (n) // si n !=0
fwrite (&n, sizeof(int), 1, fp) ;
}while (n) ;
}
void afficherFichier(FILE * fp)
{ int n,p=0;
fseek(fp, 0, SEEK_SET); /* positionnement */
while( fread (&n, sizeof(int), 1, fp)&&! feof(fp))
{ printf ("Position %d = %dn",p, n) ;
p++; }
}
int main(void)
{ int p; FILE * fp=NULL ;
fp = fopen ("fichierNombre.data", "w+b");
remplirFichier(fp);
puts("Veuillez entrer la position");
scanf("%d", &p);
modifieNombre(p,fp);
afficherFichier(fp);
return 0;
}
Taper des entiers different de 0.
Entier 0 : 10
Entier 1 : 2018
Entier 2 : 0
Veuillez entrer la position
0
LÆancien entier vaut 10
Veuillez entrer la nouvelle valeur
2019
Position 0 = 2019
Position 1 = 2018
112. • La fonction int rewind(FILE *fp) permet de se positionner au début du fichier. Elle
est équivalente à fseek(fp, 0, SEEK_SET);
• La fonction long ftell(FILE *fp) retourne la position courante dans le fichier (en
nombre d'octets depuis l'origine).
Prof. Y.BOUKOUCHI / AIAC 113
Positionnementdansunfichier
Les fichiers