Académique Documents
Professionnel Documents
Culture Documents
1
Contenu du cours :
2
Sommaire
.
3
Structure générale d’un
programme C :
4
Structure d’un programme C :
La fonction main() ( dont le nom est imposé) est la seule fonction obligatoire d’un programme C. Elle
renferme la partie principale d'un programme.
Un programme C peut utiliser deux types de fonctions : les fonctions bibliothèques qui sont fournies par
le compilateur et les fonctions utilisateur qui sont créés par le programmeur.
Un bloc est délimité par des accolades ’’{‘’ et ‘’}’’. Il peut lui-même contenir d’autres blocs.
<------bloc------------->
entête-Fonction { .............{.......}...{...{.......}..........}.......................}
Tout programme C doit commencer par l’instruction d’appel #include indiquant au compilateur C qu’il
doit inclure le contenu de certains fichiers pendant la compilation
Exemple
#include <stdio.h> signifie ajouter le contenu du fichier <stdio.h> de la bibliothèque standard du
compilateur C. Ce fichier définit les fonctions se rapportant aux entrées-sorties .
Exemple de programme C :
#include <stdio.h>
void main()
{ printf ( “hello”);
}
printf est une fonction de la bibliothèque stdio.h qui affiche des information à l’écran.
4- Les constantes
5
5- Les variables et les tableaux
6- Les déclarations
7- Les expressions
8- Les instructions.
1- Les lettres de A à Z et de a à z .
2- Les chiffres de 0 à 9
3- Les caractères : + - * / %
4- Les caractères jouant le rôle de séparateurs: ( ) [ ] { } ; < > + ! ? & # ` `` .
` : + = ?
5- C utilise aussi certaines combinaisons de ces caractères.
1) les identificateurs
Les identificateurs servent à identifier les différents objets manipulés par le programme
( variables, tableaux, fonctions, étiquettes ...).
Exemple :
X
Somme_1
_temp
x
Les mots sont des noms réservés par le langage et ne peuvent pas être utilisés comme
identificateurs par le programmeur.
6
auto default float register struct
break do for return switch while
case double goto short typedef
char else if signed union
const enum int sizeof unsigned
continue extern long static void
Remarque :
Le langage supporte plusieurs types de données. Chacun des types peut être représenté différemment en
mémoire.
Les types de base du langage C se répartissent en 3 grandes catégories :
Le type entier ( mot clé int) correspond à la représentation des nombres entiers relatifs.
Le type flottant ( mot clé float ou double) représente les nombres réels.
Les types de base sont les types simples à partir desquels pourront être construits tous les autres types
tels que : les types structurés ( tableaux, structures...) et d’autres types simples ( pointeurs).
1) Le type entier
7
short int (abrégé short)
int
long int (abrégé long)
Chacun de ces types peut être signé ou pas . Il est précédé du mot clé unsigned ou signed.
Chaque type n’a pas la même taille en mémoire .
2) Le type flottant
float
double
long float
long double
L'erreur de troncature due à une représentation approchée d'un nombre réel ne dépasse pas : 10-6
pour le type float
10-10 pour le type long double
Dans le premier cas , on gagne en place et en contrepartie on perd en précision, inversement pour le
second type.
3) Le type caractère
On distingue :
les caractères imprimables qui se notent en écrivant entre quote le caractère voulu :
Les caractères non imprimables qui ont une fonction particulière. Ils se notent en faisant précéder le
caractère voulu de `` \ `` ( backslash)
CARACTERE FONCTION
\b backspace
\n new line
\f form feed
\t horizontal tabulation
\v vertical ------
\r carriage return ( retour chariot)
\\ \ (backslash)
\` ` (apostrophe)
\`` ``( quote)
\? ?
\0 null ( fin d’une chaine de caractères)
8
Représentation en mémoire des différents types :
Les constantes
Une constante représente une valeur d’un type donné dans un programme.
Il y a 4 types de constantes :
1432
- 056
b) représentation octale :
Le premier chiffre doit être un 0 (zéro).
c) représentation hexadécimale :
la constante doit commencer par 0x
9
0xff ( vaut 255 en décimal).
Un chaîne de caractères est constituée dune séquence de caractères délimitée par des double quotes
`` .........``.
Toute de chaîne de caractères se termine en mémoire par le caractère null (\0) généré automatiquement
par le compilateur.
``A`` ( différent du caractère `A` ) car elle est représentée sur 2 octets.
``\t to continue, press the \``Return \``key \n`` qui sera interprété par
Une constante symbolique est un nom qui substitue une séquence de caractères dans un
programme C.
La séquence de caractères peut représenter :
10
• une constante numérique
• une constante caractère
• une chaîne de caractère
• A la compilation du programme C, chaque occurrence de la constante symbolique est remplacée par
la séquence de caractères correspondante.
Exemple:
#include<stdio.h>
#define TAXE 0.34
#define TRUE 1
#define PAYS ``canada``
void main()
{
int c;
c = true ;
printf(``%f``, TAXE);
printf( "%s", PAYS)
}
Les constantes énumérées permettent de créer de nouveaux types puis de définir des variables dont
l’intervalle des valeurs est délimité.
par exemple, le type couleurs sera associé aux valeurs suivantes: rouge, noir, blanc, vert, et bleu.
Le mot clé enum permet de définir ce nouveau type dont le domaine des valeurs sera défini par
énumération
A chaque constante correspond une valeur entière qui est soit définie explicitement soit 0,1,2 en
fonction de sa position dans l’énumération
11
Les variables et les tableaux
Une variable est un identificateur qui est utilisé pour représenter une donnée d'un certain type
( numérique ou caractère) dans un programme C.
• On doit lui associer un certain type qui ne doit pas changer ( déclaration de la variable).
Exemple :
enum couleurs { rouge , noir, bleu, vert, blanc};
int a, b; ( variables entières)
char c; ( variable caractère)
couleurs clr ;
• Dans le programme, on doit lui affecter des valeurs du même type.
b = 5;
a = 3;
c = `A`;
a = a + b;
clr = rouge ;
Un tableau est un autre type de variable qui est utilisé pour représenter une collection de
données de même type.
Exemple :
Si X est un tableau de 10 éléments.
Le premier élement du tableau est noté X[0]
Le 10ème élément du tableau est noté X[9]
• Les tableaux à une dimension de type caractère sont utilisés pour représenter les chaînes de
caractères. Chaque élément du tableau représente un caractère de la chaîne.
• Une chaîne de n caractères est représentée par un tableau de n+1 éléments ( le n+1 ième élément
correspond au caractère null de fin de chaîne ).
tab[5]= `a`
tab[6]= `null`
12
Les déclarations dans C:
Dans C, toutes les variables doivent être déclarées avant leur manipulation dans les instructions.
Une déclaration est formée d’un type suivi d’un ou plusieurs noms de variables séparés par des virgules.
Exemple:
int a,b;
char c,text[80];
float r;
Int i;
unsigned x; ( entier positif)
Dans une déclaration, on peut assigner une valeur initiale à une variable.
int a = 13;
const int b = 6; /* la valeur de b ne doit pas changer */
char c = `*`;
char text[ ] = ``canada``; // equivalent à char text[ 7 ] = ``canada``;
float r = 0;
Les expressions
Exemple :
int a,b;
int x,y;
a + b est une expression arithmétique qui fait la somme des valeurs entières de
a et b.
x <= y est une expression logique qui prend la valeur 1 (true) si la valeur de x
est inférieure ou égale à la valeur de y, et 0 (false) sinon.
13
i++ ( i=i+1) incrémente de 1 la valeur de i .
Les instructions
Exemple
{ a = 3;
c= 2 * a;
printf ( ``%f``,c);
}
14
Les opérateurs et les expressions
dans le langage C.
15
Les opérateurs et les expressions dans le langage C.
De façon générale, une expression est une combinaison d’opérateurs et d’opérandes dont le résultat est
une valeur.
L’expression possède une valeur mais peut réaliser une affectation à une variable. Car les opérateurs
d’affectation et d’incrémentation peuvent non seulement intervenir dans une expression ( qui aura une
valeur ) mais agir sur le contenu des variables.
Exemple:
++i est une expression qui réalise une action: incrémenter la valeur de i.
Elle aura comme valeur, la valeur de i aprés incrémentation.
i = 5 est une expression de valeur 5 qui réalise une action : affecter à i la valeur 5.
Quand une expression possède plusieurs opérateurs, l’ordre dans lequel les opérations sont effectuées est
important.
Le but de ce chapitre est de présenter les opérateurs définis dans le langage C avec les règles de priorité
et de conversion de type intervenant dans les évaluations d’expressions.
16
II-1 Les opérateurs arithmétiques:
On distingue:
+ addition
- soustraction
/ division
* multiplication
% . reste de division entière (modulo)
• Les opérateurs binaires ne sont définis que sur deux opérandes ayant le même type : ( int,
long int, float, double,long double ). Ils fournissent le même type que leurs opérandes.
Exemple :
Expression sa valeur
a+b 13
a–b 7
a*b 30
a /b 3
a%b 1
Etant données v1 et v2 deux variables de type flottant et dont les valeurs respectives sont 12.5 et 2.0.
Expression sa valeur
v1 + v2 14.5
v1 – v2 10.5
v1 * v2 25.0
v1 / v2 6.25
Etant donnés c1 et c2 de type caractère représentant respectivement les caractères ‘P’ et ‘T’.
17
Expression sa valeur
c1 80 ( code ASCII de P)
c2 84 ( code ASCII de T)
c1 + c2 164
c1 + c2 + 5 169
c1 + c2 + `5` 215
Lorsque plusieurs opérateurs arithmétiques apparaissent dans une expression, il est nécessaire de savoir
dans quel ordre ils sont mis en jeu.
L’ordre de priorité des opérateurs arithmétiques est le suivant:
* / %
+ - moins prioritaire
Une conversion de type suit un certain ordre qui permet de ne pas dénaturer la valeur initiale.
int ---> long ---> float ---> double ---> long double
Cet ordre permet de convertir par exemple, int en long ou double ou long double mais l’inverse n’est
pas possible.
Exemple:
int n;
long p;
float x;
Les opérateurs arithmétiques ne sont pas définis pour le type short et char. Le langage C prévoit que
toute valeur de l’un de ces types apparaissant dans une expression, est d’abord convertie en int. On
parle alors de promotion numérique.
Exemple
19
Cas du type char:
La promotion numérique permet de considérer le code du caractère ( sur 8 bits) comme la valeur de ce
caractère.
Dans ce cas, le langage C confond un caractère avec la valeur ( entier) du code qui le représente.
Remarque :
La valeur entière associée à un caractère donné n’est pas le même sur toutes les machines.
Exemple
Le résultat de la comparaison est une valeur entière de valeur 1 ( si le résultat est vrai) ou 0 ( si le
résultat est faux).
Cette expression faisant intervenir des opérateurs de comparaison , sera alors de type entier et donc
pourra intervenir dans des calculs arithmétiques.
< Inférieur à
> Supérieur à
== égal à
!= Différent de
20
< , > , <= , >= ( plus haute priorité )
= = , et != ( moins prioritaire)
• Les opérateurs relationnels sont moins prioritaires que les opérateurs arithmétiques.
Exemple1:
int a,b,c,d;
a<b==c<d
l’expression a < b est de type entier; elle prend la valeur 1 ou 0.
c < d est de type entier; elle prend la valeur 1 ou 0.
Suivant les valeurs de (a < b ) et de ( c< d ) , l’expression donnée aura comme valeur 1 ou 0.
Exemple2:
int x, y, a;
L’expression x + y < a permet de comparer la valeur de l’expression ( x + y ) et la valeur de a.
Le résultat sera 1 ou 0.
Remarque importante:
Une comparaison peut porter sur sur 2 caractères
a) cas de comparaison d’égalité:
( l’existence d’une conversion de promotion numérique char ---> int n’a guère d’influence).
char c1,c2;
c1 = = c2 est vraie ( a la valeur 1) si c1 et c2 ont la même valeur ou bien c1 et c2
contiennent des caractères de même code ( le même caractère).
char c1,c2;
c1 < c2 est vraie si le code du caractère c1 a une valeur inférieure au code du caractère c2.
Le résultat dépendra du codage employé.
II-3 Les opérateurs logiques:
&& et logique
|| Ou
! non
A priori ,les opérateurs logiques ne portent que sur des opérandes qui sont eux-mêmes des expressions
logiques.
21
Mais, ils acceptent des opérandes numériques ( types int et float) avec les règles de conversion
implicites.
Dans ce contexte, on considère que :
La valeur nulle ( 0 ) correspond à faux
0 && 0 0
0 && Valeur non nulle 0
Valeur non nulle 0 0
Valeur non nulle && Valeur non nulle Valeur non nulle
0 || 0 0
Valeur non nulle || 0 Valeur non nulle
0 || Valeur non nulle Valeur non nulle
Valeur non nulle || Valeur non nulle Valeur non nulle
! plus prioritaire
&&
|| moins prioritaire
• les opérateurs arithmétiques sont plus prioritaires que les opérateurs logiques.
• L’opérateurs ! ( not) a une priorité supérieure à celle de tous les opérateurs arithmétiques
binaires et opérateurs relationnels.
Exemple1:
int a,b,c,d;
! a == b équivaut à (! a) == b
22
int n,p;
Remarque:
• Le second opérande de l’opérateur && n’est pas évalué si le premier opérande a été évalué á
0 car l’expression complète aura la valeur 0 ( faux).
• Le second opérande de l’opérateur || n’est pas évalué si le premier opérande a été évalué à
vrai ( valeur non nulle) car l’expression complète aura la valeur 1 (vrai).
Exemple2 :
int i = 7;
float f = 5.5;
char c = ‘w’;
L’expression valeur
( i >= 6 ) || ( c = = 119 ) 1
( c != ‘p’ ) || ( i + f <= 10 ) 1
Exemple 3 :
int i = 7;
float f = 5.5;
L’expression valeur
F> 5 1
!(f>5) 0
! ( i > f + 1) 0
23
II-4 Les opérateurs d’affectation :
La partie gauche de l’opérateur d’affectation `` = `` doit être une lvalue (left value).
lvue est une expression à laquelle on peut affecter une valeur.
Les variables sont des lvalues.
La partie à droite de l’opérateur est une expression dont la valeur est affectée à la lvalue.
• La priorité de cet opérateur est inférieure à celle de tous les opérateurs arithmétiques et les
opérateurs de comparaison.
Exemple :
int i ;
int j =3;
24
• un opérateur de pré-incrémentation, s’il est placé à gauche de la `` lvalue`` sur laquelle il
porte. La valeur de l’expression d’incrémentation est celle dela ``lvalue`` après
incrémentation.
Exemple:
int i = 5;
i++ équivaut à i = i + 1
i devient égale à 6
la valeur de cette expression est 5
++i équivaut á i = i + 1
i devient égal á 6
la valeur de cette expression est 6.
Exemple:
int i = 4 ;
--i; équivaut à i = i - 1
i devient égale à 3
la valeur de cette expression est 3.
i--; équivaut à i = i - 1
i devient égale à 3
la valeur de cette expression est 4.
Ces opérateurs sont de plus haute priorité que les opérateurs arithmétiques.
25
Exemple:
int i, j, k ;
L’expression 3 * i++ * j-- + k++ équivaut à 3 * (i++)n* (j--) + ( k++).
Si t est un tableau :
t[ i++] = 1 permet d’initialiser tous les éléments du tableau
_ affecte la valeur 1 à t[ 0]
_ puis incrémente de 1 la valeur de i.
Exemple:
int i,k;
i += k équivaut à i = i + k
i *= k équivaut à i = i * k.
Le programmeur peut forcer la conversion d’une expression quelconque dans un type de son
choix à l’aide de l’opérateur `` cast ``.
Exemple:
int n , p;
26
• Sa priorité est élevée par rapport aux autres opérateurs.
• Toutes les conversions numériques sont réalisables par un opérateur `` cast ``.
II-8 L’opérateur conditionnel :
Exemple :
int max, a, b;
a > b ? i++ : i- - suivant que la condition a > b est vraie ou fausse, on incrémentera
ou décrémentera la valeur de i.
Exemple1:
L’expression a*b, i + j
- évalue a * b
- puis i + j
- prend comme valeur la dernière calculée ( la valeur de i + j )
L’expression i ++, j = i + k
- incrémente la valeur de i
- puis évalue j = i + k.
Exemple2 :
27
j--;
Exemple :
int n;
double z;
28
Les entrées–sorties
conversationnelles
29
Les entrées–sorties conversationnelles
La bibliothèque standard du langage C offre une fonction de lecture scanf pour lire des informations du
clavier et une fonction d’écriture printf pour afficher des informations à l’écran.
Ces deux fonctions permettent de lire ou d'écrire des données selon un certain format.
Les données peuvent être converties sous forme de caractères, de nombres entiers , de chaînes de
caractères etc.… selon les spécificateurs de format utilisés.
Sa syntaxe:
scanf ( “format” ,arg1,arg2,……argn)
où
et format correspond à une liste de codes de conversion précisant le type de la donnée à lire.
d entier décimal
ld long int
hd short int
hu unsigned short
Remarques importantes:
30
• L’information tapée au clavier est rangée dans un tampon ( un emplacement mémoire
temporaire ) manipulé par un pointeur vers le prochain caractère à prendre en compte.
1) Certains caractères comme l’espace (^) et la fin de ligne (\n) joue le rôle de séparateurs. La
rencontre d’un séparateur entraîne l’arrêt d’un traitement d’un code de format.
Exemple:
scanf(“%d%c”,&a,&b)
45(retour chariot)
A (retour chariot) a=45 , b=’A’
Ou bien
scanf(“%d%d”,&i,&j)
3) Le code format %c entraîne la prise en compte du caractère entré même s’il s’agit d’un
séparateur .
int a;
char c;
scanf(“%d%c”,&a,&c)
12^A a=12 c= ^
scanf (“%d , %c”, &a,&c); ( le blanc entre deux codes signifie que les blancs jouent le
rôle de séparateurs.
31
12 ^^^^ V a = 12, c=V
4) La rencontre d’un espace entre deux codes de format entraîne scanf à ignorer tous les
séparateurs entrés jusqu’à rencontre d’un caractère différent d’un séparateur ( ceci revient à
faire avancer le pointeur du tampon jusqu’au prochain caractère différent d’espace ou retour
chariot )
scanf(“%d %c”,&a,&b)
a=45, b=A
5) Dans les codes de format de scanf, on peut préciser un gabarit qui spécifie
le nombre maximal de caractères à utiliser pour le code du format traité. La rencontre d’un
gabarit atteint entraîne l’arrêt du traitement d’un code format.
int a;
float r;
char c;
scanf(“%3d %5f %c”,&a,&r,&c)
Caractères entrés:
123 34.5645 d a=123, r = 34.56, c= 4
Caractères entrés:
123 34.5645 d a = 123, r = 34.564, c=5
caractères entrés :
123 retour chariot X=123 ; c1=blanc ( retour chariot) ; c2 =A
A
• Les informations frappées au clavier ne sont pas traitées immédiatement, mais elles sont
mémorisées dans le tampon. Le traitement commence à la rencontre de \n ( retour chariot)
• le tampon n’est pas vidé à chaque nouvel appel de scanf .
32
7) Le tampon peut être vidé explicitement par l’appel de la primitive
fflush( stdin) de la librairie <stdio.h >.
Sa syntaxe:
printf ( “format” ,arg1,arg2,……argn)
où
et format correspond à une liste de codes de conversion précisant le format de la donnée à afficher.
d un entier décimal
ld long int
f float ou double
en notation décimale avec 6 chiffres après le point
e float ou double
en notation exponentielle avec 6 chiffres après le point
s chaîne de caractères
Remarques:
• les flottants sont affichés avec 6 chiffres après le point ( par défaut)
33
Exemple:
int a = 33;
float r = 4.351;
printf(“%f ”, r)
r =4.351000
• Le gabarit qui est placé après le % indique le nombre minimal de caractères à afficher.
• Le signe – placé après % indique que le cadrage de l’affichage doit se faire à gauche ( par
défaut, il se fait à droite) et inversement pour le signe +.
1) La macro getchar()
Elle permet de lire un caractère du clavier et retourne soit l’octet lu soit la valeur -1 (EOF).
char c;
……
c= getchar()
2) La macro putchar()
Elle permet d’afficher le caractère c sur l’écran.
34
char c;
…….
putchar(c);
Elle offre aussi des macros de lecture et d’écriture de chaînes de caractères : gets(s) et
puts( s)
Exemple :
char nom[10] ;
…
puts ("hello");
gets(nom);
puts(nom);
…
35
Les instructions de contrôle
36
Les instructions de controle
L’instruction conditionnelle permet de tester une condition puis d'exécuter une action parmi deux
actions possibles.
Syntaxe:
if ( expression) instructions1;
[ else instructions2 ; ]
instructions1 et instructions2 sont des instructions quelconques qui peuvent être soit une instruction soit
un bloc d’instructions placées entre { et }.
Si l’expression a une valeur non nulle ( vraie) alors instructions1 est exécutée sinon instructions2 est
exécutée.
Exemple1
Int a,b ;
…
if ( a<b ) max = b ;
else max = a ;
Exemple 2
Int a,b ;
…
if (( a < = b ) && ( b<= c)) printf( “ordonne”);
37
Cas d’imbrications des instructions if…else
Règle à appliquer:
Le premier else rencontré est associé avec le plus proche if qui le précède:
dans cet exemple, dans le cas où l’expression ( a<=b ) est fausse, rien n’est affiché .
else if ((heure >= 12) && ( heure < 18)) printf( “ bon pares midi” );
L’instruction switch est une instruction de choix multiple. Elle permet d’évaluer une expression puis
d'exécuter une action parmi plusieurs actions étiquetées.
Si la valeur de l’expression correspond à une des étiquettes, l’action correspondante est exécutée .
Syntaxe:
Switch ( expression)
{
case constante1 : [ instructions; ]
………….
case constante : [ instructions; ]
………
[default : instructions; ]
}
L’expression est comparée successivement( de haut en bas) aux constantes spécifiées après chaque
“case”.
S’il y a égalité, alors les instructions correspondantes à ce « case » sont exécutées.
38
Dans le cas où aucune égalité n’est vérifiée, les instructions spécifiées après “ default” sont exécutées.
Pour sortir de l’instruction switch délimitée par { et } et continuer en séquence, on doit utiliser
l’instruction break .
Exemple1:
Char c;
…
switch ( c)
{
case ‘a’ : printf( “ lettre a” ); break;
switch ( c = getchar() )
{
case ‘a’ :
case ‘o’ :
case ‘i’ :
case ‘e’ :
case ‘u’ :
case ‘y’ : printf ( " c’est une voyelle " ) ; break ;
}
int err;
char code ;
…
switch ( err)
{
case 1 : printf( " erreur grave" ) ;
switch ( code)
{
case ‘0’ : printf ( “ à l’ open " ) ; break ;
case ‘e’ : printf ( “ à l’ écriture " ) ; break ;
default : printf ( “ inconnue " ) ; break ;
} break ;
case 2 : printf( " erreur simple" ) ; break ;
default : printf( " erreur inconnue" ) ; break ;
}.
39
IV- 3 L’instruction do…while…
Elle permet de répéter une ou plusieurs actions tant que la condition spécifiée n’est pas vérifiée.
Syntaxe :
Do instructions while ( expression) ;
Instructions peut être soit une seule instruction suivie de ; soit un bloc d’instructions entre { et } .
L’expression est évaluée après avoir exécutée au moins une fois instructions.
Si la valeur de l’expression est non nulle ( vraie), cette exécution est répétée sinon l’itération se termine.
Exemple 1:
do x -- ;
while x > 0
Exemple2 :
do c = getchar() ;
while ( c != ‘\n’ )
Remarque :
• l’instruction à répéter peut être vide , après le “do” on peut mettre soit le point virgule soit
{ et }.
• L’expression du “while” peut une expression avec un opérateur séquentiel et dont la dernière
sous- expression est évaluée à vrai ou faux.
tant qu’une condition spécifiée n’est pas vérifiée, elle permet de répéter une ou plusieurs actions.
Syntaxe :
while ( expression ) instructions
Instructions peut être soit une seule instruction soit un bloc d’instructions entre { et } .
while( x >0 )
x --;
Ou bien
40
while ( x--,x>0) ;
Est équivalente à : do x -- ;
While ( x > 0) ;
Exemple2 :
Exemple3:
L’instruction for est une instruction de boucle faisant intervenir l’initialisation, le test de limite et
l’incrémentation en une seule action.
Syntaxe:
for ( [expr1] ; [expr2] ; [expr3] )
Instructions;
“ instructions” peut être une instruction composée, et sera dans ce cas délimitée par { et }.
“ expr1” est une expression ( une initialisation) qui ne sera exécutée qu’une seule fois au début.
“expr2” est une expression dont le résultat détermine la fin de la boucle.
Tant que sa valeur est non nulle ( vraie), la boucle continue.
“ expr3” est une expression ( en général) qui sera exécutée à chaque itération.
Exemple:
41
for ( ; ; ) /* boucle infinie
1) L’instruction break:
Elle peut être utilisée dans les boucles ou dans une instruction switch. Elle permet d’interrompre le
déroulement de la structure où elle a été appelée.
Dans le cas des boucles ou plusieurs ‘switch ’ imbriqués, l’instruction ‘break’ n’a d’effet que sur la
boucle où elle a été définie.
Exemple: programme qui permet de lire des caractères jusqu ‘à fin de fichier ou fin de ligne.
2) L’instruction continue:
Dans le cas des boucles imbriquées, l’instruction ‘continue’ n’a d’effet que sur la boucle où elle a été
définie.
Exemple:
3) L’instruction goto:
Elle permet le branchement inconditionnel vers une instruction spécifiée par une étiquette dans le
programme.
Syntaxe:
Goto etiquette;
….
…
etiquette: …..
Exemple:
43
La programmation modulaire et
les fonctions
44
La programmation modulaire et les fonctions
Une fonction en C est une unité de programme, référencée par un nom, qui dispose d’arguments
correspondants à des informations qui lui sont transmises. Elle peut fournir une valeur en retour.
La définition d’une fonction comporte :
• une partie en-tête constiuée de :
3) Liste de paramètres formels qui lui sont passés lors de l’appel de cette fonction
d’un programme .
Les paramètres doivent être précédés de leur type.
Syntaxe :
Type nom ( [ type1 PF1, type2 PF2, …] )
• Une partie corps délimitée par deux accolades { et }. Le corps d’une fonction peut
contenir:
Exemple :
int affich ( int nb) ; /* en-tête
{
int F ; /* declaration d’une variable locale
F=1 ; /* instuctions
45
While ( nb != 0 )
{
F = F * nb ;
nb = nb –1 ;
}
return F ;
}
Dans un programme, toutes les fonctions doivent être définies par l’utilisateur exceptées les fonctions de
la librairie commune ( printf, scanf ….) .
L’instruction return
Sa syntaxe :
Return ( expression)
Cette instruction est appelée à la fin de la fonction . Elle retourne la valeur de l’expression au
programme appelant cette fonction.
a) Dans le cas où le type de l’expression retournée est différent du type de la fonction déclaré
dans l’entête, le compilateur peut mettre en place des instructions de conversion.
b) Dans le cas des fonctions définies sans valeur de retour ou sans argument , le mot clé “ void”
permet de le préciser au niveau de la définition de l’entête et dans la déclaration de la
fonction.
Exemple :
En C , un programme source peut être éclaté en plusieurs “fichiers sources”, comme l’autorise la
compilation séparée du langage.
Ces différentes parties du programme peuvent partager des informations.
Une fonction définie dans un fichier source et appelée dans un autre fichier source doit obligatoirement
être déclarée dans le fichier source où elle est appelée.
La déclaration d’une fonction facilite la vérification des types des paramètres à l’appel de la fonction et
des paramètres à la définition :
46
1) dans le cas où les types ne sont pas spécifiés, on parle de déclaration partielle de la fonction.
float fact();
2) Dans le cas où les types et les noms des paramètres sont spécifiés on parle de déclaration complète
ou " prototype " de la fonction.
3) Dans le cas où une fonction est déclarée dans les déclarations de la fonction qui l’utilise , elle sera
considérée comme une variable locale dont la portée est limitée à la fonction où elle apparait .
void main()
{
float fact( int) ; /* prototype de fact
int a ;
float x ;
x = fact ( a ) ;
}
4) Dans le cas où une fonction n’est pas déclarée dans la fonction qui l’utilise , elle est considérée
comme une variable externe. Elle peut être appelée de n’importe quelle autre fonction.
Une fonction peut être appelée en spécifiant son nom suivi par une liste de paramètres.
En C, un appel de fonction par son nom est assimilable à une expression .
Syntaxe :
nom ( pe1,pe2,……………)
pe1,pe2,… : sont les paramètres d’appels de la fonction. Ils sont aussi appelés paramètres effectifs. Au
niveau de l’appel, un paramètre de la fonction peut être une constante, une variable ou une expression.
47
• Au niveau de l’appel, il doit y avoir un paramètre effectif pour chaque paramètre
formel.
• Chaque paramètre effectif doit être de même type que son paramètre formel
correspondant.
Exemple :
#include<stdio.h>
int max(int x ; int y) /* définition de la fonction*/
{ /* qui calcule le maximum de deux entiers*/
int m;
m = ( x > y) ? x: y;
return (m);
}
main ()
{
int a,b,c,d;
scanf( “%d %d %d “,&a,&b,&c);
d = max ( a , b ); /* 1er appel de la fonction max*/
printf ( “ %d”, max ( c,d)); /* 2ème appel de max */
}
appel max() }
En C, les paramètres sont transmis “par valeur " ce qui signifie que ce sont les contenus des
variables qui sont transmis à la fonction et non leur adresse.
Avec ce mode de transmission, les valeurs des paramètres formels peuvent être modifées dans le corps
de la fonction, mais les valeurs des paramètres effectifs ne doivent pas être modifiées.
Ce mode de transmission interdit à une fonction de produire une ou plusieurs valeurs de “retour’’ ( dans
les paramètres effectifs) autre que celle de la fonction elle-même.
Il représente un mode d’échange d’information dans un seul sens.
48
Exemple 1:
#include<stdio.h>
void main ()
{
void echange( int a,int b) ;
int n=10, p=20 ;
echange ( n,p) ; /* au retour de l’appel */
/*les valeurs de n=10 et p=20*/
}
pour altérer les valeurs des variables n et p appartenant à la fonction main(), il suffit de transmettre en
paramètre leurs adresses. La fonction echange pourra alors agir sur le contenu de ces adresses. Dans ce
cas , les paramètres formels a et b doivent être des variables qui peuvent contenir des adresses.
Exemple2:
void main()
{ int i;
char tab[ 10 ];
scanf ( “%d”, &i); /* la fonction scanf reçoit en paramètre la valeur de */
/* l’adresse de i. Le contenu de i peut alors être altéré
scanf ( “ %s”, tab); /* tab est l’adressse du tableau
tab[ i ] = 0 ; /* le contenu de l’élément i du tableau est mis a 0.
}
La programmation modulaire
49
• Les variables locales qui sont définies au sein d’une fonction et qui ne sont connues
qu’à l’intérieur de cette fonction.
Dans le cas d’une variable globale, sa définition doit apparaitre en-dehors des fonctions qui
l’utilisent et doit précéder leur définition .
On dit que sa portée est limitée à la partie du programme qui suit sa définition.
Exemple:
int i ; /* déclaration de la variable globale
main ()
{
void affich ( void); /* prototype de la fonction
1) La déclaration extern
En C, il est possible de faire la compilation séparée de plusieurs modules réparties sur différents
fichiers , et faisant partie d’un même projet .
La portée d’une variable globale étant limitée au fichier source dans lequel elle a été définie, le langage
C prévoit une déclaration qui spécifie que la variable a déjà été définie dans un autre fichier source en
faisant inclure une déclaration de cette variable spécifiant que la variable est externe .
Syntaxe de la déclaration :
Extern type nom
50
Exemple :
source 1 source2
int x ; extern int x ;
main () fonct2 ()
{ {
….. …..
} }
fonct1 ()
{……
Remarque :
d’initialisation de sa valeur .
2) La déclaration static
En C, il est possible de limiter la portée d’une variable globale et la rendre inaccessible à l’extérieur
du fichier source où elle a été définie, en la déclarant de classe static de la façon suivante :
Exemple :
source 1 source2
Static int x ; extern int x ;
main () fonct2 ()
{ {
….. …..
} }
fonct1 ()
{
……
}
51
La variable x déclarée dans le fichier source2 n’aura aucun lien avec la variable x déclarée dans le
fichier source1. Car la déclaration static de la variable x demande qu’aucune trace de x ne subsiste en
Les variables définies au sein d’une fonction sont dites locales à cette fonction. Elle ne sont connues
qu’à l’intérieur de cette fonction.
On dit que leur portée est limitée à cette fonction.
Exemple:
int n; /* n est une variable globale
main ()
{
int p; /* p est une variable locale à main
::::
}
fonct1 ()
{
int p; /* p est une variable locale à fonct1
int n; /* n est une variable locale à fonct2
…..
}
Par défaut , une variable locale a une durée de vie limitée à celle d’une éxécution de la fonction dans
laquelle elle a été définie . Un espace mémoire lui est alloué à chaque entrée dans la fonction et
libéré à chaque sortie .
On dit que sa classe d’allocation est automatique.
Contrairement à cette classe d’allocation ; il éxiste une classe d’allocation statique ; qui permet
d’attribuer à une variable locale un emplacement permanent. Pour cela ; il suffit de spécifier le mot
clé static dans la déclaration de la variable :
Exemple :
#include<stdio.h>
main ()
{
void fonct();
int n; /* declaration de n (variable locale)
52
for( n=1; n,=5; n++)
fonct();
}
void fonct()
{
static int i; /* declaration de i (variable locale static)
i++;
printf( “ i = %d ” ,i) ;
}
Remarque :
Les variables locales de classe statique sont par défaut, initialisées à 0.
La récursivité est le processus par lequel une fonction peut s’appeler de façon répétitive jusqu’à
satisfaction d’une certaine condition.
Dans une recursivité indirecte, une fonction appelle une autre fonction qui appelle à son tour la
première.
Le langage C permet la récursivité qui s’avère trés utile dans certaines circonstances .
Par exemple pour calculer le factoriel d’un nombre entier ( utile en statistiques), la recursivité peut
être utilisée. Le factoriel d’un nombre x se note x! et se calcule de la façon suivante:
x! = x * (x - 1)* (x-2) ……2*1
x! = x * (x - 1)!
où (x-1)! = (x-1) * (x-2)!
Le calcul peut être continué de façon récursive jusqu’à la valeur 1.
Par définition la fonction qui calcule de manière récursive la factorielle d’un nombre entier positif
est : fact( n ) = n * fact( n - 1)
#include< stdio.h>
/* définition de la fonction factorielle
long int fact(int n)
{ if (n < =1) return ( 1) ;
else return ( n*fact(n-1)) ;
}
53
void main()
{ int n;
long int fact( int)m
printf(“n=\t ”);
scanf( “%d”, &n);
Quand le programme est éxécuté, les appels de la fonction récursive ne sont pas éxécutés
immédiatement. Ils sont placés dans une pile ( en même temps que les espaces alloués aux variables
locales) jusqu’à ce que la condition d’arrêt est rencontrée.
Les appels de fonction seront dépilés ( en même temps que les epaces alloués aux variables locales) et
alors éxécutés dans l’ordre inverse de leur appel.
Pour évaluer la factorielle de façon récursive, les appels de la fonction se feront dans cet ordre :
fact(1) = 1
fact(2) = 2* fact(1) = 2
fact(3) = 3* fact(2) = 6
………………
fact(n ) = n* fact( n-1)
Les définitions de fonctions devraient se placer dans le même fichier source que la fonction
principale main() .
Ells peuvent aussi être placées dans un fichier source séparé de celui qui contient la fonction main().
Dans ce cas, il est possible de définir des fichiers d’extension h , appelés fichiers entête , dans
lesquels on regroupe les prototypes de fonctions définies dans un programme.
54
Exemple
:::::::::::::::::
}
55
Les tableaux et les pointeurs
56
Les tableaux et les pointeurs
Définition
De façon générale, la notion d e tableau permet de définir une structure de donnée régulière
dans le sens où ele estconstituée d’un ensemble ordonné d’éléments de même type.
Un tableau permet de regrouper des données de même type sous un nom de groupe unique.
Les tâches de programmation qui impliquent un traitement répétitif des données conduisent à
l’utilisation des tableaux.
Un tableau représente un ensemble d’emplacements mémoire consécutifs qui portent le même nom et
contiennent des données de même type.
Un tableau à une dimension est un tableau n’ayant qu’un seul index. L’index indique la position
de la donnée ou l’élément dans le tableau.
Syntaxe :
Classe type nom [ expression ]
Classe spécifie la classe d’allocation possible pour ce type de variable : extern ,static ou auto.
Type spécifie le type des éléments de ce tableau (int, float ou char).
Expresssion spécifie la dimension du tableau ou le nombre d’éléments qui le constitue. Cette
expression peut être une constante ou une expression constante.
Exemple :
#define M 60 ;
main()
{
int x[100];
char text[80];
static float N[10];
int tab [ M];
float X[ 2*M];
……………………
}
Un tableau peut être vu comme une succession de variables de même type, accessible par indexation.
57
Exemple :
Soit la déclaration suivante de tableau :
int tab [ 10 ];.
int i, j;
char c;
tab[i + j ]
tab [i + c ]
tab [ j ]
tab est considéré comme l’adresse du tableau. Cette adresse ne peut pas être modifiée.
En conséquence, les opérations suivantes ne sont pas permises: l’affectation,la comparaison etc….
tab = 0;
tab = tab + 1
tab == 0
Un élément de tableau est une lvalue ; il peut être à gauche d’un opérateur d’affectation : tab [ i ]
= 0;
tab [ i ] ++;
Reamarque :
Aucun controle de débordement d’indice n’est fait dans la plupart des compilateurs.
Comme les variables simples , un tableau peut être initialisé lors de sa déclaration partiellement
ou totalement avec des expressions constantes.
Exemple :
Remarque:
Dans le cas d’un tableau déclaré comme une variable externe :
• la dimension peut ne pas être spécifiée
• le tableau ne peut pas être réinitialisé car il joue le rôle de variable globale
Exemple:
Source1 source2
Int c[ 4]= { 1,2,4,6}; extern int c[ ];
Char text [ ] = “HELLO”; extern char text [ ];
……………. ………………….
Syntaxe :
Class type nom [ dimension1] dimension2] [ dimension3]……
Il n’y a aucune limitation sur le nombre de dimensions que peut avoir un tableau .
59
Tab[0][1] le 2ème élément
Tab[0][2]
Tab[1][0]
Tab[1][1]
……….
Tab[3][2] le dernier élément
Un tableau multidimensionnel peut être vu comme une succesion de tableaux à une dimension.
Exemple
int tab[ 4][3] = { { 1,1,1}, { 2,2,2}, {3,3,3},{ 4,4,4} }
Les valeurs du tableau X seront exploitées en fonction de la manière dont les éléments sont rangés
en mémoire.
Dans le cas d’un tableau à une seule dimension : le nom du tableau représente son adresse de debut.
Exemple :
int t[3][4]
t[0] représente l’adresse de début des 4 premiers éléments (le 1er bloc)
t[1] représente l’adresses de début des 4 éléments suivants ( le second bloc)
t[ i ] ( i variant de 0 à 2 ) est une constante ( adresse fixe) . Elle ne peut pas être une lvalue. De
ce fait , l’affectation n’est pas autorisée sur t[ i ].
Exemple
t[ 1 ] ++ n’est pas autorisé
t[1][3] ++ est autorisé car t[1][3] est une lvalue
60
Les tableaux et les fonctions
Lors de l’appel d’une fonction, placer le nom d’un tableau comme paramètre effectif de la
fonction , revient à transmettre l’adresse du tableau à la fonction. La fonction pourra donc faire toutes
les manipulations sur les éléments de ce tableau.
Exemple :
void init ( int tab[10]} ; /* definition de la fonction
{
int I ;
for ( I=0 ; I<10 ; I++) t[ I ] = 1 ;
}
init ( t1) ;
init ( t2 ) ;
ou bien
+ void init ( int t[ ] ) /* la réservation de l’espace memoire sera faite dans le programme appelant
{
int I ;
for ( I=0 ; I<10 ; I++) t[ I ] = 1;
}
Exemple :
Exemple :
int t1 [2 ][ 3 ], t2[ 2 ][ 3 ] ;
……….
init ( t1) ;
init ( t2 ) ;
Dans ce cas , le nom de la matrice tableau ainsi que sa taille sont transmis comme
paramètres à la fonction. Pour trouver l’adresse d’un élément quelconque, la seconde
dimension doit être connue par le compilateur.
62
Exemple :
int t1 [2 ][ 3 ], t2[ 4 ][ 3 ] ;
……….
init ( t1 , 2) ;
init ( t2 , 4 ) ;
63
Les pointeurs
64
Les pointeurs
Un pointeur peut contenir l’adresse d’une autre variable . Il permet donc d’accéder indirectement à
une variable.
syntaxe :
classe type * nom ;
Exemple :
comme toute variable, un pointeur doit être initialisé. Un pointeur doit contenir l’adresse d’une
variable .
L’ adresse de v est donnée par l’expression &v ( & est l’opérateur d’adresse)
ptr = &v affecte à ptr l’adresse de v
On dit alors que ptr pointe vers la variable v.
L’opérateur * ou opérateur d’indirection qui est appliqué seulement aux variables de type pointeur,
permet de donner le "contenu de " la variable.
Si ptr = &v alors *ptr ( contenu de ptr) fait référence à la variable v qui est pointée .
65
v et *ptr représentent le contenu de v.
&v et ptr représentent l’adresse de v.
Exemple:
int var = 1m
int * ptr;
main()
{
ptr = &var;
/* acces direct et indirect à var
printf( “ acces direct, var = %d\n”, var);
printf( “ acces indirect, var = %d\n”, *ptr);
/* affichage de l’adresse avec les deux methodes
printf( “ adresse de var = %d\n”, &var);
printf( “ adresse de var = %d\n”, ptr);
}
a) l’initialisation d’un pointeur peut être faite lors de sa déclaration ou dans le programme.
Exemple 1:
float u,v ;
float *p1 = &v , *p2;
p2 = p1 ;
Exemple2:
int n = 10,p;
int *ad1, *ad2, *ad3;
ad2 = &p;
ad1 = &n;
66
Quand un pointeur est incrémenté , sa valeur est incrémentée en un multiple de la taille de
l’objet pointé.
Exemple :
Int * ptr ;
ptr = ptr + 1 : // le contenu de ptr sera incrementé de la taille d’un
entier.
// ptr va donc pointer vers l’objet suivant.
Remarque :
• Toutes les opérations arithmétiques lui sont interdites exceptées ( L’addition
et la soustraction).
Exemple:
Pour initialiser les éléments d’un tableau à 0.
int t[ 5];
int *p;
for ( p=t; p< t+5; p++) *p = 0;
Exemple :
int tab [10]; /* définit un tableau de 10 éléments de type entiers.
int * p; /* definit un pointeur vers un objet de type int.
67
• le pointeur p est une variable
si p = tab alors p++ est permis
Puisque un nom de tableau est un pointeur vers le 1er élément du tableau, on peut accéder au
premier élément de ce tableau avec l’opérateur indirect ( * ).
si tab [ ] est un tableau, l’expression *tab représente le premier élément de ce tableau
*tab == tab [ 0 ]
*(tab +1) == tab [ 1 ] etc….
En C , il n’éxiste de type de données pour les chaines de caractères. Les chaines de caractères
sont manipulées à l’aide de tableaux de caractères.
Soit la déclaration suivante :
char * t = “hello” est équivalente à char t[ 6 ] = “hello”
permet de déclarer le pointeur t vers le premier caractère de la chaine de caractères. Le pointeur t est
utilisé pour accéder à la chaine
t[0] correspond au caractère h
t[1] correspond au caractère e etc…
t[5] correspond au caractère null à la fin
Les fonctions malloc() et free() sont des fonctions de la librairie standard stdlib qui permettent
respectivement d’allouer et de libérer un espace mémoire de façon dynamique.
Exemple1:
int *t;
char *texte;
/* allocation mémoire pour un tableau de 10 entiers
t = (int *) malloc( 10 * sizeof( int) ) ;
/* allocation mémoire pour un tableau de 99 caractères plus un pour null
texte = (char*) malloc( 100);
68
malloc( ) est appelée pour faire une réservation d’un espace pour le nombre d’octets nécessaires
et nous renvoit un pointeur de type void vers le bloc de mémoire qui a été réservé.
L’avantage de la réservation dynamique : est la possibilité de réserver de l’espace mémoire durant
l’éxécution du programme . Le processus d’allocation peut être rappelé plusieurs fois durant l’éxécution
d’un programme .
multi[0] [0]
Chacun de ces deux éléments contient à son tour 4 éléments de type int.
69
Comme pour les tableaux à une dimension, le nom d’un tableau à 2 dimensions est un pointeur vers le
premier élément du tableau, on peut accéder au premier élément de ce tableau avec l’opérateur indirect
( * ).
Un tableau à 2 dimensions peut être défini à l ‘aide d’un pointeur à un groupe de tableaux ( à un indice)
contigus.
Exemple :
Donc *(x) == x[0] est le pointeur vers le 1er élément du 1er tableau
*( x + 1 ) == x[1] pointe vers le 1er élément du 2ième tableau
*( x + 1) + 2 ==& x[1][2] est le pointeur au 3ième élément du 2ième tableau
Exemple:
#include <stdio.h>
void print_tableau( int (*ptr)[ 4 ]);
void print_tableau( int (*ptr)[ 4 ]);
main()
{
int multi[2] [4] = { {1,2,3,4},
{ 5,6,7,8},
70
{ 8,9,10,11},
{ 12,13,14,15}};
{
int *p, j;
p = ( int*) ptr;
for (j=0; j < 4; j++)
printf( “%d”, p++)
}
2) Un tableau à deux dimensions peut être exprimé sous forme d’un tableau de pointeurs plutôt
qu’un pointeur vers un groupe de tableaux.
En C, les pointeurs constituent un type de données, on peut alors définir un tableau de pointeurs.
Exemple1 :
char * x [ 10] ;
Exemple2:
#include <stdio.h>
void print_tableau( int (*ptr)[ 4 ]);
void print_tableau( int (*ptr)[ 4 ]);
main()
{ /* déclaration d’un tableau de 3 pointeurs de type char
char *message [3] = { “un”, “deux”, “trois”};
int j;
for(j=0; j<3; j++)
printf(“%s\n”, message[j]);
}
71
message[0] 1000 u n \0
1200
message[1] d e u x \0
1100
t r o i s \0
message[2]
main ()
{ int *A[20], *B[20], *C[20] ;
int i, j ;
/* lire ncol , nligne;
/* allouer mémoire
/* lire A et B
/* calcul de la somme
for( j = 1 ; j < ncol ; j++)
*(C [ I ] + j) = *(A [ I ] + j) + *(B [ I ] + j) ;
}
}
En C, un pointeur qui représente une adresse peut être passé en paramètre à une fonction.
Etant donné qu’en C le passage des paramètres se fait par valeur, il est interdit à une fonction de
modifier la valeur de ses paramètres effectifs. les pointeurs permettent de résoudre ce problème.
En effet, au niveau de l’appel d’une fonction , si les paramètres effectifs sont des adresses, les
paramètres formels correspondants seront définis de type pointeur pour pouvoir recevoir les valeurs
transmises à l’appel .
Exemple 1
#include<stdio.h>
void main ()
{
void echange( int *a,int *b) ;
72
int n=10, p=20 ;
echange ( &n, &p) ; /* au retour de l’appel
/*les valeurs de n=10 et p=20
}
int c ;
c= * a ;
*a= *b ;
*b= c ;
}
Exemple2 :
+ void init( int * t) ; /* definition de la fonction
{ /* la réservation de l’espace memoire sera faite dans le programme appelant
int I ;
for ( I=0 ; I<10 ; I++, t++) *t = 1;
}
init ( t1) ;
init ( t2 ) ;
ou bien
73
Exemple3
+ void init( int (* t )[3 ] , int nligne) ;
{
int I ;
for ( I=0 ; I< nligne ; I++ )
for ( j = 0 ; j < 3 ; j++ )
*(*(t + I ) + j ) = 1;
}
ou bien
74
Les fichiers
75
Les fichiers
. ;
En C ,un fichier est un ensemble d’informations stockées sur une memoire secondaire ou un
peripherique donné.( disque,disquette, ecran clavier…)
• Dans le cas des entrées- sorties conversationnelles , l’échange d’information entre l e programme et
l’utilisateur se fait à l’aide de deux fichiers standards stdin ( fichier d’entrée associé au clavier) et
stdout ( fichier de sortie associé à l’écran).
• Dans les autres cas, un fichier sera identifié par un nom externe.
Les manipulations des fichiers s’effectuent par l’intermédiaire de fonctions de la bibliothèque standard.
FILE ptr; / / ptr est un pointeur de fichier qui va correspondre au nom interne
associé au fichier.
mode= “r” ouverture en lecture, si le fichier n’éxiste pas, il y a renvoi d’une erreur
mode = “w” ouverture en ecriture. Si le fichier n’éxiste pas, il sera creé
s’il existe deja , son ancien contenu sera inaccessible
La fonction fopen retourne lepointeur associé au fichier ( ou son nom interne) si l’ouverture s’est bien
deroulée ,ou bien le pointeur nul, si erreur à l’ouverture ( dans le cas où on essaye d’ouvrir en lecture un
fichier qui n’éxiste pas).
Syntaxe
fclose (ptr)
76
Elle retourne un entier égal à 0 si la fermeture s’est bien deroulée et –1 sinon
Exemple
#include <stdio.h>
main()
{
FILE * ptr;
ptr = fopen( “fich.txt”, “w”);
if (ptr == null)
printf(“ erreur , ne peut pas ouvrir le fichier”);
…….
fclose(ptr);
}
si le fichier est considéré comme une séquence de caractères, il peut être crée en lisant des caractères du
clavier à l’aide de getc et les écrire dans le fichier à l’aide de putc.
putc et getc sont les fonctions de lecture et écriture d’un caractère d’un fichier quelconque.
putc(octet , ptr)
Valeur retournée: le caractère écrit ou la valeur null dans le cas d’erreur
77
Exemple : Programme qui lit une ligne de texte du clavier caractère par caractère et la recopie caractère
par caractère sur le fichier
#include <stdio.h>
main()
{ char c;
FILE * ptr;
ptr = fopen( “fich.txt”, “w”);
if (ptr == null)
printf(“ erreur , ne peut pas ouvrir le fichier”);
fclose(ptr);
}
Remarque:
Les fonctions fgets et fputs premettent de manipuler plus facilement les fichiers formés de chaines de
caractères.
fputs( chaine,ptr)
Dans les fichiers texte , chaque octet représente un caractère, y compris le caractere ‘\n’.
Ils peuvent être vus comme une suite de lignes.
Les fonctions fscanf et fprintf permettent de réaliser des entrées sorties formattées.
Exemple
#include <stdio.h>
main()
{ char c;
typedef struct{
char nom[40],prenom[40];
int numero;
}record;
78
record person;
FILE * ptr;
fclose(ptr);
}
79
Exercices
1) Lire à l’écran un tableau d'entiers positifs ou négatifs dont la fin est signalée par le nombre zéro. La
fonction parcourt ce tableau en transformant les négatifs en positifs.
2) Ecrire un programme qui lit la dimension N d'un tableau T du type int (dimension maximale: 50
composantes), remplit le tableau par des valeurs entrées au clavier et affiche le tableau.
Ranger ensuite les éléments du tableau T dans l'ordre inverse sans utiliser de tableau d'aide. Afficher le tableau
résultant.
Idée: Echanger les éléments du tableau à l'aide de deux indices qui parcourent le tableau en commençant
respectivement au début et à la fin du tableau et qui se rencontrent en son milieu.
3) Ecrire un programme qui lit les points de N élèves d'une classe dans un devoir et les mémorise dans un
tableau POINTS de dimension N.
80
* Rechercher et afficher:
- la note maximale,
- la note minimale,
* A partir des POINTS des élèves, établir un tableau NOTES de dimension 7 qui est composé de la façon
suivante:
...
Etablir un graphique de barreaux représentant le tableau NOTES. Utilisez les symboles ####### pour la
représentation des barreaux et affichez le domaine des notes en dessous du graphique.
Idée: Déterminer la valeur maximale MAXN dans le tableau NOTES et afficher autant de lignes sur l'écran.
(Dans l'exemple ci-dessous, MAXN = 6).
Exemple:
6 > #######
5 > ####### #######
4 > ####### ####### #######
3 > ####### ####### ####### #######
2 > ####### ####### ####### ####### #######
1 > ####### ####### ####### ####### #######
+-------+-------+-------+-------+-------+-------+-------+
I 0 - 9 I 10-19 I 20-29 I 30-39 I 40-49 I 50-59 I 60 I
4) Ecrire un programme qui lit deux chaînes de caractères CH1 et CH2 et qui copie la première moitié de
CH1 et la première moitié de CH2 dans une troisième chaîne CH3. Afficher le résultat.
81
5) Ecrire un programme qui demande l'introduction du nom et du prénom de l'utilisateur et qui affiche alors
la longueur totale du nom sans compter les espaces. Employer la fonction strlen.
Exemple:
6)
1.
Déclarer un entier i et un pointeur p vers un
entier ;
2.
Initialiser l'entier à une valeur arbitraire et faire pointer p vers i ;
3.
Imprimer la valeur de i ;
4.
Modifier l'entier pointé par p (en utilisant p, pas i) ;
5.
Imprimer la valeur de i.
7)
1.
Déclarer et initialiser statiquement une matrice [5,5] d'entiers (tab).
2.
Écrire une fonction (print_mat) qui admette en paramètre une matrice [5,5] et qui imprime ses éléments
sous forme de tableau.
3.
La procédure main fera un appel à print_mat pour le tableau tab
QUESTION #1
/* EX1 */
#include <stdio.h>
fich = fopen(«a:\\exer1.don»,
«r» );
82
for( i=5; i>=0; i-- )
fscanf( fich, «%d», &x[i]);
QUESTION #2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* EX2 */
#include <stdio.h>
b[0] = 10;
for( i=1; i<5; i++ )
b[i] = b[i-1] * 2;
83
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
QUESTION #3
/* EX3 */
#include <stdio.h>
QUESTION #4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* EX4 */
#include <stdio.h>
k = 2;
n[0] = 10;
n[1] = 2;
for( j=1; j<5; j++)
{
n[k] = n[k-1] / 2;
n[k+1] = n[k] * (k+1);
k = k + 2;
}
printf( «%5d%5d\n», n[n[2]], n[9] );
}
Écrivez ce que le programme affichera lors de son exécution.
84
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
QUESTION #5
/* EX5 */
#include <stdio.h>
FILE *fich;
QUESTION #6
/* boucle8 */ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <stdio.h>
85
/* boucle9 */ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <stdio.h>
som = 0;
for( k=1; k<=3; k++ )
{
for( n=1; n<=4; n++ )
{
som = som + n;
printf( «%3d», som );
}
printf( «\n» );
}
}
QUESTION #8
- fonctions
void main(void) {
int x = 22;
int y = 23;
ma_fonction(x);
printf( "x=%d y=%d\n", x, y );
}
2- Donner le prototype d'une fonction nommée EstPremier testant si un nombre n est ou non
premier.
3- Donner le prototype d'une fonction DemandePoint qui demande à l'utilisateur les coordonnées
(x,y) d'un point.
QUESTION #9
86
*dp = *sp;
else
*dp = 0;
}
QUESTION #10
Dans le programme suivant, rayez les lignes illégales (erreurs). Qu'est ce qui s'affiche ?
p = &i;
*f = 666;
f = &x;
*f = *p;
*p = 34;
p = f
*p = *p + 1;
printf( "%d %f\n", i, *f );
}
QUESTION #11
...
int a = 10, b = 22;
Echanger( &a, &b );
/* ici a == 22 et b == 10 */
2- En utilisant la fonction Echanger, écrire une fonction Permute3 qui effectue une permutation
circulaire de trois variables, comme dans l'exemple ci-dessous :
...
int a = 10, b = 22, c = 33;
Permute3( &a, &b, &c );
/* ici a == 33, b == 10, c == 22 */
QUESTION #12
87
#include <stdio.h>
void main( void )
{
int i, j, k;
int TabA[3], TabB[3], TabC[6];
FILE *Fich;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
88
QUESTION #13
int a,b;
int *pta, *ptb;
a=5; b=8;
pta=&a; ptb=&b;
b) Pour chaque instruction indiquer la valeur finale des variables impliquées (on
reprend toujours les valeurs de départ) :
a=a+(*ptb) ; a=
*ptb=*ptb+a a= b=
*pta=*ptb+*pta a= b=
Dites ce qui sera affiché par chacun des printf après l’appel de la fonction AuSecours.
#include <stdio.h>
void AuSecours(int *k, int *g);
void main(void)
{
int a = 1,
b = 2;
AuSecours(&a, &b);
printf("A = %d, B = %d\n", a, b);
a=1; b=2;
AuSecours(&b, &a);
printf("A = %d, B = %d\n", a, b);
nb = 5;
nb = (nb * (*k)) / *g ;
*k = nb * (*g) ;
}
References:
http://www.iro.umontreal.ca/
90