Академический Документы
Профессиональный Документы
Культура Документы
Bref historique
Pourquoi utiliserle langage C
Cycle de développement du programme
Votre premier programme C
Introduction
s’est rapidement répandue au-delà des laboratoires Bell.
Les programmeurs ont commencé à l’utiliser pour écrire
toutes sortes de programmes
Diverses organisations ont utilisé leurs propres versions
du langage C. Conséquence : l’implémentation est devenu
un casse-tête pour les programmeurs.
Réponse à ce problème : l’American National Standards
Institute(ANSI) à formé un comité en 1983 pour établir le
C standard ANSI.
Introduction
Il existe un large choix de compilateurs et d’utilitaires.
Avec la norme ANSI, le C est devenu un langage portable: un
programme C écrit pour un type d’ordinateur(IBM) peut être
compilé pour tourner sur un autre système avec très peu ou
aucune modification.
Le langage C est modulaire: son code peut(et devrait) être écrit
sous forme de sous-programme appelés fonctions. Si vous
passez des informations à ces fonctions, vous obtenez un code
réutilisable.
C est un langage structuré (offre plusieurs structures de
contrôle) et typé (déclarations obligatoires).
22/02/10 Programmer en langage C 4
Introduction : Cycle de développement du
programme
Introduction
indiquent à l’ordinateur les tâches que vous voulez lui
faire exécuter, il est créé à l’aide d’un éditeur.
La plupart des systèmes d’exploitation contiennent un
éditeur. Sous Unix vous pouvez utiliser, ed, ex, edit
emacs ou vi. Microsoft Windows vous offre le bloc-notes.
Introduction
appelle du langage machine. Votre programme C doit être
transformé en langage machine pour pouvoir être exécuté sur
votre ordinateur. Cette opération est réalisée par un compilateur
qui transforme votre fichier code source en un fichier contenant
le code objet(les mêmes instructions en langage machine).
Chaque compilateur possède sa propre commande pour créer le
code objet.
○ Windows: C Microsoft, Turbo C, Turbo C++, Borland C, Borland C++.
○ Unix : utiliser la commande c.
○ Linux et Unix: la commande gcc.
Introduction
destiné à des fonctions prédéfinies. Ces fonctions sont
fournies avec votre compilateur. Si votre programme les
utilise, le fichier objet obtenu après compilation doit
être complété par le code objet issu de la bibliothèque de
fonctions. Cette dernière étape, appelée liaison, fournit
le programme exécutable (exécutable signifie que ce
programme peut être exécuté sur votre ordinateur)
Introduction
/*déclaration*/
Main()
{
…..
}
Bibliothèques précompilées
(.lib)
math.lib
Programme executable
(.exe)
22/02/10 Programmer en langage C 8
Introduction : votre premier programme
#include<stdio.h>
Introduction
Main()
{
Affichage Bonjour
printf(‘’Bonjour’’);
}
Programme principal
{ printf("donnez un nombre:");
scanf("%f",&x);
Bloc
if(x<0.0)
printf("le nombre %f ne possède pas de racine carrée\n",x);
else
{ racx=sqrt(x);
printf("le nombre %f a pour racine carrée :%f\n",x,racx);
}
}
printf("travail terminé Au revoir");
}
22/02/10 Programmer en langage C 11
Exemple de programme en langage C
#include<conio.h>
#include<stdio.h>
Notion d’identificateur
Les commentaires
Chaînes de caractères
Les chaînes de caractères sont vues comme un pointeur sur des
caractères et sont donc de type char *.
*
Exemple:
○ char * chaine = "Hello World !";// une chaine de caractère
// noter l’utilisation du double
// quotte
La syntaxe du langage C
point virgule( à l’exception de #define et #include). Par exemple:
x=2+3;
est une instruction d’affectation. Elle demande à l’ordinateur
d’ajouter 2 et 3 et d’attribuer le résultat à la
variable x.
Les blocs:
○ Un bloc (ou instructions composées) est un groupe d’instructions
entre accolades:
{
printf("Hello"); {printf("Hello");
printf("world!"); printf("world!");}
}
La syntaxe du langage C
de l’expression.
Les expressions Simples
○ L’expression simple est constituée d’une seule variable, d’une constante. Par exemple:
PI //constante dont la valeur est définie par #define
Taux //variable
Les expressions complexes
○ Les expressions complexes sont constituées d’expressions plus simples avec des
opérateurs. Par exemple:
2+8
8+(5*taux)+(taux*taux)/cout
La syntaxe du langage C
programme C : x=y;
ne signifie pas ‘x égal y’. Elle indique à l’ordinateur
‘d’affecter la valeur de y à x’. Cette instruction doit être
composée d’une expression à droite du signe égale, et d’un
nom de variable à gauche de ce signe:
variable=expression;
Exemple:
○ x=6+(y=4+5);
○ a=b=2;
La syntaxe du langage C
var += exp ; équivalent à var = var + (exp) ;
var -= exp ; var = var - (exp) ;
var *= exp ; var = var * (exp) ;
var /= exp ; var = var / (exp) ;
var %= exp ; var = var % (exp) ;
Attention :
pas d’espace entre l’opérateur op et le égal =,
x *= y+1 est équivalent à x = x*(y+1) et pas x = x*y+1.
La syntaxe du langage C
22/02/10 Programmer en langage C 48
Instructions, Expressions et Opérateurs
Opérateurs arithmétiques
La syntaxe du langage C
Remarques :
○ Les opérandes de ces opérateurs arithmétiques peuvent
appartenir à tout type arithmétique seul l’opérateur % requiert
des types entiers.
○ Le résultat d’une division d’entiers est aussi un entier, Exemple :
6 / 4 // Resultat: 1
6 % 4 // Resultat: 2
6.0 / 4.0 // Resultat: 1.5
La syntaxe du langage C
○ Concernant l’incrémentation pré/postfixe, voici un petit exemple: Supposons que
la valeur de N soit égale à 3 :
Incrémentation postfixe : X = N++ ;
Résultat : N = 4 et X = 3
Incrémentation préfixe : X = ++N ;
Résultat : N = 4 et X = 4
Décrémentation postfixe : X = N-- ;
Résultat : N = 2 et X = 3
Décrémentation préfixe : X = --N ;
Résultat : N = 2 et X = 2
Opérateurs de comparaison
La syntaxe du langage C
Toute comparaison est une expression de type int qui
renvoie la valeur 0 (faux) ou 1 (vraie). Il faut que les
opérandes soient du même type arithmétique (ou des
pointeurs sur des objets de même type).
Attention : il ne faut pas confondre l’opérateur d’égalité
(==) avec celui d’affectation (=).
Les différents opérateurs de comparaison sont détaillés
dans le tableau ci-dessous.
La syntaxe du langage C
22/02/10 Programmer en langage C 52
Instructions, Expressions et Opérateurs
Opérateurs de comparaison
La syntaxe du langage C
#include <stdio.h>
void main ()
{
int x=14,y=1; // x est différent de y
if (x = y) //erreur!!! il faudrait écrire ’if (x == y)’
printf("x est égal à y (%i=%i)\n",x,y);
else
printf("x est différent de y (%i!=%i)\n",x,y);
}
La syntaxe du langage C
logique. Les opérandes des opérateurs logiques peuvent être
n’importe quel scalaire. Toute valeur différente de 0 est interprétée
comme vraie (et 0 correspond à ’faux’). Comme pour les expressions
de comparaisons les expressions logiques renvoient une valeur
entière (0 =faux ; 1=vraie).
Remarque :
les opérateurs && et || évaluent les opérandes de gauche à droite et
le résultat est connu dès l’opérande de gauche. Ainsi, l’opérande de
droite n’est évaluée que si celle de gauche est vraie dans le cas de
l’opérateur && (respectivement fausse dans le cas de l’opérateur ||).
Exemple:
(i < max) && (f(14) == 1), la fonction f n’est appelée que si i < max.
La syntaxe du langage C
Exemples
L’expression : 32 && 40 vaut 1
L’expression : !65.34 vaut 0
L’expression : !!0 vaut 0
La syntaxe du langage C
Les opérandes sont interprétées bits par bits (le bit 1
correspondant à une valeur vraie, 0 est considéré
comme une valeur fausse).
La syntaxe du langage C
22/02/10 Programmer en langage C 57
Instructions, Expressions et Opérateurs
La syntaxe du langage C
qui désigne un objet ou une expression.
&x renvoie l’adresse mémoire de x et est donc
un pointeur vers x.
La syntaxe du langage C
○ Exprime des calculs successifs dans une même expression. Le type
et la valeur de l’expression sont ceux du dernier opérande.
○ Exemple : x = 5 , x + 6. L’expression a pour valeur 11
Opérateur conditionnel (? :)
○ <expression> ? <expr1>: <expr2>
La syntaxe du langage C
22/02/10 Programmer en langage C 60
Instructions, Expressions et Opérateurs
Priorité et associativité des opérateurs
Lors de l’évaluation des différentes parties d’une
La syntaxe du langage C
expression, les opérateurs respectent certaines lois de
priorité et d’associativité.
Exemples
○ La multiplication a la priorité sur l’addition
○ La multiplication et l’addition ont la priorité sur l’affectation.
Tableau des opérateurs et priorité
La priorité est décroissante de haut en bas dans le tableau.
La règle d’associativité s’applique pour tous les opérateurs d’un
même niveau de priorité. (pour une associativité de gauche à droite
et pour une associativité de droite à gauche).
Dans une expression, les parenthèses forcent la priorité.
La syntaxe du langage C
2 + - ++ -- !
3 * / %
4 + -
5 < <= > >=
6 == !=
7 &&
8 ||
9 ?:
10 = += -= *= /= %=
La syntaxe du langage C
Float x=1.75;
Donner le type et la valeur de chacune des expressions suivantes
a) n+q
b) n+x a) long 12
c) n%p+q b) float 11,75
d) n<p c) long 4
e) q+3 *(n<p) d) int 0
f) x*(q==2) e) long 5
g) x*(q=2) f) float 1,75
h) (q-2)&&(n-10) g) int 0
i) q&&n h) int 1
La syntaxe du langage C
-1 si n est négatif
0 si n est nul
1 si n est positif
n ? (n>0 ? 1: -1) : 0
La syntaxe du langage C
Parmi les structures de contrôle, on distingue :
structures de choix
○ if….else (choix conditionnel)
○ switch (choix multiple)
structures répétitives ou itérative ou boucle
○ for
○ while
○ do…while
Branchement inconditionnel
○ Break, goto, continue
La syntaxe du langage C
bloc d'instructions selon qu'une condition est vraie ou
fausse.
Syntaxe
○ Forme 1
if (expression) instruction-1;
la forme if est ici dans sa forme la plus simple. Si expression est
vraie, instruction-1 est exécutée. Si expression est fausse,
instruction-1 est ignorée.
La syntaxe du langage C
Si expression est vraie, instruction-1 est exécutée, sinon c’est instruction-2 qui est
exécutée.
○ Forme 3
if (expression-1)
instruction-1;
else if (expression-2)
instruction-2;
else
instruction-3;
Les instructions if sont imbriquées. Si expression-1 est vraie, instruction-1
est exécutée. Dans le cas contraire expression-2 est évaluée si cette dernière est
vraie instruction-2 est exécutée. Si les deux expressions sont fausses, c’est
instruction-3 qui est exécuté
La syntaxe du langage C
○ if (salaire >45.000)
tax=0.30;
else
tax=0.25;
Exemple 2
○ if (age <18)
printf(‘’mineur’’);
else if (age <65)
printf(‘’adulte’’);
else
printf(‘’personne agée’’);
La syntaxe du langage C
d’exécuter différentes instructions en fonction d’une
expression qui pourra avoir plus de deux valeurs.
On l’appelle aussi l’instruction d’aiguillage. Elle teste
si une expression prend une valeur parmi une suite
de constantes, et effectue le branchement
correspondant si c’est le cas.
La syntaxe du langage C
switch (<condition>) {
case <valeur 1> : <action 1>; break;
case <valeur 2> : <action 2>; break;
…
default : <action n>;
}
La syntaxe du langage C
○ expression est évaluée ;
○ s’il existe un énoncé case avec une constante qui est égale à la
valeur de l’expression, le contrôle est transféré à l’instruction qui
suit cet énoncé;
○ si un tel case n’existe pas, et si énoncé default existe, alors le
contrôle est transféré à l’instruction qui suit l’énoncé default ;
○ si la valeur de l’expression ne correspond à aucun énoncé case et
s’il n’y a pas d’énoncé default, alors aucune instruction n’est
exécutée.
Attention.
○ Lorsqu’il y a branchement réussi à un case, toutes les instructions
qui le suivent sont exécutées, jusqu’à la fin du bloc ou jusqu’à une
instruction de rupture (break).
La syntaxe du langage C
char operateur;
Printf(‘’ Entrez un opérateur (+, -,* ou /):’’);
Scanf(‘’%c’’,&operateur);
Printf(‘’ Entrez deux entiers:’’);
Scanf(‘’%d’’,&a); Scanf(‘’ %d’’,&b);
switch(operateur){
case’-’ : y=a-b; printf(‘’%d’’,y);break;
case’+’ : y=a+b; printf(‘’%d’’,y); break;
case’*’ : y=a*b; printf(‘’%d’’,y); break;
case’/’ : y=a/b; printf(‘’%d’’,y); break;
default : printf(‘’opérateur inconnu\n’’);break;
}
}
La syntaxe du langage C
Syntaxe
Forme 1
while (condition)
une-instruction;
Forme 2
while (condition) {
Des instructions;
}
}
La syntaxe du langage C
3. si la condition est vraie les instructions sont exécutées
4. l’exécution reprend à l’étape 1.
Exemple
#include <stdio.h>
void main ()
{ int i=1, N;
printf("N=\n"); scanf("%d",&N);
while (i <= N) {
printf("%d ", i); i = i+1;}
printf("\n");
}
La syntaxe du langage C
int i=0,j;
while (i < MAX ) {
j=0;
while (j < MAX ) {
printf(" position : %d \t %d\n",i,j);
j++;
}
i++;
}
La syntaxe du langage C
Syntaxe
Forme 1
do
une-instruction;
while (condition)
Forme 2
do {
Des instructions;
} while (condition)
La syntaxe du langage C
#define MAX 4
void main()
{
int i=MAX;
do {
printf("Valeur de i : %i\n",i);
i++;
} while (i < MAX);
}
La syntaxe du langage C
Syntaxe:
for( [expression1] ; [expression2] ; [expression3 ])
{
liste d’instructions
}
Les crochets [ et ] signifient que leur contenu est facultatif
Dans la construction de for :
○ expression1 : effectue les initialisations nécessaires avant
l’entrée dans la boucle;
○ expression2 : est le test de continuation de la boucle ; le test
est évalué avant l’exécution du corps de la boucle;
○ expression3 : est évaluée à la fin du corps de la boucle.
La syntaxe du langage C
souvent plusieurs initialisations séparées par des
virgules.
○ For(i=0,j=1,k=5;….;…)
Les expressions expression1 et expression3 peuvent
être absente(les points-virgules doivent apparaître.
○ i=1; for(;i<=5;) {printf(‘’%d fois\n’’,i);i++;}
Lorsque expression2 est absente, l’expression
correspondante est considérée comme vraie. Par
conséquent, for(;;) est une boucle infinie
La syntaxe du langage C
{
liste d’instructions
}
est équivalente à
expression1;
while(expression2)
{
instructions;
expression3;
}
La syntaxe du langage C
Int n,total;
For(total=0,n=1;n<=100;n++)
total+=n;
Printf(’’la sommes des nombres de 1 à 100 est %d\n’’,total);
La syntaxe du langage C
On a vu le rôle de l’instruction break; au sein d’une
instruction de branchement multiple switch.
L’instruction break peut, plus généralement, être
employée à l’intérieur de n’importe quelle boucle (for ;
while ; do-while). Elle permet l’abandon de la structure
et le passage à la première instruction qui suit la
structure.
En cas de boucles imbriquées, break fait sortir de la
boucle la plus interne.
La syntaxe du langage C
#include <stdio.h>
void main( )
{ int i;
for (i = 1 ; i<=10 ; i++){ Evaluation:
printf(’’début tour %d\n’’ ,i) ; Début tour 1
Bonjour
printf(’’ bonjour\n’’); Début tour 2
if (i ==3) break ; bonjour
fin tour 2
printf(" fin tour%d\n", i) ; Début tour 3
Bonjour
} Après la boucle
printf(" après la boucle\n") ;
}
22/02/10 Programmer en langage C 84
Les structures de contrôle : break, goto et
continue
Instruction continue
La syntaxe du langage C
L’instruction continue peut être employée à l’intérieur
d’une structure de type boucle (for ; while ; do-while ).
Elle produit l’abandon de l’itération courante et fait
passer directement à l’itération suivante d’une boucle.
L’instruction continue concerne la boucle la plus
proche.
La syntaxe du langage C
Exemple :
Void main()
Evaluation:
{ int i; Début tour 1
for(i=1;i<=10;i++) Début tour 2
Début tour 3
{ printf(’’début tour %d\n’’ ,i) ; Début tour 4
Bonjour
if (i <4) continue ; Début tour 5
printf(’’ bonjour\n’’); Bonjour
}
}
La syntaxe du langage C
du programme.
Void main()
{ int i;
for(i=1;i<=10;i++) Evaluation:
{ printf(’’début tour %d\n’’ ,i) ; Début tour 1
Bonjour
printf(’’ bonjour\n’’);
fin tour 1
if (i ==3) goto sortie ; Début tour 2
printf(’’ fin tour%d\n", i); bonjour
fin tour 2
}
Début tour 3
Sortie:printf (" après la boucle\n") ; Bonjour
} Après la boucle
La syntaxe du langage C
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)
La syntaxe du langage C
int fact (int x)
{ printf (“Computing fact %d\n”, x) ;
if (x == 1)
return 1 ;
else
return x * fact (x-1) ;
}
Void main (){
printf (“5! = %d\n”, fact (5)) ;
}
22/02/10 Programmer en langage C 89
Les conversions de types
La conversion de type est un outil très puissant, elle
doit donc être utilisée avec prudence. Le compilateur
La syntaxe du langage C
fait de lui-même des conversions lors de l’évaluation
des expressions. Pour cela il applique des règles de
conversion implicite. Ces règles ont pour but la perte
du minimum d’information dans l’évaluation de
l’expression. Ces règles sont les suivantes:
Règle de Conversion Implicite
○ Convertir les éléments de la partie droite d’une expression
d’affectation dans le type de la variable ou de la constante le
plus riche.
○ Faire les opérations de calcul dans ce type.
○ Puis convertir le résultat dans le type de la variable affectée.
La syntaxe du langage C
règles suivantes :
1. si l’un des deux opérandes est du type long double alors le
calcul doit être fait dans le type long double ;
2. sinon, si l’un des deux opérandes est du type double alors le
calcul doit être fait dans le type double ;
3. sinon, si l’un des deux opérandes est du type float alors le
calcul doit être fait dans le type float ;
4. si l’un des deux opérandes est du type unsigned long int
alors le calcul doit être fait dans ce type ;
5. si l’un des deux opérandes est du type long int alors le
calcul doit être fait dans le type long int ;
La syntaxe du langage C
La syntaxe du langage C
long double
double
Float
unsigned long long
long long
unsigned long
long
unsigned int
int
Conversion implicite
Il est possible de forcer la conversion d’une variable (ou
La syntaxe du langage C
d’une expression) dans un autre type avant de l’utiliser
par une conversion implicite. Cette opération est
appelée “cast”.
cast Elle se réalise de la manière suivante :
(type) expression
Prenons pour exemple l’expression : i = (int) f + (int) d ;
f et d sont convertis en int, puis additionnés. Le résultat
entier est rangé dans i.
La syntaxe du langage C
float f ; double d ; int i ; long li ;
li = f + i ; i est transformé en float puis additionné à f,
le résultat est transformé en long et rangé dans li.
La syntaxe du langage C
utilisées avec les unités classiques d’entrées-sorties,
qui sont respectivement le clavier et l’écran.
Ces fonctions sont:
Getchar
Putchar
Puts
Printf
scanf
La syntaxe du langage C
La fonction getchar permet la récupération d’un seul
caractère à partir du clavier. La syntaxe d’utilisation de
getchar est la suivante : var=getchar();
Notez que var doit être de type char. Exemple :
#include <stdio.h>
void main() {
char c;
printf("Entrer un caractère:");
c = getchar();
printf("Le caractère entré est %c\n",c);
}
La syntaxe du langage C
permet l’affichage d’un seul caractère sur l’écran de
l’ordinateur. putchar constitue alors la fonction
complémentaire de getchar. La syntaxe d’utilisation est
la suivante : putchar(var);
où var est de type char. Exemple :
#include <stdio.h>
Void main() {
char c;
printf("Entrer un caractère:");
c = getchar();
putchar(c);
}
La syntaxe du langage C
Syntaxe : puts(ch);
Cette fonction affiche, sur stdout, la chaîne de
caractères ch puis positionne le curseur en début de
ligne suivante. puts retourne EOF en cas d’erreur.
Exemple :
#include <stdio.h>
void main() {
char * toto = "on est super content!";
puts(toto);
}
La syntaxe du langage C
La fonction printf est une fonction d’impression formatée, ce
qui signifie que les données sont converties selon le format
particulier choisi. Sa syntaxe est la suivante :
printf("chaîne de contrôle", expression1, . . . , expressionn);
La chaîne de contrôle contient le texte à afficher et les
spécifications de format correspondant à chaque expression
de la liste. Les spécifications de format ont pour but
d’annoncer le format des données à visualiser. Elles sont
introduites par le caractère %. Le i-ème format de la chaîne
de contrôle sera remplacé par la valeur effective de
expressioni.
La syntaxe du langage C
Les différents formats de la fonction printf
format Conversion en écriture
%d int décimale signée
%ld long int décimale signée
%u unsigned int décimale non signée
%lu unsigned long décimale non signée
%o unsigned int Octale non signée
%lo unsigned long Octale non signée
%x unsigned int Héxadécimal non signée
%lx unsigned long Héxadécimal non signée
La syntaxe du langage C
format Conversion en écriture
%f float décimale virgule fixe
%lf Long float décimale virgule fixe
%e Double décimale notation exponentielle
%le Long double décimale notation exponentielle
%g Double décimale, représentation la plus courte parmi
%f et %e
%lg Long double décimale, représentation la plus courte parmi
%lf et %le
%c unsigned char caractère
%s char* Chaîne de caractères
La syntaxe du langage C
Les différents formats de la fonction printf
Exemple
printf("|% d|\n",14); | 14|
printf("|% d|\n",-14); |-14|
printf("|%x|\n",0x56ab); |56ab|
printf("|%X|\n",0x56ab); |56AB|
printf("|%o|\n",14); |16|
printf("|%#o|\n",14); |016|
printf("|%10d|\n",14); | 14|
printf("|%f|\n",1.234567890123456789e5); |123456.789012|
printf("|%.4f|\n",1.234567890123456789e5); |123456.7890|
La syntaxe du langage C
Exemple
printf("|%e|\n",1.234567890123456789e5); |1.234568e+05|
printf("|%.4e|\n",1.234567890123456789e5); |1.2346e+05||
printf("|%.4g|\n",1.234567890123456789e-5); |1.235e-05|
printf("|%.4g|\n",1.234567890123456789e-3); |0.001235|
printf("|%.8g|\n",1.234567890123456789e5); |123456.79|
La syntaxe du langage C
saisies au clavier, dans le format spécifié. Ces données
sont stockées aux adresses spécifiées par les arguments
de la fonction scanf (on utilise donc l’opérateur
d’adressage & pour les variables scalaires). scanf
retourne le nombre de valeurs effectivement lues et
mémorisées .La syntaxe est la suivante :
scanf("chaîne de contrôle", arg1, . . . , argn);
La chaîne de contrôle indique le format dans lequel les
données lues sont converties. Comme pour printf, les
conversions de format sont spécifiées par un caractère
précédé du signe %.
La syntaxe du langage C
Exemple
#include <stdio.h>
void main()
{
int i ;
printf("entrez un entier sous forme hexadecimale i = ");
scanf("%x",&i);
printf("i = %d\n",i);
}
Les pointeurs
la mémoire. Les deux sont connectés par un bus, c'est-à-
dire un ensemble de lignes électriques
Mémoire(RAM) Adresses
rate
1000
Processeur 100 1004
Bus 1008
1009
1010
1014
Un octet = 8 bits 1018
Les pointeurs
installée sur votre ordinateurs.
Lorsqu’une variable est déclarée, le compilateur réserve un
emplacement mémoire (une série de bits qu’on ne lit/écrit pas
un par un mais par paquets de huit, ce que l'on appelle un octet
(byte).) avec une adresse unique pour stocker cette
variable(qu’on peut relire plus tard) .
Le compilateur associe l’adresse au nom de la variable. Quand
le programme utilise le nom de la variable, il accède
automatiquement à l’emplacement mémoire correspondant
Les pointeurs
L’adresse de cette variable rate est un nombre, ce qui nous permet
de l’utiliser comme n’importe quel autre nombre en langage C.
Si vous connaissez l’adresse d’une variable, vous pouvez créer une
autre variable pour y stocker l’adresse de la première.
La première étape consiste à déclarer la variable dans laquelle on
stockera l’adresse de rate.
Les pointeurs
? 100
p_rate rate
L’étape suivante consiste à stocker l’adresse de rate
dans la variable p_rate, celle-ci représente
maintenant l’emplacement mémoire de la variable
rate 1001 1002 1003 1004 1005
1004 100
p_rate rate
Déclaration
On déclare un pointeur par l’instruction :
Les pointeurs
type *nom_du_pointeur ;
Les pointeurs
en utilisant l’opérateur &, quand il est placé avant
le nom de la variable, l’opérateur d’adresse renvoie
l’adresse de cette variable. Son initialisation est une
instruction de la forme : pointeur=&variable;
Exemple 1 :
int A, B, *P; /*supposons que ces variables occupent
la mémoire à partir de l’adresse 1000 */
Les pointeurs
A = 10;
B = 50;
P = &A ; // se lit : mettre dans P l’adresse de A
B = *P ; /* se lit : mettre dans B le contenu de
la variable pointée par P */
*P = 20; /*mettre la valeur 20 dans la variable
pointé par P*/
P = &B; // P pointe sur B
void main()
{ int v=12;
int u=10;
Les pointeurs
int *vP; /*pointeur sur int*/
vP = &v; /*affectation du pointeur */
u = *vP;
printf(“u=%d v=%d\n”,u,v);
*vP = 25;
printf(“u=%d v=%d\n”,u,v);
printf(“*vP=%d”,*vP);
}
22/02/10 Programmer en langage C 138
Exemple 2 :
#include <stdio.h>
#include <conio.h>
Void main( )
{ float a , *p; /*supposons que ces variables sont représentées en
Les pointeurs
mémoire à partir de l’adresse 1000*/
clrscr( ); // pour effacer l’écran<conio.h>
p = &a;
printf(‘’Entrer une valeur : ‘’);
scanf(‘’%f’’ ,p); // on saisie la valeur 12.4
printf(‘’\nAdresse de a = %d Contenu de a = %f’’ ,p,*p);
*p += 0.4;
printf(‘’a = %f *p = %f ‘’, a,*p);
getch( ); // pour lire un caractère <conio.h>}
22/02/10 Programmer en langage C 139
Opérations élémentaires sur les pointeurs
L’opérateur & : ’adresse de’ : permet d’obtenir
l’adresse d’une variable.
L’opérateur * : ’contenu de’ : permet d’accéder au
Les pointeurs
contenu d’une adresse.
Si un pointeur P pointe sur une variable X, alors *P
peut être utilisé partout où on peut écrire X.
Exemple :
int X=1, Y, *P Après l’instruction, P = &X ; On a :
Y = X + 1 équivalente à Y = *P + 1
X += 2 équivalente à *P += 2
++X équivalente à ++ *P
X++ équivalente à (*P)++
22/02/10 Programmer en langage C 140
Opérations élémentaires sur les pointeurs
Le seul entier qui puisse être affecté à un pointeur d’un type
quelconque P est la constante entière 0 désignée par le
symbole NULL défini dans <stddef.h>.
On dit alors que le pointeur P ne pointe ’nulle part’.
Les pointeurs
Exemple :
#include <stddef.h>
int *t, x , *r;
short y = 10 , *pt = &y;
t = NULL ; /* Correct */
t = 0 ; /* Correct */
x=0;
t = x ; /* Incorrect ! bien que x vaille 0 */
r = &x ;
t = r ; /* Correct : p et q pointe sur des variables de même type*/
t = pt ; /* Incorrect : p et pt pointe sur des variable de type différent */
Les pointeurs
b) int x = 17 , *p = x; *p = 17 b) p = x est incorrect. Pour que
c) double *q; int x = 17 , *p; p pointe sur x :p = &x
p = &x; q =p; c) q = p incorrect. q et p deux
d) int x, *p; &x = p; pointeurs sur des types
différent
Les pointeurs
○ le nom T du tableau est un pointeur constant sur le premier élément
(1er entier) du tableau
○ T et &T[0] contiennent l’adresse du premier élément (1er entier) du
tableau.
Tableau à deux dimensions( int T[N][M]) :
○ le nom T est un pointeur constant sur le premier tableau d’entiers
○ T[i] est un pointeur constant sur le premier élément (1er entier) du
ième tableau.
○ T et T[0] contiennent la même adresse mais leur manipulation n’est
pas la même puisqu’ils ne représentent pas le même type de
pointeur.
Les pointeurs
= A crée une liaison entre le pointeur P et le tableau A en
mettent dans P l’adresse du premier élément de A (de même
P = &A[0]).
A partir du moment où P = A, la manipulation du tableau A
peut se faire par le biais du pointeur P. En effet
p pointe sur A[0] *p désigne A[0]
p+1 pointe sur A[1] *(p+1) désigne A[1]
..
p+(N-1) pointe sur A[N-1] *(p+N-1) désigne A[N-1]
Les pointeurs
{ float t[N] , *pt ;
int i ;
printf("Entrez %d entiers\n", N) ;
pt = &t[0] ; /* ou pt = t */
for (i = 0 ; i<N; i++)
scanf("%f", pt+i) ; /* pt+i pointe sur t[i] */
printf("\n Tableau lu : \n") ;
for (i = 0 ; i<N ; i++)
printf("%7.2f", *(pt+i)) ; /* *(pt+i) équivalente à pt[i]*/
}
22/02/10 Programmer en langage C 145
Exemple ( Lecture et Affichage d’un tableau
matérialisé par un pointeur)
/* Autre Solution sans déclarer la variable i */
#include <stdio.h>
#define N 10
Les pointeurs
void main()
{ float T[N] , *pt ;
printf("Entrez %d entiers\n", N) ;
for (pt = T ; pt<T+N; pt++)
scanf("%f", pt) ;
printf("\nTableau lu : \n") ;
for (pt = T ; pt<T+N; pt++)
printf("%7.2f", *pt) ;
}
22/02/10 Programmer en langage C 146
Pointeurs et tableaux à deux dimensions
En déclarant une matrice A de type int (int A[M][N]) et un
pointeur P sur des variables entières (int *P),
l’instruction P = A[0] crée une liaison entre le pointeur P et la
matrice A en mettent dans P l’adresse du premier élément de la
Les pointeurs
première ligne de la matrice A ( P = &A[0][0]). A partir du
moment où P = A[0], la manipulation de la matrice A peut se
faire par le biais du pointeur P. En effet :
p pointe sur A[0][0] et * p désigne A[0][0]
p+1 pointe sur A[0][1] et * ( p + 1 ) désigne A[0][1]
..
p+N pointe sur A[1][0] et * ( p + N ) désigne A[1][0]
p+N+1 pointe sur A[1][1] et * ( p + N + 1 ) désigne A[1][1]
..
p + M * N-1 pointe sur A[M-1][N-1] et * ( p + M * N -1 ) désigne
A[M-1][N-1]
Les pointeurs
{ short A[M][N] ;
short *pt ;
int i, j ;
/* lecture d’une matrice */
pt = &A[0][0] ; /* ou bien pt = A[0] ; */
for (i = 0 ; i<M ; i++)
{
printf("\t ligne n° %d\n", i+1) ;
for (j = 0 ; j<N ; j++)
scanf("%i", pt + i * N + j ) ;
} for (i = 0 ; i<M ; i++)
{ for (j = 0 ; j<N ; j++)
printf("%d", *( pt + i * N + j ) ) ;
printf("\n") ; }}
Les pointeurs
L’affectation : P1 = P2 ; fait pointer P1 sur le même
objet que P2.
Addition et soustraction d’un nombre entier :
Si P pointe sur l’élément A[i] d’un tableau, alors :
P+n pointe sur A[i+n] et P-n pointe sur A[i-n]
Les pointeurs
P += n ; P pointe sur A[i+n]
P-- ; P pointe sur A[i-1]
P -= n ; P pointe sur A[i-n]
Comparaison de deux pointeurs :
On peut comparer deux pointeurs de même type par :
<, >, <=, >=, == ou !=
La comparaison de deux pointeurs qui pointent dans le
même tableau est équivalente à la comparaison des
indices correspondants.
22/02/10 Programmer en langage C 150
Autres déclarations des pointeurs :
En C, il existe d’autres déclarations des pointeurs. En effet :
Tableau de pointeurs :
int *Tab[20] ;
Les pointeurs
déclare un tableau Tab de 20 pointeurs d’entiers.
Pointeur de tableaux :
int (*pt)[30] ;
déclare un pointeur pt sur des tableaux de 30
composantes.
Pointeur de pointeurs :
int **pt ;
déclare un pointeur pt qui pointe sur des pointeurs
d’entiers.
Les pointeurs
toujours l’espace maximal prévisible.
Il serait souhaitable que l’allocation de la mémoire
dépend du nombre d’éléments à saisir. Ce nombre ne
sera connu qu’à l’exécution : c’est l’allocation
dynamique.
Les pointeurs
○ char *realloc(char *, taille); //modification de la taille d’un bloc
○ void free(char *) ; //libération d’un bloc
Chacune des fonctions malloc, calloc ou realloc, prend une zone
d’une taille donnée dans l’espace mémoire libre réservé pour le
programme (appelé tas ou heap) et affecte l’adresse du début
de la zone à une variable pointeur.
S’il n’y a pas assez de mémoire libre à allouer, la fonction
renvoie le pointeurNULL.
malloc
<pointeur> = <type> malloc(<taille>);
○ <type> est un type pointeur définissant la variable pointé par
Les pointeurs
<pointeur>
○ <taille> est la taille, en octets, de la zone mémoire à allouer
dynamiquement, <taille> est du type unsigned int, donc on
ne peut pas réserver plus de 65536 octets à la fois
La fonction malloc retourne l’adresse du premier
octet de la zone mémoire allouée. En cas d’échec, elle
retourne NULL.
free
Si on n’a plus besoin d’un bloc de mémoire réservé
dynamiquement par malloc, alors on peut le libérer à
Les pointeurs
l’aide de la fonction free.
free(<pointeur>);
Libère le bloc de mémoire désigné par le pointeur
<pointeur>
Les pointeurs
{short *pt;
int N , i;
printf("Entrez la taille N du tableau \n") ;
scanf("%d", &N) ;
pt = ( short * ) malloc( N * sizeof( short ) );
if (pt == NULL)
{printf("Mémoire non disponible") ;
system("pause");
}
22/02/10 Programmer en langage C 156
Exemple (Allocation dynamique, Saisie et
Affichage d’un tableau )
Les pointeurs
scanf("%d", pt + i ) ;
printf("Affichage du tableau ") ;
for ( i= 0 ; i < N; i++)
printf("%d\t", *( pt + i ) ) ;
free( pt );
}
Explication de l’exemple 1
Les pointeurs
22/02/10 Programmer en langage C 158
Annexe A:
Gestion dynamique des tableaux
EXEMPLE :
/* Déclaration d'un pointeur sur des entiers p et de la taille du
tableau N */
Les pointeurs
int* p=NULL;
int N;
/* Saisie de la taille du tableau par l'utilisateur */
scanf ("%d",&N);
/* Allocation dynamique de la zone mémoire occupée par le
tableau */
p = (int*)malloc (N*sizeof(int));
Les pointeurs
Struct data {
int *valeur;
int *taux;
} premier;
Soit cout et interet de variable de type int tel que :
○ int cout, interet;
L’initialisation du pointeur valeur et taux suit la syntaxe
suivante :
○ premier.valeur=&cout;// (*premier.valeur=cout;)
○ premier.taux=&interet; // (*premier.taux=interet;)
Les pointeurs
float y;
}
On déclarera une variable de type pointeur vers cette structure
de la façon suivante :
○ struct point *p;
Pour initialiser ce pointeur, il faut déclarer une structure sur le
modèle struct point, sur laquelle il va pointer :
○ Struct point pnt;
○ p=&pnt;
Les pointeurs
soit (->) comme suit:
○ p ->num=1;
○ p ->x=1.2;
○ p ->y=2.5;
Les pointeurs
};
Nous pouvons déclarer un tableau appartenant au type part
○ struct part data[50];
Nous pouvons ensuite déclarer un pointeur vers une structure de
type part, et l’initialiser pour pointer sur la première structure du
tableau data:
○ struct part *p_part;
○ p_part=&data[0];// ou bien écrire p_part=data;
Nous obtenons un tableau de structures de type part et un pointeur
vers le premier élément du tableau. On affiche le contenu du premier
élément avec l’instruction:
printf(’’ %d %s ’’, p_part->nombre , p_part ->nom);
Les pointeurs
}data[Max]={1,’’smith’’,
2, ‘’jones’’,
3, ‘’Adams’’,
4,’’Wilson’’
};
Struct part *p_part;
int count;
void main(){
P_part=data;
For(count=0;count<Max;count++)
{ printf(‘’A l’adresse %d : %d %s\n’’,p_part,p_part->nombre,p_part->nom);
p_part++;}}
Les fonctions
code de la fonction. une fonction peut être appelée par une autre fonction.
Une fonction est indépendante : une fonction peut effectuer avec ou sans
échanges avec une autre partie du programme.
Une fonction réalise une tâche particulière : cela peut être l’envoi d’une ligne
de texte vers l’imprimante, un tri, ou le calcul d’une racine carrée.
Une fonction peut renvoyer une valeur au programme appelant: Quand ce
programme appelle la fonction, le code de cette fonction est exécuté. Ces
instructions peuvent renvoyer une information au programme.
Les fonctions
liste-d'instructions
}
Les fonctions
paramètres formels.
La liste-de-déclarationsoption : permet si besoin, de
déclarer des variables qui seront locales à la fonction,
elles seront donc inaccessibles de l'extérieur.
La liste-d'instructions: est l'ensemble des instructions
qui seront exécutées sur appel de la fonction. Parmi
ces instructions, il doit y avoir au moins une
instruction du type : return expression ;
Les fonctions
Sémantique :
Les expressions de liste-d'expressions sont évaluées,
puis passées en tant que paramètres effectifs à la
fonction de nom identificateur, qui est ensuite exécutée.
La valeur rendue par la fonction est la valeur de
l'expression appel de fonction.
Les fonctions
float x = 1.5 ;
float y, z ;
int n = 3, p = 5, q = 10 ;
/* appel de fexple avec les arguments x, n et p */
y = fexple (x, n, p) ;
printf ("valeur de y : %e\n", y) ;
/* appel de fexple avec les arguments x+0.5, q et n-1 */
z = fexple (x+0.5, q, n-1) ;
printf ("valeur de z : %e\n", z) ;
}
Les fonctions
float val ; /* déclaration d’une variable "locale" à fexple
val = x * x + b * x + c ;
return val ;
}
#include<stdio.h>
/* déclaration de la fonction cube*/
long cube(long x); /* prototype de la fonction cube */
/****************************************************/
Les fonctions
long input, reponse;
void main()
{
printf("entrez une valeur entière : ");
scanf("%ld",&input);
reponse=cube(input);
printf("\n\n le cube de %ld est %ld\n", input, reponse);
}
/* définition de la fonction */
Les fonctions
{ /*attention pas de ; */
long x_cube; /* variable “locale” à la fonction cube */
x_cube= x*x*x;
return x_cube;
}
Les fonctions
int p ;
p = arrondi (v1) ; printf (“%d\n”, p) ;
p = arrondi (v2) ; printf (“%d\n”, p) ;
printf (“%d %d\n”, arrondi(v1+v2), arrondi(v1) + arrondi(v2) ) ;
}
int arrondi (float r)
{ float y ;int n ;
y = r + 0.5 ;
n=y;
return n ;
}
Les fonctions
int max (int a, int b, int c)
{ int m ;
m=a;
if ( b>m ) m = b ;
if ( c>m ) m = c ;
return m ;
}
/*programme principal*/
void main()
Les fonctions
{ int max (int, int, int) ; /* prototype de notre fonction max */
int n, p, q, m ;
n=3;p=5;q=2;
m = max (n, p, q) ;
printf (“max de %d %d %d : %d\n”, n, p, q, m) ;
m = max (5*n, n+p, 12) ;
printf (“valeur : %d\n” , m) ;
}
Les fonctions
printf (“il fait beau\n”) ;
}
Son en-tête montre qu’elle comporte un paramètre entier
(nommé nfois) ; cette fois, il est précédé du mot void qui
indique que la fonction ne fournit pas de résultat.
Si l’on examine les instructions du corps de la fonction, on
constate qu’elles affichent un certain nombre de fois le
même texte : il fait beau. Pour effectuer son travail, notre
fonction a eu besoin d’une variable locale (i).
Remarques:
Aucune instruction return ne figure dans la définition
de notre fonction.
Les fonctions
y = optimist (k) ; /* incorrect */
l’appel de cette fonction ce fait à l’aide d’une instruction
de la forme :
optimist (k) ; /* instruction simple provoquant
l’appel de optimist à laquelle on
transmet en paramètre, la valeur de k */
Les fonctions
optimist (p) ;
optimist (n+p) ;
}
void optimist (int nfois)
{ int i ;
for (i=0 ; i<nfois ; i=i+1)
printf (“il fait beau\n”) ;
}
Les fonctions
int fexple1 (void)
Sa déclaration (prototype) serait:
int fexple1 (void) ;
L’en-tête d’une fonction ne recevant aucun paramètre
et ne fournissant aucun résultat est:
void fexple2 (void)
Son prototype est:
void fexple2 (void) ;
Les fonctions
et non simplement : fexple1
Exemple :
#include<stdio.h>
Void affiche(void);
Void main()
{ affiche();}
Void affiche(void)
{ printf(‘’bonjour’’);}
Les fonctions
(de l’anglais : formal parameter). Leur rôle est de
permettre, au sein du corps de la fonction, de décrire ce
qu’elle doit faire.
Les arguments fournis lors de l’utilisation (l’appel) de la
fonction se nomment des « arguments effectifs » (ou
encore « paramètres effectifs »).
Les fonctions
{ return (x * x + b * x + c) ;}
L’instruction return peut apparaître à plusieurs
reprises dans une fonction, comme dans cet autre
exemple :
○ double absom (double u, double v)
{ double s ;
s=a+b;
if (s>0) return (s) ;
else return (-s);
}
Les fonctions
En ce qui concerne son emplacement, le prototype peut
figurer :
soit parmi les différentes déclarations situées au début d’une
fonction (y compris main) ; il n’est alors connu que dans la
dite fonction ; c’était le cas dans les exemples rencontrés
jusqu’ici ;
soit avant toutes les définitions de fonctions, à un niveau
global (comme les variables globales dont nous parlerons un
peu plus loin) ; dans ce cas, il est utilisable par toutes les
fonctions du programme.
Les fonctions
fonction. Par exemple, avec cette définition :
void affiche (void)
{ int n = 10 ;
printf (“%d”, n) ;
n=n+1;
}
on obtiendra l’affichage de la valeur 10, à chaque appel
de affiche.
Les fonctions
.....
f1 (...) ; /* appel de f1 */
.....
}
int f1 (float)
{ void f2 (int) ; /* prototype de f2 */
.....
f2 (...) ;
.....
}
22/02/10 Programmer en langage C 186
En langage C, les paramètres sont transmis
par valeur
void main(){
void echange (int a, int b) ;
int n=10, p=20 ;
Les fonctions
printf (“avant appel : %d %d\n”, n, p) ;
echange (n, p) ;
printf (“après appel : %d %d”, n, p) ; avant appel : 10 20
} début echange : 10 20
void echange (int a, int b) fin echange : 20 10
{ int c ; après appel : 10 20
printf (“début echange : %d %d\n”, a, b) ;
c=a;a=b;b=c;
printf (“fin echange : %d %d\n”, a, b) ;
}
22/02/10 Programmer en langage C 187
En langage C, les paramètres sont transmis
par valeur
La fonction echange reçoit deux valeurs correspondant à ses
deux paramètres muets a et b. Elle effectue un échange de ces
deux valeurs. Mais, lorsque l’on est revenu dans le programme
Les fonctions
principal, aucune trace de cet échange ne subsiste sur les
paramètres effectifs n et p.
En effet, lors de l’appel de echange, il y a eu transmission de la
valeur des expressions n et p. On peut dire que ces valeurs ont
été recopiées “localement” dans la fonction echange dans des
emplacements nommés a et b. C’est effectivement sur ces copies
qu’a travaillé la fonction echange, de sorte que les valeurs des
variables n et p n’ont, quant à elles, pas été modifiées. C’est ce
qui explique le résultat constaté.
Solutions :
Transmettre en paramètre la “valeur” de l’“adresse”
Les fonctions
d’une variable. La fonction recevra, certes, toujours une
copie de cette adresse, mais elle pourra éventuellement
agir sur ce qui se trouve à cette adresse. Ceci est possible
grâce aux “pointeurs”.
Utiliser des “variables globales”.
Les fonctions
pointeur.
Exemple:
void add(int a, int b, int *c) {
/* c repère l’entier où on veut mettre le résultat */
*c = a + b;}
void main() {
int i=10,j=14,k;
/* on passe les valeurs de i et j comme premiers paramètres */
/* on passe l’adresse de k comme troisième paramètre */
add(i,j,&k);}
Les fonctions
void main(){
int x=2, y=4, z=6;
par_valeur(x,y,z);
par_adresse(&x,&y,&z); }
void par_valeur(int a, int b, int c)
{a=0;b=0;c=0;}
void par_valeur(int *a, int *b, int *c)
{*a=0;*b=0;*c=0;}
Les fonctions
echange (&n, &p) ;
printf (“après appel : %d %d”, n, p) ; avant appel : 10 20
} début echange : 10 20
void echange (int *a, int *b) fin echange : 20 10
{ int c ; après appel : 20 10
printf (“début echange : %d %d\n”, *a, *b) ;
c = *a ; *a = *b ; *b = c ;
printf (“fin echange : %d %d\n”, *a, *b) ;
}
22/02/10 Programmer en langage C 192
Passage de tableau en paramètre
Tableau à une dimension de taille fixe
void main()
{ int i ;
int t[5] = { 1, 1, 1, 1, 1 } ; /* initialisation du tableau */
void affiche (int [5]) ; /* prototype de la fonction affiche */
Les fonctions
printf (“tableau t avant appel de affiche : ”) ;
for (i=0 ; i<5 ; i=i+1) printf (“%d ”, t[i]) ;
printf (“\n”) ;
affiche (t) ; /* appel de affiche, à laquelle on transmet en paramètre le tableau t
*/
printf (“tableau t après appel de affiche : ”) ;
for (i=0 ; i<5 ; i=i+1) printf (“%d ”, t[i]) ;
}
void affiche (int v[5])
{ int i ;
for (i=0 ; i<5 ; i=i+1)
v[i] = i+1 ;}
Les fonctions
○ l’appel affiche (t) provoque la transmission à la fonction
affiche, de la valeur du paramètre t c’est-à-dire en fait de
l’adresse du tableau t (il y a bien toujours mécanisme de
transmission par valeur, mais cette valeur se trouve être celle
d’une adresse) ;
○ dans la fonction affiche, à chaque appel, le symbole t est
remplacé par sa “valeur”, c’est-à-dire en l’occurrence l’adresse
reçue en paramètre ; ainsi, une affectation telle que : v[i] = 0 ;
est traduite en : affecter au i-ème entier, à partir de l’adresse
v, la valeur 0.
Les fonctions
tab[i] = i;
}
void main()
{ int i, n = 5;
int *tab;
tab = (int*)malloc(n * sizeof(int));
init(tab,n);
for(i=0;i<n;i++) printf(‘’ %d\n’’,*tab++);
}
Les fonctions
for (j=0 ; j<4 ; j++)
t[i][j] = 1 ;
}
Voici quelques exemples d’utilisation de cette fonction :
void main ()
{ int tab [5] [4] ;
mat (tab) ;
}
Les fonctions
préciser le nombre de lignes :
void mat (int t[][3])
En revanche, il n’est pas possible de l’écrire :
void mat (int t[][])/* en-tête incorrect */
Les fonctions
}rec;
void affiche_rec(struct data x);
void main(){
printf("Entrez le montant du don\n");
scanf("%f",&rec.montant);
printf("Entrez le nom et le prénom du donateur\n");
scanf("%s %s", rec.lnom,rec.fnom);
printf("**********************\n");
affiche_rec(rec);
}
void affiche_rec(struct data x)
{ printf("\n le donateur %s %s a donné %.2f dh\n", x.lnom, x.fnom, x.montant);
}
Les fonctions
} data[MAX]={{1,"Smith"},{2,"Jones"},{3,"Adams"},{4,"Wilson"}};
void affiche_str(struct personne [MAX]);
void main(){
affiche_str(data);
}
void affiche_str(struct personne x[MAX])
{int i;
for(i=0; i<MAX;i++)
printf("%d \t %s \n", x[i].numero,x[i].nom);
}
Les fonctions
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).
Exemple
long fac (int n)
{
if (n>1) return (fac(n-1)*n) ;
else return(1) ;
}
Les fonctions
22/02/10 Programmer en langage C 201
Fonctions prédéfinies : math.h
Les fonctions
22/02/10 Programmer en langage C 202
•Définition
•Déclarations
•Chaînes de caractères constantes(chaînes littérales)
•Tableaux de caractères
•Chaînes et pointeurs
•Ordre alphabétique et lexicographique
•Manipulation des chaînes de caractères
Fonctions de <string.h>
size_t strlen(const char * chaine);
#include <string.h>
#include <stdio.h>
void main() {
char m1[60] = "Ecole Nationale";
char *m2 = " de l'Aviation Civile";
strcat(m1, m2); printf("%s\n", m1); }
/* résultat de l'exécution: Ecole Nationale de l'Aviation Civile*/
Fichiers
Pour pouvoir manipuler un fichier, un programme a besoin
d’un certain nombre d’informations : l’adresse de l’endroit
de la mémoire-tampon où se trouve le fichier, la position
de la tête de lecture, le mode d’accès au fichier (lecture ou
écriture)
Ces informations sont rassemblées dans une structure,
dont le type est FILE *. Ce type est défini dans <stdio.h>.
Un objet de type FILE * est appelé flot de données (stream
en anglais).
Fichiers
Principe de manipulation d’un fichier:
Ouverture du fichier
Lecture, écriture et déplacement dans le fichier
Fermeture du fichier
Deux techniques pour manipuler un fichier
L’accès séquentiel : pour atteindre l’information souhaité, il faut
passer par la première puis la deuxième et ainsi de suite.
L’accès direct : consiste à se déplacer directement sur l’information
souhaité sans avoir à parcourir celles qui la précédent.
Fichiers
Le buffer une zone de la mémoire centrale qui
stocke une quantité, assez importante, de données
du fichier.
Son rôle est d’accélérer les entrées/sorties à un
fichier.
Fichiers
Fichiers standards : se sont des fichiers spéciaux
prédéfinis qui s’ouvrent automatiquement lorsqu’un
programme commence à s’exécuter :
Stdin (standard input): entrée standard(par défaut, lié au
clavier)
Stdout (standard output): sortie standard(par défaut, lié à
l’écran)
Stderr stderr (standard error) : affichage des messages
d’erreur (par défaut, à l’écran).
22/02/10 Programmer en langage C 225
Déclaration d’un fichier
FILE *<pointeurfichier>;
Le type file est défini dans <stdio.h> en tant que structure. A
l’ouverture d’un fichier, la structure FILE contient un
certain nombre d’informations sur ce fichier telles que :
Adresse de la mémoire tampon,
Fichiers
Position actuelle dans le tampon,
Nombre de caractères déjà écrits dans le tampon,
Type d’ouverture du fichier,…
Pour travailler avec un fichier dans un programme, il faut
ranger l’adresse de la structure FILE dans le pointeur de
fichier et tout accès ultérieur au fichier se fait par
l’intermédiaire de ce pointeur.
Fichiers
fopen("nom-de-fichier","mode");
Sémantique des paramètres
Le premier argument de fopen fournit donc le nom du
fichier.
Le second argument, mode, est une chaîne de caractères
qui spécifie le mode d’accès au fichier.
Fichiers
contrôle (retour à la ligne...) seront interprétés en tant
que tels lors de la lecture et de l’écriture ;
Fichiers
"a" ouverture d’un fichier texte en écriture à la fin
"r+" ouverture d’un fichier texte en lecture/écriture
"w+" ouverture d’un fichier texte en lecture/écriture
"a+" ouverture d’un fichier texte en lecture/écriture à la fin
Fichiers
contenu est perdu.
Si le mode contient la lettre a, le fichier peut ne pas exister.
Comme pour le cas précédent, si le fichier n’existe pas, il est
créé ; si le fichier existe déjà, son ancien contenu est conservé.
Si un fichier est ouvert en mode ”écriture à la fin” toutes les
écritures se font à l’endroit qui est était la fin du fichier lors de
l’exécution de l’ordre d’écriture. Cela signifie que si plusieurs
processus partagent le même FILE*, résultat de l’ouverture
d’un fichier en écriture à la fin, leurs écritures ne s’écraseront
pas mutuellement.
Fichiers
if ((fp = fopen("donnees.txt","r")) == NULL)
{
fprintf(stderr,"Impossible d’ouvrir le fichier données en
lecture\n");
exit(1);
}
Fichiers
fonction fopen correspondante.
La fonction fclose retourne
0 si l’opération s’est déroulée normalement et
EOF si il y a eu une erreur.
Exemple :
FILE *fp;
fp = fopen("donnees.txt","r")
fclose(fp);
Fichiers
où nom_du_fichier est le flot retourné par la fonction
fopen.
Les spécifications de format utilisées pour la fonction
fprintf sont les mêmes que pour printf
Puisque
printf(...) ⇐⇒ fprintf(stdout,...)
Expressioni est une expression délivrant une valeur à
écrire.
22/02/10 Programmer en langage C 233
La fonction de saisie en fichier : fscanf
La fonction fscanf, analogue à scanf, permet de lire des
données dans un fichier.
Sa syntaxe est semblable à celle de scanf :
fscanf(nom_du_fichier, "format", adresse1, . . . ,
adressen);
Fichiers
où nom_du_fichier est le flot de données retourné par
fopen.
Les spécifications de format sont ici les mêmes que celles
de la fonction scanf.
Adressei : adresse des variables à affecter à partir des
donner.
Un format et une adresse doivent être fournis pour
chaque variable.
22/02/10 Programmer en langage C 234
Programme: Exemple
#include<stdio.h>
Void main(){
FILE *pf;
int i=100;
Fichiers
char=‘c’;
float t=1.234;
pf=fopen(’’essai.txt’’,w+); /*ouverture et mise à jour*/
fprintf(pf,’’%d %c %f ’’,i,c,t);
fscanf(pf,’’%d %c %f’’,&i,&c,&t);
fprintf(pf,’’%d %c %f,i,c,t);
fclose(pf);
}
22/02/10 Programmer en langage C 235
Lecture et écriture par caractère : fgetc et
fputc
Similaires aux fonctions getchar et putchar les
fonctions fgetc et fputc permettent respectivement de
lire et d’écrire un caractère dans un fichier.
La fonction fgetc retourne le caractère lu dans le
Fichiers
fichier et la constante EOF lorsqu’elle détecte la fin du
fichier. Sa syntaxe est :
int fgetc(pf); /*où pf est de type FILE* */
La fonction fputc écrit un caractère dans le flot de
données . Sa syntaxe est :
fputc(int caractere, FILE *flot)
Elle retourne l’entier correspondant au caractère lu
(ou la constante EOF en cas d’erreur).
Fichiers
// Ouverture du fichier ENTREE en lecture
if ((f_in = fopen(ENTREE,"r")) == NULL)
fprintf(stderr, "\nErreur: Impossible de lire %s\n",ENTREE);
// Ouverture du fichier SORTIE en ecriture
if ((f_out = fopen(SORTIE,"w")) == NULL)
fprintf(stderr, "\nErreur: Impossible d’ecrire dans %s\n",SORTIE);
// Recopie du contenu de ENTREE dans SORTIE
while ((c = fgetc(f_in)) != EOF)
fputc(c, f_out);
// Fermeture des flots de donnees
fclose(f_in);
fclose(f_out);
}
Fichiers
TheFic = fopen ("esai.txt", "r"); /*doit être créé avant compilation*/
TheFic1 = fopen ("esai1.txt", "w");
if (TheFic == NULL)
printf ("Impossible d ouvrir le fichier \n");
/*char *fgets(char *, int , FILE *) ;*/
Fichiers
autres.
Il est également possible d’accéder à un fichier en mode
direct, c’est-à-dire que l’on peut se positionner à
n’importe quel endroit du fichier.
La fonction fseek permet de se positionner à un endroit
précis.
Fichiers
La variable deplacement détermine la nouvelle position
dans le fichier. Il s’agit d’un déplacement relatif par
rapport à origine, compté en nombre d’octets.
La variable origine peut prendre trois valeurs :
1. SEEK_SET (égale à 0) : début du fichier ;
2. SEEK_CUR (égale à 1) : position courante ;
3. SEEK_END (égale à 2) : fin du fichier.
Fichiers
ftell
long ftell(FILE *flot);
retourne la position courante dans le fichier (en nombre
d’octets depuis l’origine).