Langage C - Pages de Michel Deloizy - Free
Langage C - Pages de Michel Deloizy - Free
Langage C - Pages de Michel Deloizy - Free
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
LICENCE SPI - EEA<br />
<strong>Langage</strong> C<br />
Éléments <strong>de</strong> Cours<br />
M. <strong>Deloizy</strong> Édition du 5 février 2009<br />
http://michel.<strong>de</strong>loizy.free.fr
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
INTRODUCTION<br />
Le langage C est un langage structuré conçu pour obtenir un haut niveau dřoptimisation en produisant une taille <strong>de</strong> co<strong>de</strong><br />
réduite et une gran<strong>de</strong> rapidité dřexécution.<br />
Son écriture peut sembler quelque peu hermétique au programmeur non initié ; elle permet cependant une écriture<br />
efficace <strong>de</strong> programmes, le langage définissant très peu <strong>de</strong> mots clés et autorisant largement les omissions<br />
(réglementées) et les contractions. Ceci constitue parfois une difficulté qui nécessite une bonne connaissance du langage<br />
et une gran<strong>de</strong> rigueur lors <strong>de</strong> la transcription <strong>de</strong> programmes.<br />
Pour permettre au compilateur dřobtenir une bonne efficacité, le niveau <strong>de</strong> protection du langage est très faible (on<br />
pourra fréquemment « planter » la machine). Par ailleurs, il permet <strong>de</strong> disposer <strong>de</strong>s ressources avancées du système<br />
comme les écrans, les claviers, les disques et autres périphériques ; Il permet également en standard dřaccé<strong>de</strong>r aux<br />
ressources proches du matériel (par exemple la mémoire) ce qui rend le langage C « universel » et explique sa fréquente<br />
utilisation dans <strong>de</strong> nombreux domaines.<br />
Une autre caractéristique très intéressante du langage C est quřil offre <strong>de</strong>s mécanismes assurant une bonne portabilité, à<br />
condition que le programmeur veuille bien se plier à lřécriture <strong>de</strong>s programmes « dans les règles <strong>de</strong> lřArt ».<br />
I. Constitution d’un programme C<br />
DESCRIPTION DU LANGAGE<br />
I.1. Généralités<br />
Un programme C est un ensemble constitué <strong>de</strong> modules, eux-mêmes composés <strong>de</strong> fonctions.<br />
Pour le programmeur, un module est en réalité un fichier texte (dřextension « .c ») que lřon saisit avec un éditeur <strong>de</strong><br />
textes ; il sřagit du fichier source codé en ASCII dans la machine.<br />
Les fonctions décrivent les actions à réaliser dans le programme. Elles peuvent appeler dřautres fonctions qui ellesmêmes<br />
peuvent en appeler dřautres, etc.<br />
En C, une fonction particulière permet le démarrage du programme : elle se nomme main(), ce qui signifie<br />
« principale ». Lorsque lřon exécute un programme C sur une machine, tout se passe comme si le système<br />
dřexploitation <strong>de</strong> lřordinateur appelait cette fonction (le système dřexploitation étant alors vu comme étant, pour la<br />
fonction main, une fonction <strong>de</strong> niveau supérieur).<br />
I.2. Syntaxe<br />
I.2.a. Commentaires.<br />
En C, les commentaires sont encadrés par les séquences <strong>de</strong> caractères /* et */. Ils ne peuvent pas être<br />
imbriqués (pas <strong>de</strong> commentaires en commentaire). Les commentaires peuvent occuper plusieurs lignes.<br />
Toute information notée en commentaire sera ignorée par le compilateur.<br />
Aujourd'hui, certains compilateurs reconnaissent la séquence // comme étant le début d'un commentaire<br />
occupant le reste <strong>de</strong> la ligne (héritage du C++). Ceci n'est malheureusement pas le cas <strong>de</strong> tous les<br />
compilateurs et <strong>de</strong>vra être évité dans un souci <strong>de</strong> portabilité.<br />
I.2.b. Noms <strong>de</strong> symboles.<br />
Les symboles sont composés d'un ensemble <strong>de</strong> lettres, <strong>de</strong> chiffres et du caractère '_'. Le premier caractère<br />
ne pouvant être un chiffre.<br />
Les caractères accentués ne sont pas acceptés.<br />
I.2.c. Minuscules et majuscules.<br />
Les minuscules et majuscules sont différenciés en C (Toto est différent <strong>de</strong> toto). En règle générale, on<br />
évitera d'utiliser <strong>de</strong>s noms <strong>de</strong> symboles se différenciant uniquement par la présence <strong>de</strong> minuscules et/ou<br />
majuscules, ceci étant source <strong>de</strong> confusion et d'erreurs.<br />
-2-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
I.3. Mots clés<br />
Le langage C utilise un nombre très restreint <strong>de</strong> mots réservés. Ces mots qui ne doivent pas être utilisés comme noms <strong>de</strong><br />
symboles sont les suivants :<br />
auto break case char const continue <strong>de</strong>fault do<br />
double else enum extern float for goto if<br />
int long register return short signed sizeof static<br />
struct switch type<strong>de</strong>f union unsigned void volatile while<br />
II. Types <strong>de</strong> variables<br />
Le langage C propose un jeu <strong>de</strong> types <strong>de</strong> données assez complet tout en offrant <strong>de</strong>s outils permettant <strong>de</strong> sřaffranchir <strong>de</strong><br />
lřimplémentation.<br />
II.1. Les types <strong>de</strong> base<br />
II.1.a. char :<br />
II.1.b. int :<br />
est le type <strong>de</strong> données le plus petit. Il permet <strong>de</strong> manipuler <strong>de</strong>s caractères et est souvent composé <strong>de</strong><br />
8 bits. Il est signé par défaut. Il peut être vu comme étant un entier très court. Cřest le type <strong>de</strong> données <strong>de</strong><br />
taille élémentaire.<br />
est un entier. Cřest le type <strong>de</strong> données qui pris par défaut par le langage (quand le type <strong>de</strong> donnée nřest<br />
pas précisé). Il est en général constitué du nombre <strong>de</strong> bits correspondant au processeur sur lequel est<br />
exécuté le programme. En principe, le type int est composé dřau moins 16 bits. Il est signé par défaut.<br />
II.1.c. float :<br />
est un nombre codé en virgule flottante, permettant dřobtenir une gran<strong>de</strong> dynamique. Il est adapté aux<br />
calculs scientifiques et ne convient pas pour les énumérations (à cause <strong>de</strong> sa précision limitée).<br />
II.2. Les types dérivés<br />
II.2.a. unsigned char :<br />
est un caractère non signé, permettant <strong>de</strong> manipuler uniquement <strong>de</strong>s entiers (très courts) positifs.<br />
II.2.b. signed char :<br />
est un caractère signé. char étant signé par défaut, signed peut être utile dans certains environnements qui<br />
prennent le type char comme non signé.<br />
II.2.c. unsigned int ou unsigned :<br />
est un entier non signé.<br />
II.2.d. short :<br />
est un entier signé qui peut être plus petit que int (souvent 16 bits).<br />
II.2.e. unsigned short :<br />
est un short non signé.<br />
II.2.f. long int ou long :<br />
est un entier signé à gran<strong>de</strong> précision ; il est composé dřun nombre <strong>de</strong> bits supérieur ou égal à celui <strong>de</strong> int.<br />
II.2.g. unsigned long int ou unsigned long :<br />
est un long int non signé.<br />
II.2.h. double :<br />
correspond à un long float. Il contient un nombre à virgule flottante dont le nombre <strong>de</strong> chiffres<br />
significatifs et la dynamique sont supérieurs ou égaux à float.<br />
-3-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
II.2.i. long double :<br />
contient un nombre à virgule flottante dont le nombre <strong>de</strong> chiffres significatifs et la dynamique sont<br />
supérieurs ou égaux à double.<br />
II.2.j. Dynamique <strong>de</strong>s nombres :<br />
A titre indicatif, la dynamique <strong>de</strong>s nombres est indiquée dans les tableaux ci-<strong>de</strong>ssous :<br />
ENTIERS Valeur minimale Valeur maximale<br />
8 bits signé -128 127<br />
8 bits non signé 0 255<br />
16 bits signé -32768 32767<br />
16 bits non signé 0 65535<br />
32 bits signé -2 147 483 648 2 147 483 647<br />
32 bits non signé 0 4 294 967 295<br />
VIRGULE FLOTTANTE Chiffres significatifs Exposant min/max<br />
4 octets 7 38<br />
8 octets 15 308<br />
10 octets 19 4932<br />
Remarques :<br />
Le langage C ne définit pas un nombre <strong>de</strong> bits (donc une précision) correspondant à chaque type <strong>de</strong> données. Celui-ci<br />
dépend donc du matériel sur lequel sera exécuté le programme, et surtout du compilateur utilisé. Il existe simplement<br />
une recommandation concernant la taille <strong>de</strong>s entiers (int) qui <strong>de</strong>vront être codés sur au moins 16 bits.<br />
La seule certitu<strong>de</strong> concerne le classement <strong>de</strong>s encombrements (notés E) :<br />
E(char) E(short) E(int) E(long)<br />
E(float) E(double) E(long double)<br />
Lors dřopérations sur <strong>de</strong>s entiers, le type int sera automatiquement utilisé par le compilateur (sauf si un terme long int<br />
apparaît dans lřexpression). Cřest le cas également lors <strong>de</strong> la transmission <strong>de</strong> paramètres entiers à une fonction.<br />
Lors dřopérations sur <strong>de</strong>s nombres à virgule flottante, le type double sera utilisé par le compilateur ; Le type float sera<br />
donc réservé au rangement <strong>de</strong> données en gran<strong>de</strong> quantité.<br />
Lřopérateur sizeof permet <strong>de</strong> connaître la taille dřune donnée, exprimée en nombre <strong>de</strong> données <strong>de</strong> taille élémentaire<br />
(sizeof(char) vaut 1). En général, puisque le type char est souvent codé sur un octet, sizeof donne la taille <strong>de</strong>s données<br />
en octets.<br />
Il nřexiste pas en C <strong>de</strong> type booléen. Le type entier (int) sera utilisé lors <strong>de</strong> lřévaluation dřune expression logique. Une<br />
expression sera dite « vraie » si elle est non nulle ; Elle sera « fausse » si elle est nulle.<br />
II.3. Les types composés<br />
Les types <strong>de</strong> données énoncés précé<strong>de</strong>mment permettent <strong>de</strong> constituer <strong>de</strong>s données plus complexes :<br />
II.3.a. les tableaux :<br />
Ils sont constitués dřun ensembles <strong>de</strong> données <strong>de</strong> même type, placées <strong>de</strong> manière contiguë en mémoire.<br />
II.3.b. les structures :<br />
Elles sont constituées dřun ensemble <strong>de</strong> types <strong>de</strong> données. Elles permettent <strong>de</strong> décrire cette donnée en lui allouant un<br />
ensemble <strong>de</strong> variables la caractérisant.<br />
Par exemple, pour décrire un individu, on indiquera son nom, son âge, sa taille, son poids et son sexe (0 pour un<br />
homme, 1 pour une femme).<br />
Lřindividu constituera une donnée <strong>de</strong> type structure dont les « champs » seront :<br />
- le nom (tableau <strong>de</strong> caractères)<br />
- lřâge (un entier court non signé)<br />
- la taille (un nombre à virgule flottante)<br />
- le poids (un nombre à virgule flottante)<br />
- le sexe (un caractère)<br />
Les structures seront développées ultérieurement (page 28).<br />
-4-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
II.3.c. les unions :<br />
Il sřagit <strong>de</strong> structures particulières dans lesquelles tous les champs sont situés à la même adresse. Les unions sont utiles<br />
lors du développement <strong>de</strong> programmes à bas niveau (proches du matériel), et permettent ainsi une bonne portabilité du<br />
langage.<br />
Remarque :<br />
On peut évi<strong>de</strong>mment combiner les structures et les tableaux, permettant ainsi dřobtenir <strong>de</strong>s tableaux <strong>de</strong><br />
structures ou <strong>de</strong>s structures contenant <strong>de</strong>s tableaux.<br />
II.4. Autres types<br />
II.4.a.<br />
II.4.b.<br />
les types définis par le programmeur<br />
le programmeur peut à son aise renommer un type <strong>de</strong> donnée par lřintermédiaire du mot clé type<strong>de</strong>f.<br />
Utilisé à bon escient, cela permet souvent une meilleure lisibilité <strong>de</strong>s programmes.<br />
Exemples :<br />
type<strong>de</strong>f unsigned char byte;<br />
type<strong>de</strong>f unsigned short word;<br />
type<strong>de</strong>f unsigned long dword;<br />
void<br />
nřest pas un type <strong>de</strong> donnée. Ce mot clé permet dřindiquer lřabsence <strong>de</strong> donnée ou la méconnaissance du<br />
type <strong>de</strong> donnée.<br />
III. La déclaration <strong>de</strong>s variables<br />
Pour déclarer une variable, il suffit dřindiquer le type choisi, suivi du nom <strong>de</strong> la variable. Plusieurs variables <strong>de</strong> même<br />
type peuvent être déclarées simultanément.<br />
La fin <strong>de</strong> la déclaration est marquée par le caractère Ř;ř<br />
Exemples :<br />
char x ; x est un caractère (sur 8 bits : [-128…+127])<br />
int i, j, k ; i, j et k sont <strong>de</strong>s entiers (sur 16 bits : [-32768…+32767])<br />
unsigned arthur ; arthur est un entier non signé (sur 16 bits : [0…+65535])<br />
unsigned char octet ; octet est un caractère non signé(sur 8 bits : [0…+255])<br />
Pour déclarer <strong>de</strong>s tableaux <strong>de</strong> données, on fait suivre le nom <strong>de</strong> variable par le nombre dřéléments que peut contenir<br />
chaque ligne du tableau ; Cette valeur obligatoirement constante doit figurer entre crochets.<br />
Exemples :<br />
char tab[10] ; tab est un tableau pouvant contenir 10 caractères<br />
double f[5][3] ; f est un tableau <strong>de</strong> 5 lignes et 3 colonnes (15 x double)<br />
Remarques :<br />
A lřutilisation, le premier élément du tableau est dřindice 0.<br />
Les éléments dřun tableau sont rangés consécutivement en mémoire (Ex. <strong>de</strong> tab[0] à tab[9])<br />
Pour les tableaux multi-dimensionnés, le <strong>de</strong>rnier indice « court » le plus vite ; Par exemple, pour le tableau f, le<br />
rangement en mémoire sera :<br />
f[0][0], f[0][1], f[0][2], f[1][0], f[1][1], f[1][2], f[2][0], … , f[4][1], f[4][2]<br />
IV. Constantes<br />
Lors <strong>de</strong> lřécriture <strong>de</strong> données constantes, la syntaxe permet dřindiquer au compilateur le type <strong>de</strong> la constante :<br />
Ecritures<br />
Exemples<br />
Caractère Řxř ŘAř, Ř=ř, Ř\\ř, Ř\řř<br />
Entier nnn ou nnn 421, 0, -12, +456<br />
Entier exprimé en octal 0nnn ou 0nnn 0712, 010, -057<br />
Entier hexadécimal 0xnn ou 0xNN 0x4A, 0x00ff<br />
double nnn.nn ou nnnEnn 1.0, -4., 3E4, 1.6e-19<br />
Chaîne <strong>de</strong> caractères "xxxxxx" "Bonjour les amis"<br />
-5-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
Remarque : le caractère \ est le caractère dŘéchappement en C. Il permet dřintroduire une séquence à signification<br />
particulière.<br />
Séquences dřéchappement possibles :<br />
Séquence Signification Exemple Résultat<br />
\r Retour chariot (en début <strong>de</strong> ligne). 0x0D printf("\rbonjour") bonjour<br />
\n Saut à la ligne suivante. 0x0A printf("bonjour\n") bonjour<br />
\t Tabulation. 0x09 printf("Rés.\tMoy.\n") Rés. Moy. <br />
\\ Caractère \ printf("valeur : \\10\\\n") valeur : \10\<br />
\ř Caractère ' x='\''-0x20 x=39-32x=7<br />
\" Caractère " printf("Il dit : \"Bof!\"\n") Il dit : "Bof!" <br />
\xnn ou \Xnn Nombre hexadécimal (n : digit hexa) 0x3B, 0xFA8 59, 4008<br />
\ooo Nombre octal (o : digit octal) \012, \033 10, 27<br />
On peut également préciser le type <strong>de</strong> constantes grâce à lřadjonction <strong>de</strong> suffixes :<br />
Suffixe : sans U ou u L ou l F ou f<br />
Entier int unsigned int long float<br />
Virgule flottante double - long double Float<br />
Exemples :<br />
12L : valeur 12 codée sur un type long<br />
40000u : codé sur un type unsigned int<br />
13.4 : constante double<br />
12.5f : constante float<br />
12UL : constante unsigned long int<br />
-6-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
V. Organisation générale d'un module<br />
Un programme C est constitué <strong>de</strong> un ou plusieurs modules (fichiers sources d'extension ".c").<br />
Chaque module sera organisé <strong>de</strong> la manière suivante :<br />
déclarations<br />
…<br />
fonction1<br />
…<br />
fonction2<br />
…<br />
…<br />
La zone <strong>de</strong> déclaration initiale permet <strong>de</strong> définir <strong>de</strong>s données globales au module ; Elles seront reconnues par l'ensemble<br />
<strong>de</strong>s fonctions définies dans le module.<br />
Pour l'ensemble <strong>de</strong>s modules, on ne <strong>de</strong>vra définir qu'une fonction main() qui sera le point <strong>de</strong> démarrage du programme.<br />
VI. Constitution d'une fonction<br />
VI.1. Définition d'une fonction<br />
Pour définir une fonction, on déclare le nom <strong>de</strong> la fonction, avec le type <strong>de</strong> valeur retournée par la fonction, ainsi que<br />
les noms et les types <strong>de</strong>s arguments transmis.<br />
Ensuite on définit le corps <strong>de</strong> la fonction (entre accola<strong>de</strong>s). Celui-ci a la structure suivante :<br />
déclarations <strong>de</strong> données locales à la fonction<br />
blocs d'instructions<br />
retour à la fonction appelante (avec un éventuel renvoi d'une valeur)<br />
Exemple :<br />
double somme(double a, double b)<br />
{<br />
double res;<br />
res = a + b;<br />
return res;<br />
}<br />
On rencontre encore quelques fois l'ancienne syntaxe (avant la standardisation du C Ansi) qu'il vaut mieux éviter, sauf<br />
si le compilateur ne reconnaît que celle-ci :<br />
double somme(a, b)<br />
double a, b;<br />
{<br />
double res;<br />
res = a + b;<br />
return res;<br />
}<br />
Remarques :<br />
lors <strong>de</strong> la définition d'une fonction, le caractère ";" doit être omis en fin <strong>de</strong> ligne<br />
en C, les paramètres sont toujours transmis par valeur<br />
si une fonction ne doit rien retourner (il s'agit alors d'une procédure), on la définit void :<br />
-7-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
Exemple :<br />
void init_glob()<br />
{<br />
A=0;<br />
TOT=12E4;<br />
}<br />
si le type retourné par la fonction est omis, le compilateur supposera qu'elle retourne une valeur <strong>de</strong> type int.<br />
lorsqu'une fonction n'a pas été déclarée antérieurement, le compilateur supposera qu'elle retourne un type int<br />
(d'où la nécessité <strong>de</strong> définir <strong>de</strong>s prototypes).<br />
VI.2. Prototypes<br />
Le prototypage permet d'indiquer au compilateur le type <strong>de</strong> donnée retourné par une fonction, ainsi que le nombre et le<br />
type <strong>de</strong>s arguments transmis ; Il s'agit donc en fait d'une déclaration <strong>de</strong> fonction.<br />
Cette déclaration permet au compilateur <strong>de</strong> réaliser <strong>de</strong>s contrôles (par exemple, il vérifie la cohérence <strong>de</strong>s paramètres<br />
transmis). Elle permet en outre la réalisation <strong>de</strong> transtypages automatiques, ce qui permet <strong>de</strong> lever bien <strong>de</strong>s erreurs.<br />
Exemple <strong>de</strong> prototype :<br />
double sin(double);<br />
Ce prototype indique au compilateur que la fonction sinus retourne une valeur <strong>de</strong> type double et qu'elle attend un<br />
paramètre <strong>de</strong> type double.<br />
Ce prototype est défini en standard dans "math.h".<br />
Si ce prototype n'avait pas été défini, lors <strong>de</strong> l'écriture <strong>de</strong> la ligne<br />
y = sin(3);<br />
le nombre 3 écrit ainsi étant <strong>de</strong> type entier, la fonction sin attendant un double (dont le codage en mémoire est<br />
différent), la fonction ne récupérerait pas la valeur "3.0" ; Le résultat fourni par la fonction sin serait dans ce cas<br />
aléatoire.<br />
Il en va <strong>de</strong> même pour la valeur retournée, puisque le compilateur suppose par défaut qu'une fonction retourne un type<br />
int, ce qui n'est pas le cas dans cet exemple.<br />
Par contre, si le prototype est lu par le compilateur avant l'utilisation <strong>de</strong> la fonction, les transtypages se font <strong>de</strong> manière<br />
automatique, l'entier 3 <strong>de</strong>venant alors un nombre à virgule flottante (3.0) avant l'appel <strong>de</strong> la fonction.<br />
Pour éviter toute erreur, il est donc essentiel <strong>de</strong> déclarer les prototypes <strong>de</strong>s fonctions avant leur utilisation (ici, en<br />
ajoutant par exemple la ligne : #inclu<strong>de</strong> ).<br />
On notera que la définition d'un prototype ne génère pas <strong>de</strong> co<strong>de</strong> ; elle communique uniquement <strong>de</strong>s informations à<br />
l'attention du compilateur.<br />
VII. Blocs d'instructions<br />
Un bloc d'instructions est constitué soit :<br />
d'une instruction élémentaire terminée par un caractère ";"<br />
d'un ensemble d'instructions élémentaires encadrées par <strong>de</strong>s accola<strong>de</strong>s ; dans ce cas, le bloc d'instructions peut<br />
comporter <strong>de</strong>s déclarations (locales à ce bloc).<br />
d'un simple caractère ';'. Dans ce cas, l'instruction est vi<strong>de</strong> (sans effet).<br />
Exemples <strong>de</strong> blocs d'instructions :<br />
ou :<br />
ou :<br />
x = 2*a + b;<br />
{<br />
x = 2;<br />
y = 4;<br />
z = x+y;<br />
}<br />
{<br />
int i;<br />
i = 3;<br />
x = 2*(i++);<br />
y=i;<br />
}<br />
-8-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
VII.1. Opérateurs<br />
Ils permettent l'évaluation d'expressions arithmétiques ou logiques.<br />
VII.1.a. Opérateurs arithmétiques :<br />
Opérateur Description Exemple (a=5, b=3, c=1)<br />
* multiplication x = 20*a x = 100<br />
/ division z = 10.0/4 z = 2.5<br />
+ addition x = 3+b x = 6<br />
- soustraction x = 3-b x = 0<br />
% modulo (reste <strong>de</strong> la division entière) x = 8%a x = 3<br />
^ ou exclusif (opération sur les bits) x = a^b x = 6<br />
| ou (opération sur les bits) x = a|b x = 7<br />
& et (opération sur les bits) x = a&b x = 1<br />
>c x = 1<br />
VII.1.b. Opérateurs logiques :<br />
Ils donnent comme résultat un entier (0 pour faux, 1 pour vrai).<br />
Opérateur Description Exemple (a=5, b=3)<br />
== test d'égalité x = a==b x = 0<br />
|| ou logique x = (a==1)||(a==2) x = 0<br />
&& et logique x = (a>0) && (a4 x = 1<br />
=4 x = 1<br />
Remarques :<br />
- Lors <strong>de</strong> l'exécution, il se peut que <strong>de</strong>s termes ne soient pas évalués dans <strong>de</strong>s expressions logiques ; cela<br />
peut être le cas si le résultat final peut être déterminé avant l'évaluation totale <strong>de</strong> l'expression. Dans ce cas,<br />
il est donc fortement déconseillé d'utiliser <strong>de</strong>s appels <strong>de</strong> fonctions ou d'effectuer <strong>de</strong>s affectations sur <strong>de</strong>s<br />
variables à l'intérieur d'expressions logiques (le résultat dépendra <strong>de</strong> la façon dont le compilateur aura<br />
effectué la traduction <strong>de</strong> l'expression).<br />
Par exemple, lors <strong>de</strong> l'écriture <strong>de</strong> la ligne<br />
if ((a>5) || (somme(a,b)
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
|= équivalent à # = # | … a |= b a = 7<br />
&= équivalent à # = # & … a &= b a = 1<br />
>= b-2 a = 2<br />
Remarques :<br />
En C, l'affectation est un opérateur à part entière : Elle donne un résultat qui peut être utilisé dans une expression, ce qui<br />
permet les écritures suivantes :<br />
x = (a=3)+1;<br />
met 3 dans a et 4 dans x<br />
x -= (a+=10); augmente a <strong>de</strong> 10 et soustrait le résultat <strong>de</strong> x<br />
Il faut cependant noter que ces écritures concises risquent <strong>de</strong> rendre le programme moins lisible. D'autre part, il n'est pas<br />
certain que le co<strong>de</strong> généré soit amélioré par ce type d'écriture quelquefois plus difficile à interpréter par le compilateur ;<br />
Tout dépend <strong>de</strong> la puissance du compilateur.<br />
VII.1.d. Opérateur ternaire :<br />
Opérateur Description Exemple (a=5, b=3, c=1)<br />
: choix d'une valeur selon une condition<br />
x=(a>4)(b*2):(c+1) x = 6<br />
si la condition est vraie, la première expression est<br />
retournée, sinon, la <strong>de</strong>uxième expression est retournée. x=(a3) x = 0<br />
++ auto incrémentation (post ou pré) x = a++ x = 5, a = 6<br />
x = ++a x = 6, a = 6<br />
-- auto décrémentation (post ou pré) x = a-- x = 5, a = 4<br />
x = --a x = 4, a = 4<br />
sizeof donne la taille d'un objet (donnée ou type).<br />
est équivalent à une constante, déterminée par le compilateur.<br />
sizeof(char) vaut 1<br />
sizeof sur un tableau donne le nombre d'octets occupé par le tableau<br />
sizeof(int) vaut 2 si le type int est codé sur 16 bits<br />
(type) opérateur cast (transtypage). Permet <strong>de</strong> modifier le type d'une expression ; type représente un<br />
type <strong>de</strong> donnée prédéfini.<br />
Exemples :<br />
i = (int)(100.0*sin(2.45));<br />
x = (double)(2*a+1);<br />
-10-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
VII.2. Expressions<br />
Les expressions utilisent <strong>de</strong>s opérateurs. L'ordre d'évaluation <strong>de</strong>s expressions dépend <strong>de</strong> la priorité <strong>de</strong>s opérateurs. Dans<br />
le doute, il est recommandé d'utiliser <strong>de</strong>s parenthèses.<br />
Exemples :<br />
3b<br />
x = 2*a + 3*b/4/c; est interprété comme : x 2<br />
a<br />
4 c<br />
La priorité <strong>de</strong>s opérateurs est indiquée ci-<strong>de</strong>ssous :<br />
Opérateurs<br />
Priorité<br />
() [] -> . 15<br />
! ~ ++ -- + * - * * * & * (type) sizeof 14<br />
* / % 13<br />
+ - 12<br />
> 11<br />
< >= 10<br />
== != 9<br />
& 8<br />
^ 7<br />
| 6<br />
&& 5<br />
|| 4<br />
: 3<br />
= += -= *= /= %= &= ^= |= = 2<br />
, 1<br />
(*) : Opérateurs unaires & pointeurs<br />
VII.3. Instructions <strong>de</strong> contrôle <strong>de</strong> déroulement<br />
Les instructions <strong>de</strong> contrôle sont celles offertes par tous les langages évolués, avec toutefois une plus gran<strong>de</strong> souplesse<br />
procurée par l'écriture concise du langage.<br />
Toute expression retournant une valeur peut être utilisée lors <strong>de</strong> l'utilisation d'une condition ; Si le résultat (converti en<br />
int) est nul, la condition sera considérée comme fausse ; Elle sera vraie dans le cas contraire.<br />
VII.3.a. Tests si … sinon …<br />
if (condition)<br />
bloc d'instructions à exécuter si la condition est vraie<br />
else<br />
bloc d'instructions à exécuter si la condition est fausse<br />
optionnel<br />
VII.3.b. Boucles tant que … faire :<br />
while (condition)<br />
bloc d'instructions à exécuter si la condition est vraie.<br />
la condition est réévaluée à la fin <strong>de</strong> l'exécution du bloc d'instructions ; si<br />
la condition est vraie, le bloc est exécuté <strong>de</strong> nouveau (voir graphe cicontre).<br />
Exemple :<br />
while(x
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
VII.3.c. Boucles faire … tant que :<br />
Exemple :<br />
do<br />
bloc d'instructions à exécuter.<br />
while (condition);<br />
Le bloc d'instructions est exécuté inconditionnellement ; La condition<br />
est ensuite évaluée ; si la condition est vraie, le bloc est exécuté <strong>de</strong><br />
nouveau (voir graphe ci-contre).<br />
non<br />
bloc<br />
d'instructions<br />
condition<br />
vraie <br />
oui<br />
do<br />
{<br />
printf("Entrer un nombre positif : ");<br />
scanf("%d",&x);<br />
}<br />
while(x
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
do<br />
Exemple :<br />
{<br />
k = getchar(); /* Acquisition clavier -> k */<br />
switch (k) /* Test <strong>de</strong> k */<br />
{<br />
case '1':<br />
menu1(); /* Appeler menu1 si '1' tapé */<br />
break; /* Quitter switch */<br />
case '2':<br />
menu2(); /* Appeler menu1 si '2' tapé */<br />
break; /* Quitter switch */<br />
case 'q':<br />
case 'Q':<br />
printf("Fin du programme.\n"); /* Quitter le programme si */<br />
exit(0); /* 'q' ou 'Q' tapé */<br />
<strong>de</strong>fault:<br />
printf("\n"); /* Erreur */<br />
}<br />
}<br />
while((k=='1') || (k=='2'));<br />
VII.3.f. Rupture <strong>de</strong> séquence break :<br />
break permet <strong>de</strong> sortir d'une boucle <strong>de</strong> type type while … , do … while , for ou d'un switch … case. On<br />
peut noter un exemple d'utilisation dans l'exemple précé<strong>de</strong>nt.<br />
VII.3.g. Rupture <strong>de</strong> séquence continue :<br />
continue permet d'interrompre le déroulement normal d'une boucle <strong>de</strong> type while … , do … while ou for<br />
en allant directement à la fin du bloc d'instructions.<br />
Exemple :<br />
for(i=0; i
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
VIII.1. Donnée globale au programme<br />
Pour qu'une donnée soit globale au programme, il<br />
suffit <strong>de</strong> la définir à l'extérieur d'un bloc <strong>de</strong> fonction.<br />
Pour y accé<strong>de</strong>r <strong>de</strong>puis un autre module, ou avant sa<br />
définition, il faut effectuer une déclaration <strong>de</strong> cette<br />
donnée avec le spécificateur extern, afin que le<br />
compilateur puisse connaître son existence.<br />
On note que par défaut, les noms <strong>de</strong>s fonctions sont<br />
globaux au programme ; les fonctions <strong>de</strong>s modules<br />
sont dont accessibles par la totalité <strong>de</strong>s modules.<br />
module 1<br />
...<br />
double x;<br />
...<br />
...<br />
x=2.0*a;<br />
module 2<br />
...<br />
extern double x;<br />
...<br />
...<br />
x = x+1.0;<br />
VIII.2. Donnée locale à un module<br />
Quelquefois, on souhaite définir une donnée globale à un ensemble <strong>de</strong> fonctions contenues dans un module, mais pas à<br />
la totalité du programme ; C'est notamment le cas lors <strong>de</strong> l'écriture <strong>de</strong> bibliothèques <strong>de</strong> fonctions dont on ne veut pas<br />
qu'un nom puisse interférer avec ceux <strong>de</strong> l'utilisateur <strong>de</strong> la bibliothèque.<br />
Pour rendre une donnée globale au module, il suffit <strong>de</strong> la déclarer à l'extérieur d'un corps <strong>de</strong> fonction en ajoutant le<br />
spécificateur static.<br />
Exemple :<br />
int x;<br />
x est globale au programme (et donc au module aussi)<br />
static double y;<br />
y est locale au module (inconnue <strong>de</strong>s autres modules)<br />
void fct1(void)<br />
{<br />
...<br />
}<br />
static void fct2(void)<br />
{<br />
...<br />
}<br />
la fonction fct1 est accessible par tout le programme<br />
la fonction fct2 n'est visible que dans ce module<br />
VIII.3. Donnée locale à une fonction<br />
Une donnée définie à l'intérieur d'un corps <strong>de</strong> fonction est locale à cette fonction et n'est donc accessible qu'à l'intérieur<br />
<strong>de</strong> cette fonction. On notera que les paramètres transmis à la fonction sont vus comme <strong>de</strong>s variables locales à cette<br />
fonction.<br />
Exemple :<br />
void fonction(int a, double x) a et x sont <strong>de</strong>s variables locales à la fonction<br />
{<br />
unsigned c,d;<br />
c et d sont <strong>de</strong>s variables locales à la fonction<br />
...<br />
}<br />
VIII.4. Donnée locale à un bloc d'instructions<br />
En C, il est possible <strong>de</strong> déclarer <strong>de</strong>s données à l'intérieur d'un bloc d'instructions. Dans ce cas, ces données sont locales<br />
au bloc d'instructions.<br />
Exemple :<br />
void fonction(int a, double x) a et x sont <strong>de</strong>s variables locales à la fonction<br />
{<br />
unsigned i;<br />
i est locale à la fonction<br />
...<br />
for(i=0; i
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
IX.1. static<br />
Ce mot clé signifie que la donnée doit être à allocation fixe pendant toute la durée d'exécution du programme ; il s'agit<br />
d'une donnée statique, dont l'adresse <strong>de</strong>meure inchangée pendant l'existence du programme.<br />
Remarques :<br />
Les données globales sont statiques, car elles existent dès le démarrage du programme.<br />
Déclarer une variable locale comme étant statique permet <strong>de</strong> retrouver sa valeur antérieure (lors du <strong>de</strong>rnier passage dans<br />
la fonction).<br />
Les variables statiques peuvent être initialisées ; on spécifie alors la valeur que doit prendre la variable lors du<br />
démarrage du programme.<br />
Une variable statique non initialisée est par défaut mise à zéro au démarrage du programme ; Ceci n'est cependant pas<br />
garanti sur tous les environnements.<br />
Exemple :<br />
void fonction(void)<br />
{<br />
{<br />
static x;<br />
x est <strong>de</strong> type int ; vaut 0 au démarrage du programme.<br />
static long double pi=3.14L; pi vaut 3.14 au démarrage du programme<br />
if(x
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
entrée. On <strong>de</strong>man<strong>de</strong> ainsi au compilateur <strong>de</strong> ne pas réaliser d'optimisation sur cette variable ; il <strong>de</strong>vra évaluer sa valeur à<br />
chaque accès, comme indiqué dans le programme.<br />
Exemple :<br />
...<br />
volatile char x;<br />
extern volatile unsigned char pio;<br />
...<br />
X. Les pointeurs<br />
X.1. Définition<br />
Les pointeurs permettent d'accé<strong>de</strong>r à <strong>de</strong>s données à partir <strong>de</strong> leur adresse.<br />
Notation :<br />
où<br />
et<br />
*nom_var<br />
nom_var représente la variable pointeur (qui contient une adresse)<br />
*nom_var représente la variable pointée.<br />
Déclaration :<br />
nom_type *nom_var;<br />
Exemple :<br />
char *c;<br />
c contient l'adresse <strong>de</strong> la variable pointée<br />
la variable pointée est <strong>de</strong> type char<br />
Certaines données sont constantes et l'utilisation <strong>de</strong> pointeurs pourrait autoriser la modification <strong>de</strong> ces données. Dans ce<br />
cas, les déclarations suivantes sont vali<strong>de</strong>s :<br />
pointeur sur une chaîne <strong>de</strong> caractères constante : "chaîne <strong>de</strong> caractères"<br />
pointeur sur une donnée constante : const char *c; (*c est constant)<br />
pointeur constant : double * const v; (v est constant)<br />
pointeur constant sur une donnée constante : const int * const p; (p et *p sont constants)<br />
X.2. Arithmétique <strong>de</strong>s pointeurs<br />
Les opérations suivantes sont vali<strong>de</strong>s :<br />
opérateur<br />
pointeur + entier<br />
pointeur - entier<br />
pointeur - pointeur<br />
pointeur comparaison pointeur<br />
résultat<br />
pointeur<br />
entier<br />
Lorsque l'on ajoute ou retranche un entier à un pointeur, on accè<strong>de</strong> à un élément positionné en mémoire comme s'il était<br />
dans un tableau. Par exemple, si p est un pointeur, les pointeurs (p+i) pointent sur les données situées à la suite <strong>de</strong> la<br />
donnée pointée par p, tandis que les pointeurs (p-i) pointent sur les données situées avant, comme indiqué ci-<strong>de</strong>ssous :<br />
…<br />
p-2<br />
p-1<br />
p p+1 p+2 …<br />
Le programme suivant peut ainsi être utilisé pour parcourir une chaîne <strong>de</strong> caractères :<br />
char *p, c;<br />
p = "HELLO";<br />
c = *p;<br />
c = *(p+1);<br />
p += 4;<br />
p--;<br />
c = 'H'<br />
c = 'E'<br />
*p = 'O'<br />
*p = 'L'<br />
Remarque :<br />
Quand on ajoute (ou retranche) un entier à un pointeur, l'adresse est augmentée (ou diminuée) <strong>de</strong> la taille (en octets, ou<br />
éléments <strong>de</strong> taille élémentaire) <strong>de</strong> l'élément pointé. C'est pourquoi le compilateur ne peut opérer <strong>de</strong>s opérations sur les<br />
-16-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
pointeurs que lorsqu'il connaît le type <strong>de</strong>s données pointées ; L'arithmétique <strong>de</strong>s pointeurs ne fonctionne donc pas avec<br />
<strong>de</strong>s pointeurs void.<br />
X.3. Utilité <strong>de</strong>s pointeurs<br />
En C, l'usage <strong>de</strong>s pointeurs est indispensable pour :<br />
accé<strong>de</strong>r aux éléments d'un tableau<br />
manipuler les chaînes <strong>de</strong> caractères<br />
permettre aux fonctions <strong>de</strong> retourner plusieurs valeurs<br />
X.3.a. Les tableaux<br />
Ils permettent <strong>de</strong> disposer <strong>de</strong> manière contiguë en mémoire <strong>de</strong>s données <strong>de</strong> même type. Par exemple, la tableau déclaré<br />
par :<br />
double v[5];<br />
place 5 variables en virgule flottante à partir <strong>de</strong> l'adresse v.<br />
v est donc un pointeur. Il est constant (sinon on perdrait l'adresse <strong>de</strong> base du tableau).<br />
v est l'adresse <strong>de</strong> la première donnée du tableau.<br />
Pour accé<strong>de</strong>r aux éléments du tableau, on utilise la notation v[i], où i est un entier et représente l'indice.<br />
En C, l'indice du premier élément d'un tableau est toujours 0. Ainsi, pour le tableau v contenant 5 éléments, on pourra<br />
accé<strong>de</strong>r aux éléments v[0] à v[4].<br />
Puisque v est un pointeur, on peut également accé<strong>de</strong>r à l'élément i du tableau en écrivant : *(v+i).<br />
Les notations v[i] et *(v+i) sont équivalentes ; Elles peuvent être utilisées même lorsque v n'est pas un tableau.<br />
Pour connaître l'espace mémoire occupé par un tableau, on peut utiliser l'opérateur sizeof sur ce tableau. Par exemple,<br />
dans le cas précé<strong>de</strong>nt, sizeof(v) donnerait 40 si le type double avait une taille <strong>de</strong> 8.<br />
Pour déterminer le nombre d'éléments que l'on peut mettre dans un tableau, on peut donc écrire l'expression suivante :<br />
sizeof(v)/sizeof(*v)<br />
On divise la taille du tableau par la taille du premier élément du tableau, ce qui donne le nombre d'éléments contenus (5<br />
dans l'exemple).<br />
Par contre, il faut bien noter que l'opérateur sizeof appliqué à un pointeur donne la taille du pointeur. Par exemple, avec<br />
la déclaration :<br />
char *str = "Hello";<br />
sizeof(str) donne la valeur 4 si les pointeurs occupent 4 octets. La déclaration ci-<strong>de</strong>ssus indique simplement que<br />
l'on définit un pointeur que l'on initialise sur une chaîne <strong>de</strong> caractères constante ("Hello").<br />
Quant à la déclaration suivante :<br />
char str[10] = "Hello";<br />
l'utilisation <strong>de</strong> sizeof(str) dans ce cas donnera 10, car on a ici défini un tableau <strong>de</strong> 10 caractères, ce tableau étant<br />
initialisé par les 6 caractères <strong>de</strong> la chaîne "Hello" (y compris l'octet nul).<br />
X.3.b. Chaînes <strong>de</strong> caractères<br />
En C, les chaînes <strong>de</strong> caractères sont <strong>de</strong>s tableaux <strong>de</strong> caractères. Le caractère '\0' est le délimiteur <strong>de</strong> chaîne et sera pris<br />
en compte par toutes les fonctions traitant <strong>de</strong>s chaînes <strong>de</strong> caractères.<br />
Une chaîne <strong>de</strong> caractères constante sera notée entre guillemets, par exemple : "Bonjour à tous". Les caractères<br />
successifs sont placés en mémoire et l'octet nul est ajouté à la fin. La chaîne "toto" occupe donc 5 octets.<br />
On trouvera <strong>de</strong>s exemples d'initialisation <strong>de</strong> chaînes <strong>de</strong> caractères dans le paragraphe précé<strong>de</strong>nt.<br />
X.3.c. Fonctions et pointeurs<br />
Les fonctions retournent une valeur unique. Lorsque l'on désire qu'une fonction retourne plusieurs valeurs, on utilise <strong>de</strong>s<br />
pointeurs au niveau <strong>de</strong>s paramètres transmis à la fonction : On transmet ainsi les paramètres par référence.<br />
Exemple d'une fonction initialisant un tableau à 0 :<br />
void InitTab(int *baseTab, unsigned nb)<br />
{<br />
unsigned i;<br />
for(i=0; i
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
La fonction InitTab aurait pu également être écrite ainsi :<br />
void InitTab(int *baseTab, unsigned nb)<br />
{<br />
while(nb--) *(baseTab++)=0;<br />
}<br />
Les paramètres étant transmis à la fonction par valeur, et ces <strong>de</strong>rniers étant locaux à la fonction, leur modification dans<br />
la fonction ne change pas la valeur <strong>de</strong>s données transmises en arguments lors <strong>de</strong> l'appel.<br />
Par contre, on accè<strong>de</strong> aux éléments <strong>de</strong> tableau par l'intermédiaire <strong>de</strong> l'adresse du tableau.<br />
Autre exemple permettant la recherche <strong>de</strong> minima et maxima :<br />
void MinMax(double x, double *Min, double *Max)<br />
{<br />
if(x < *Min) *Min = x;<br />
else if(x > *Max) *Max = x;<br />
}<br />
...<br />
double tab[100];<br />
unsigned i;<br />
double mini, maxi;<br />
...<br />
mini = maxi = *tab;<br />
for(i=1; i
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
Remarque :<br />
Opérations sur les flux peuvent échouer (disque plein, fichier introuvable…)<br />
Nécessité <strong>de</strong> vérifier validité opérations<br />
Tester les co<strong>de</strong>s dřerreurs (EOF ou NULL).<br />
XI.2. Flux en sortie.<br />
Par défaut lřécran (stdout) ne nécessite pas dřouverture.<br />
Accès en écriture <strong>de</strong>s fichiers.<br />
Fonctions <strong>de</strong> gestion du flux :<br />
printf, fprintf, sprintf,…<br />
int printf(const char *format, …)<br />
int fprintf(FILE *f, const char *format, …)<br />
int sprintf(char *str, const char *format, …)<br />
putchar, putc, fputc<br />
int putchar(int x)<br />
int putc(int x, FILE *f)<br />
int fputc(int x, FILE *f)<br />
puts, fputs<br />
char *puts(const char *str)<br />
char *fputs(const char *str, FILE *f)<br />
fwrite<br />
int fwrite(const void *buffer, size_t size, size_t nb, FILE *f)<br />
XI.3. Flux en entrée.<br />
Par défaut le clavier (stdin) ne nécessite pas dřouverture.<br />
Accès en lecture <strong>de</strong>s fichiers.<br />
Fonctions <strong>de</strong> gestion du flux :<br />
scanf, fscanf, sscanf,…<br />
int scanf(const char *format,…)<br />
int fscanf(FILE *f, const char *format,…)<br />
int sscanf(char *s, const char *format,…)<br />
getchar, getc, fgetc<br />
int getchar(void)<br />
int getc(FILE *f)<br />
int fgetc(FILE *f)<br />
gets, fgets<br />
char *gets(void)<br />
char *fgets(char *<strong>de</strong>st, size_t nb_max, FILE *f)<br />
fread<br />
int fread(void *buffer, size_t size, size_t nb, FILE *f)<br />
XI.4. Fonctions <strong>de</strong> gestion<br />
<br />
<br />
<br />
<br />
<br />
long ftell(FILE *f)<br />
int fseek(FILE *f, long offset, int fromwhere)<br />
void rewind(FILE *f)<br />
int feof(FILE *f)<br />
int fflush(FILE *f)<br />
XII. Fonctions standard<br />
XII.1. Manipulation <strong>de</strong> chaînes <strong>de</strong> caractères <br />
memchr strcat strchr strrstr<br />
memcmp strncat strrchr strlen<br />
memcpy strcpy strspn strerror<br />
memmove strncpy strcspn<br />
memset strcmp strpbrk<br />
strncmp<br />
strtok<br />
-19-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
XII.1.a. Traitement <strong>de</strong> données brutes<br />
memchr : recherche le caractère c dans les n premiers octets du tableau s.<br />
void *memchr(const void *s, int c, size_t n);<br />
Cette fonction retourne un pointeur sur la première occurence <strong>de</strong> c dans s ; elle retourne NULL si c ne figure pas<br />
dans le tableau s.<br />
memcmp : compare <strong>de</strong>ux blocs, s1 et s2, sur une longueur d'exactement n octets.<br />
int memcmp(const void *s1, const void *s2, size_t n);<br />
Cette fonction retourne une valeur < 0 si s1 est inférieur à s2, nulle si s1 est i<strong>de</strong>ntique à s2 et > 0 si s1 est supérieur à<br />
s2.<br />
memcpy : copie un bloc <strong>de</strong> n octets <strong>de</strong> src dans <strong>de</strong>st.<br />
void *memcpy(void *<strong>de</strong>st, const void *src, size_t n);<br />
Cette fonction retourne le pointeur <strong>de</strong>st.<br />
memmove : copie un bloc <strong>de</strong> n octets <strong>de</strong> src dans <strong>de</strong>st.<br />
void *memmove(void *<strong>de</strong>st, const void *src, size_t n);<br />
Cette fonction retourne le pointeur <strong>de</strong>st.<br />
memset : initialise n octets <strong>de</strong> s avec l'octet c.<br />
void *memset(void *s, int c, size_t n);<br />
Cette fonction retourne le pointeur s.<br />
XII.1.b. Copie et concaténation :<br />
strcat : concatène la chaîne src à <strong>de</strong>st.<br />
char *strcat(char *<strong>de</strong>st, const char *src);<br />
Cette fonction retourne <strong>de</strong>st.<br />
strncat : ajoute au plus maxlen caractères <strong>de</strong> la chaîne src à la fin <strong>de</strong> <strong>de</strong>st.<br />
char *strncat(char *<strong>de</strong>st, const char *src, size_t maxlen);<br />
Cette fonction retourne <strong>de</strong>st.<br />
strcpy : copie la chaîne src dans <strong>de</strong>st.<br />
char *strcpy(char *<strong>de</strong>st, const char *src);<br />
Cette fonction retourne l'adresse <strong>de</strong> <strong>de</strong>st.<br />
strncpy : copie jusqu'à maxlen caractères <strong>de</strong> la chaîne src dans la chaîne <strong>de</strong>st.<br />
char *strncpy(char *<strong>de</strong>st, const char *src, size_t maxlen);<br />
Si maxlen caractères sont copiés, aucun caractère nul n'est ajouté ; le contenu <strong>de</strong> la zone <strong>de</strong>st est une chaîne terminée<br />
par un caractère nul.<br />
Cette fonction retourne <strong>de</strong>st.<br />
XII.1.c. Comparaisons <strong>de</strong> chaînes <strong>de</strong> caractères :<br />
strcmp : compare la chaîne s2 à la chaîne s1.<br />
int strcmp(const char *s1, const char *s2);<br />
Cette fonction retourne une valeur < 0 si s1 est inférieur à s2, nulle si s1 est i<strong>de</strong>ntique à s2 et > 0 si s1 est supérieur à<br />
s2. La comparaison est signée.<br />
-20-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
strncmp : compare les chaînes s2 et s1 en se limitant aux maxlen premiers caractères.<br />
int strncmp(const char *s1, const char *s2, size_t maxlen);<br />
Cette fonction retourne une valeur < 0 si s1 est inférieur à s2, nulle si s1 est i<strong>de</strong>ntique à s2 et > 0 si s1 est supérieur à<br />
s2. Effectue une comparaison signée.<br />
XII.1.d. Recherche <strong>de</strong> séquences :<br />
strchr : cherche le caractère c dans la chaîne str.<br />
char *strchr(const char *str, int c);<br />
Cette fonction retourne un pointeur sur la première occurrence du caractère c dans str ; si c ne figure pas dans str,<br />
strchr retourne NULL.<br />
strrchr : cherche dans la chaîne s la <strong>de</strong>rnière occurrence du caractère c.<br />
char *strrchr(const char *s, int c);<br />
Cette fonction retourne un pointeur sur la <strong>de</strong>rnière occurrence du caractère c dans s ; si c ne figure pas dans la<br />
chaîne, elle retourne NULL.<br />
strspn : cherche la longueur du segment initial <strong>de</strong> s1 formé uniquement <strong>de</strong> caractères figurant dans la chaîne s2.<br />
size_t strspn(const char *s1, const char *s2);<br />
strcspn : cherche la longueur du premier segment <strong>de</strong> s1 formé uniquement <strong>de</strong> caractères NE FIGURANT PAS dans la<br />
chaîne s2.<br />
size_t strcspn(const char *s1, const char *s2);<br />
strpbrk : cherche dans la chaîne s1 la première occurrence d'un caractère quelconque <strong>de</strong> la chaîne s2.<br />
char *strpbrk(const char *s1, const char *s2);<br />
Cette fonction retourne un pointeur sur la première occurrence dans s1 d'un caractère <strong>de</strong> s2 ; si aucun <strong>de</strong>s caractères<br />
<strong>de</strong> s2 ne figure dans s1, c'est la valeur NULL qui est retournée.<br />
strstr : cherche la première occurrence <strong>de</strong> la sous-chaîne s2 dans s1.<br />
char *strstr(const char *s1, const char *s2);<br />
Cette fonction retourne un pointeur sur la partie <strong>de</strong> s1 i<strong>de</strong>ntique à s2 (un pointeur sur s2 dans s1). S'il n'y a pas<br />
d'occurrence <strong>de</strong> s2 dans s1, c'est la valeur NULL qui est retournée.<br />
strtok : cherche dans la chaîne s1 le premier élément ne figurant pas dans s2.<br />
char *strtok(char *s1, const char *s2);<br />
s2 définit <strong>de</strong>s caractères séparateurs. strtok considère la chaîne s1 comme une suite d'éléments séparés par <strong>de</strong>s<br />
caractères <strong>de</strong> la chaîne s2. Si aucun élément n'est trouvé dans s1, la fonction retourne la valeur NULL. Si un élément<br />
est trouvé, le caractère nul est écrit dans s1 à la suite <strong>de</strong> l'élément et strtok retourne un pointeur sur cet élément.<br />
Les appels suivants à strtok avec NULL comme premier argument poursuivent la recherche dans la chaîne s1 <strong>de</strong><br />
l'appel précé<strong>de</strong>nt et continuent après le <strong>de</strong>rnier élément trouvé.<br />
XII.1.e. Fonctions diverses :<br />
strlen : calcule la longueur <strong>de</strong> la chaîne s.<br />
size_t strlen(const char *s);<br />
Cette fonction retourne le nombre <strong>de</strong> caractères <strong>de</strong> la chaîne s, le caractère nul d'arrêt n'étant pas compté.<br />
strerror : retourne un pointeur sur une chaîne contenant un message d'erreur.<br />
char *strerror(int errnum);<br />
Cette fonction retourne un pointeur sur le message d'erreur associé à errnum.<br />
-21-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
XII.2. Entrées sorties <br />
clearerr getc flushall rewind<br />
fclose getchar fopen scanf<br />
fcloseall gets fprintf setbuf<br />
fdopen getw fputc setvbuf<br />
feof perror fputchar sprintf<br />
ferror printf fputs scanf<br />
fflush putcs fread _strerror<br />
fgetc putchar freopen strerror<br />
fgetchar puts fscanf vfscanf<br />
fgetpos tmpfile fseek vprintf<br />
fgets tmpnam fsetpos vscanf<br />
fileno ungetc putw vsprintf<br />
ftell unlink remove vsscanf<br />
fwrite vfprintf rename<br />
XII.2.a. Entrées / Sorties formatées :<br />
scanf : effectue <strong>de</strong>s entrées formatées <strong>de</strong>puis le flux standard stdin<br />
int scanf(const char *format, ...);<br />
Cette fonction retourne le nombre <strong>de</strong> champs d'entrée traités correctement. Elle traite les entrées selon la chaîne <strong>de</strong><br />
format et place les résultats dans les emplacements mémoire pointés par les arguments.<br />
printf : écrit <strong>de</strong>s sorties formatées dans le flux standard stdout.<br />
int printf(const char *format, ...);<br />
Cette fonction applique une spécification <strong>de</strong> format à un nombre variable d'arguments et écrit les données formatées<br />
dans le flux stdout. printf retourne le nombre d'octets écrits. En cas d'erreur, elle retourne EOF.<br />
XII.2.b. Spécifications <strong>de</strong> format (pour printf et scanf) :<br />
% [flags] [width] [.prec] [F|N|h|l] type<br />
Type Format <strong>de</strong> la sortie<br />
d : entier décimal signé<br />
i : entier décimal signé<br />
o : entier octal non signé<br />
u : entier décimal non signé<br />
x : avec printf = entier hexadécimal non signé en minuscules<br />
: avec scanf = entier hexadécimal<br />
X : avec printf = entier hexadécimal non signé en majuscules<br />
: avec scanf = entier hexadécimal long<br />
f : virgule flottante [-]dddd.ddd<br />
e : virgule flottante avec exposant [-]d.ddd e [+/-]ddd<br />
g : format e ou f suivant la précision<br />
E : comme e mais l'exposant est la lettre E<br />
G : comme g mais l'exposant est la lettre E<br />
c : caractère simple<br />
s : affiche les caractères jusqu'au caractère nul d'arrêt '\0' ou jusqu'à ce que la précision soit atteinte<br />
% : caractère <strong>de</strong> pourcentage %<br />
p : pointeur<br />
n : range (à l'adresse pointée par l'argument d'entrée) le nombre <strong>de</strong> caractères écrits.<br />
[flags] Signification<br />
aucun : résultat justifié à droite et complété à gauche par <strong>de</strong>s espaces ou <strong>de</strong>s 0<br />
- : résultat justifié à gauche et complété à droite par <strong>de</strong>s espaces<br />
+ : les résultats commencent toujours par le signe + ou -<br />
espace : n'affiche le signe que pour les valeurs négatives<br />
# l'argument doit être converti en utilisant une autre forme :<br />
c,s,d,i,u : sans effet<br />
-22-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
o : 0 sera placé <strong>de</strong>vant l'argument s'il est non nul<br />
x ou X : 0x ou 0X placé <strong>de</strong>vant la valeur <strong>de</strong> l'argument<br />
e, E, f : le résultat contiendra toujours un point décimal<br />
g or G : même chose mais sans les zéros à droite<br />
[width] Effet sur l'affichage<br />
n : affichage d'au moins n caractères, au besoin complété par <strong>de</strong>s espaces<br />
0n : affichage d'au moins n caractères, au besoin complété à gauche par <strong>de</strong>s chiffres 0<br />
* : l'argument suivant <strong>de</strong> la liste contient la spécification <strong>de</strong> largeur<br />
[.prec] Effet sur l'affichage<br />
aucun : précision par défaut<br />
.0 : avec d,i,o,u,x précision par défaut<br />
: avec e, E, f pas <strong>de</strong> point décimal<br />
.n : n caractères au plus<br />
* : l'argument suivant <strong>de</strong> la liste contient la précision<br />
Modificateur Comment arg est interprété<br />
F : arg est interprété comme un pointeur long<br />
N : arg est interprété comme un pointeur court<br />
h : arg est interprété comme un entier <strong>de</strong> type short pour d,i,o,u,x,X<br />
l : arg est interprété comme un entier <strong>de</strong> type long pour d,i,o,u,x,X<br />
l : arg est interprété comme un réel <strong>de</strong> type double pour e,E,f,g,G (scanf)<br />
L : arg est interprété comme un réel <strong>de</strong> type long double pour e,E,f,g,G<br />
XII.2.c. Fonctions d'entrées :<br />
getchar : (macro) retourne un caractère <strong>de</strong>puis le flux d'entrée stdin.<br />
int getchar(void);<br />
getchar retourne le caractère lu, après conversion en un entier <strong>de</strong> type int sans extension <strong>de</strong> signe. Elle retourne EOF à la<br />
fin du fichier ou en cas d'erreur.<br />
getc : (macro) retourne un caractère <strong>de</strong>puis un flux.<br />
int getc(FILE *fp);<br />
Cette macro retourne le caractère lu. Elle retourne EOF à la fin du fichier ou en cas d'erreur.<br />
fgets : lit une chaîne dans un flux.<br />
char *fgets(char *s, int n, FILE *fp);<br />
Lorsqu'elle réussit, cette fonction retourne la chaîne s ; elle retourne NULL en fin <strong>de</strong> fichier ou en cas d'erreur.<br />
XII.2.d. Fonctions <strong>de</strong> sorties :<br />
putchar : envoie un caractère dans le flux standard stdout.<br />
int putchar(int ch);<br />
Si la sortie peut se faire, putchar retourne le caractère ch ; s'il y a une erreur, elle retourne EOF.<br />
putc : sort un caractère dans un flux.<br />
int putc(int ch, FILE *fp);<br />
Si la sortie peut se faire, putc retourne le caractère ch ; s'il y a une erreur, elle retourne EOF.<br />
fputs : envoie une chaîne dans un flux.<br />
int fputs(const char *s, FILE *fp);<br />
S'il n'y a pas d'erreur, cette fonction retourne le <strong>de</strong>rnier caractère écrit ; sinon, c'est la valeur EOF qui est retournée.<br />
-23-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
XII.2.e. Gestion <strong>de</strong> fichiers (flux) :<br />
fopen : ouvre un flux.<br />
FILE *fopen(const char *filename, const char *mo<strong>de</strong>);<br />
Si elle aboutit, cette fonction retourne un pointeur sur le flux qui vient d'être ouvert ; sinon, elle retourne NULL.<br />
Types d'ouverture :<br />
r : ouvert pour lecture<br />
w : créé pour écriture<br />
a : ouvert pour écriture en fin <strong>de</strong> fichier<br />
+ : pour permettre un accès en lecture et en écriture<br />
b : ouvert en mo<strong>de</strong> binaire<br />
t : ouvert en mo<strong>de</strong> texte<br />
fclose : ferme un flux.<br />
int fclose(FILE *fp);<br />
Cette fonction retourne 0 si elle réussit et EOF lorsqu'une erreur est détectée.<br />
fflush : vi<strong>de</strong> la mémoire tampon associée à un flux.<br />
int fflush(FILE *fp);<br />
Cette fonction retourne EOF lorsqu'une erreur est détectée.<br />
fseek : repositionne le pointeur <strong>de</strong> fichier d'un flux.<br />
int fseek(FILE *fp, long offset, int whence);<br />
offset est le nouvelle position par rapport l'emplacement donné par whence. Cette fonction retourne 0 si le pointeur a<br />
pu être déplacé et une valeur non nulle sinon.<br />
Constantes symboliques :<br />
Positionnement du pointeur <strong>de</strong> fichier.<br />
SEEK_SET au début du fichier<br />
SEEK_CUR à la position courante du pointeur<br />
SEEK_END à la fin du fichier<br />
fsetpos : positionne le pointeur <strong>de</strong> fichier d'un flux.<br />
int fsetpos(FILE *fp, const fpos_t *pos);<br />
Le nouvel emplacement pointé par pos est la valeur obtenue lors d'un précé<strong>de</strong>nt appel à fgetpos. Quand l'opération<br />
aboutit, cette fonction retourne 0. Dans le cas contraire, elle retourne une valeur non nulle.<br />
Rem. : fpos_t : Type pour les pointeurs <strong>de</strong> fichiers.<br />
ftell : retourne la position courante du pointeur d'un fichier.<br />
long ftell(FILE *fp);<br />
Cette fonction retourne la position courante du pointeur <strong>de</strong> fichier ou la valeur -1L quand il y a une erreur.<br />
fwrite : écrit dans un flux.<br />
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);<br />
fwrite écrit n objets ayant chacun une longueur <strong>de</strong> size octets. Cette fonction retourne le nombre d'objets (et non le<br />
nombre d'octets) réellement écrits.<br />
fread : lit <strong>de</strong>s données <strong>de</strong>puis un flux.<br />
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);<br />
Cette fonction lit n objets ayant chacun une longueur <strong>de</strong> size octets ; elle retourne le nombre d'objets (et non le<br />
nombre d'octets) réellement lus.<br />
-24-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
XII.2.f. Exemple : copie <strong>de</strong> fichier texte<br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
void erreur(int err, const char *fmt, ...)<br />
{<br />
va_list arg;<br />
va_start(arg,fmt);<br />
fprintf(st<strong>de</strong>rr,"Erreur [%d] : ",err);<br />
vfprintf(st<strong>de</strong>rr,fmt,arg);<br />
va_end(arg);<br />
exit(err);<br />
}<br />
main(int argc, char *argv[])<br />
{<br />
FILE *fs, *fd ;<br />
int x ;<br />
if(argc>1)<br />
{<br />
fs=fopen(argv[1],"r");<br />
if(fs==NULL) erreur(1,"Le fichier %s ne peut être ouvert.\n",argv[1]);<br />
}<br />
else fs=stdin;<br />
if(argc>2)<br />
{<br />
fd=fopen(argv[2],"w");<br />
if(fd==NULL) erreur(2,"Création <strong>de</strong> %s impossible.\n",argv[1]);<br />
}<br />
else fd=stdout;<br />
while((x=getc(fs))!=EOF)<br />
if(putc(x,fd)==EOF) erreur(3,"Erreur en écriture");<br />
fclose(fd);<br />
fclose(fs);<br />
return 0;<br />
}<br />
XII.3. Fonctions utilitaires :<br />
atof rand bsearch calloc abort abs<br />
atoi srand qsort malloc exit labs<br />
atol realloc atexit div<br />
strtod free system ldiv<br />
strtol<br />
getenv<br />
strtoul<br />
XII.3.a. Conversion <strong>de</strong> chaînes <strong>de</strong> caractères :<br />
atof : convertit une chaîne <strong>de</strong> caractères en un nombre à virgule flottante.<br />
double atof(const char *s);<br />
Cette fonction retourne le résultat <strong>de</strong> la conversion ou 0 si s ne peut pas être convertie.<br />
atoi : convertit une chaîne en un entier<br />
int atoi(const char *s);<br />
Retourne le résultat <strong>de</strong> la conversion <strong>de</strong> la chaîne passée en argument. Si la chaîne ne peut pas être convertie, la<br />
valeur retournée est 0.<br />
atol : convertit une chaîne <strong>de</strong> caractères en un entier long.<br />
long atol(const char *s);<br />
Cette fonction retourne le résultat <strong>de</strong> la conversion en entier <strong>de</strong> la chaîne passée en argument. Si la chaîne ne peut<br />
pas être convertie, la valeur retournée est 0.<br />
-25-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
strtod : convertit une chaîne en une valeur <strong>de</strong> type double.<br />
double strtod(const char *s, char **endptr);<br />
Cette fonction retourne la valeur <strong>de</strong> la chaîne s convertie en une valeur <strong>de</strong> type double. s doit être une suite <strong>de</strong><br />
caractères correspondant au format :<br />
[ws] [sn] [ddd] [.] [ddd] [fmt[sn]ddd]<br />
strtol : convertit la chaîne s en une valeur <strong>de</strong> type long, exprimée dans la base indiquée par radix.<br />
long strtol(const char *s, char **endptr, int radix);<br />
Cette fonction retourne la valeur convertie <strong>de</strong> la chaîne s ou bien 0 en cas d'erreur. s doit être une suite <strong>de</strong> caractères<br />
correspondant au format :<br />
[ws] [sn] [0] [x] [ddd]<br />
strtoul : convertit une chaîne en une valeur <strong>de</strong> type unsigned long, exprimée dans la base indiquée par radix.<br />
unsigned long strtoul(const char *s, char **endptr, int radix);<br />
Cette fonction retourne la valeur convertie <strong>de</strong> la chaîne ou bien 0 en cas d'erreur.<br />
XII.3.b. Générateur <strong>de</strong> nombres aléatoires :<br />
rand : générateur <strong>de</strong> nombres aléatoires.<br />
int rand(void);<br />
Cette fonction retourne un nombre aléatoire compris entre 0 et RAND_MAX. RAND_MAX est défini dans stdlib.h.<br />
srand : initialise le générateur <strong>de</strong> nombres aléatoires.<br />
void srand(unsigned seed);<br />
srand ne retourne pas <strong>de</strong> valeur.<br />
XII.3.c. Fouilles et tris :<br />
bsearch : recherche dichotomique dans un tableau (binary search).<br />
void *bsearch(const void *key, const void *base, size_t *nelem, size_t width,<br />
int (*fcmp)(const void*, const void*));<br />
bsearch retourne l'adresse du premier élément du tableau correspondant à la clé <strong>de</strong> recherche key. Si aucun élément<br />
ne convient, elle retourne 0.<br />
Dans bsearch, la valeur retournée par *fcmp est < 0 si *elem1 < *elem2, nulle si *elem1 est égal à *elem2 et > 0 if<br />
*elem1 > *elem2.<br />
Le tableau doit être trié en ordre croissant.<br />
qsort : effectue un tri rapi<strong>de</strong> (Quicksort).<br />
void qsort(void *base, size_t nelem, size_t width,<br />
int(*fcmp)(const void *, const void *));<br />
Cette fonction effectue le tri <strong>de</strong>s nelem éléments <strong>de</strong> taille width, situés dans le tableau pointé par base.<br />
XII.3.d. Allocation <strong>de</strong> mémoire :<br />
calloc : alloue <strong>de</strong> la mémoire.<br />
void *calloc(size_t nelem, size_t elsize);<br />
Alloue un bloc pour nelem items formés <strong>de</strong> elsize octets ; initialise le bloc avec <strong>de</strong>s zéros. Cette fonction retourne un<br />
pointeur sur le bloc nouvellement alloué ou la valeur NULL lorsqu'il n'y a pas assez <strong>de</strong> place.<br />
malloc : alloue <strong>de</strong> la mémoire.<br />
void *malloc(size_t size);<br />
L'argument size est exprimé en octets. Cette fonction retourne un pointeur sur le bloc nouvellement alloué, ou bien<br />
la valeur NULL quand il n'y a pas assez d'espace pour un nouveau bloc. Si size = 0, elle retourne NULL.<br />
-26-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
realloc : réalloue <strong>de</strong> la mémoire.<br />
void *realloc(void *block, size_t size);<br />
Cette fonction tente d'ajuster (augmenter ou diminuer) la taille d'un bloc précé<strong>de</strong>mment alloué pour l'amener à une<br />
taille <strong>de</strong> size octets. Elle retourne l'adresse du bloc réajusté qui n'est pas toujours la même que le bloc d'origine. Si<br />
l'opération n'a pas été possible ou si size vaut 0, elle retourne la valeur NULL.<br />
free : libère <strong>de</strong>s blocs alloués par malloc ou calloc.<br />
void free(void *block);<br />
XII.3.e. Fonctions système :<br />
abort : arrêt anormal d'un programme.<br />
void abort(void);<br />
exit : met fin à un programme.<br />
void exit(int status);<br />
Avant la sortie, les mémoires tampons sont vidées, les fichiers sont fermés et les fonctions <strong>de</strong> sortie sont appelées.<br />
atexit : enregistre une fonction <strong>de</strong> sortie.<br />
int atexit(atexit_t func);<br />
Cette fonction retourne 0 si l'enregistrement <strong>de</strong> la fonction peut avoir lieu et une valeur non nulle en cas d'anomalie.<br />
system : lance une comman<strong>de</strong> du système d'exploitation.<br />
int system(const char *command);<br />
system exécute une comman<strong>de</strong> du système d'exploitation<br />
Cette fonction retourne zéro si l'opération a pu se réaliser et -1 sinon.<br />
getenv : retourne un élément <strong>de</strong> l'environnement.<br />
char *getenv(const char *name);<br />
Si l'opération est possible, cette fonction retourne un pointeur sur la valeur associée à son argument name ; si le nom<br />
n'est pas défini dans l'environnement, retourne NULL.<br />
XII.3.f. Opérations sur <strong>de</strong>s entiers :<br />
abs : retourne la valeur absolue d'un entier.<br />
int abs(int x);<br />
labs : valeur absolue pour <strong>de</strong>s valeurs <strong>de</strong> type long.<br />
long labs(long x);<br />
div : divise <strong>de</strong>ux entiers.<br />
ldiv : divise <strong>de</strong>ux entiers <strong>de</strong> type long.<br />
div_t div(int numer, int <strong>de</strong>nom);<br />
ldiv_t ldiv(long lnumer, long l<strong>de</strong>nom);<br />
Chaque fonction retourne une structure dont les éléments sont quotient (quot) et le reste (rem). Les éléments sont<br />
<strong>de</strong>s entiers pour div et <strong>de</strong>s entiers longs pour ldiv.<br />
Type div_t : Type <strong>de</strong>s valeurs retournées par la fonction <strong>de</strong> division entière.<br />
type<strong>de</strong>f struct<br />
{<br />
int quot, rem;<br />
} div_t;<br />
Type ldiv_t : Type <strong>de</strong>s valeurs retournées par la fonction <strong>de</strong> division entre entiers longs.<br />
type<strong>de</strong>f struct<br />
{<br />
long quot, rem;<br />
} ldiv_t;<br />
-27-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
XIII. Structures<br />
Ces données sont construites par le programmeur à partir <strong>de</strong>s données déjà définies (par le langage ou le programmeur).<br />
Les structures permettent au programmeur <strong>de</strong> rassembler dans une même donnée un ensemble dřinformations liées.<br />
Par exemple, on souhaite se constituer un fichier dřindividus contenant le nom, le prénom, lřage et le poids pour chaque<br />
individu ; Ces informations étant propres à chaque individu, on préfère constituer une donnée unique contenant<br />
lřensemble <strong>de</strong> ces informations ; Cette nouvelle donnée sřappelle en C une structure.<br />
On pourra déclarer cette structure <strong>de</strong> la manière suivante :<br />
struct T_Individu<br />
{<br />
char nom[40] ;<br />
char prenom[40] ;<br />
unsigned age ;<br />
float poids;<br />
} ;<br />
champs <strong>de</strong> la structure<br />
struct : mot clé définissant une structure<br />
T_Individu : Nom du type <strong>de</strong> structure défini par le<br />
programmeur.<br />
Cette structure est composée <strong>de</strong> quatre champs (nom, prénom, âge et poids).<br />
Avec cette définition, on a défini un type <strong>de</strong> donnée (<strong>de</strong> type struct T_Individu). On peut alors définir <strong>de</strong> nouvelles<br />
données dans ce type :<br />
struct T_Individu toto ;<br />
struct T_Individu x, individu[20] ;<br />
Dans cet exemple, toto représente une variable contenant le nom, le prénom, lřâge et le poids dřun individu.<br />
Pour accé<strong>de</strong>r à un champ <strong>de</strong> la variable toto, on utilise le caractère Ř.ř.<br />
On pourra ainsi écrire :<br />
printf("Entrer le nom : ") ;<br />
scanf("%s",toto.nom) ;<br />
toto.age=4 ;<br />
toto.poids=12.3 ;<br />
On peut mettre les structures sous forme <strong>de</strong> tableaux avec une déclaration du type :<br />
struct T_Individu individu[20] ;<br />
Dans ce cas, on peut accé<strong>de</strong>r à lřélément i du tableau en écrivant individu[i], soit, par exemple pour son âge,<br />
individu[i].age, comme dans lřexemple suivant :<br />
printf("Entrer le nom n°%d : ",n) ;<br />
scanf("%s",toto[n].nom) ;<br />
scanf("%u",&toto[n].age) ;<br />
scanf("%f",&toto[n].poids) ;<br />
printf("%s : %u ans (%f kg)\n",toto[n].nom,toto[n].age,toto[n].poids) ;<br />
Il est possible <strong>de</strong> définir une structure sans définir un type <strong>de</strong> structure avec la déclaration suivante :<br />
struct<br />
{<br />
int forme ;<br />
double perimetre ;<br />
double aire ;<br />
} objet[200], rectangle, disque;<br />
Dans ce cas, il est bien sûr nécessaire <strong>de</strong> définir une ou plusieurs variables.<br />
On peut initialiser les structures par la notation suivante :<br />
struct T_Individu Homme =<br />
{<br />
"Dupont",<br />
"Marcel",<br />
24,<br />
84.5<br />
} ;<br />
Cette initialisation peut se faire dans les classes dřallocation const, static ou auto (attention alors à lřefficacité du<br />
programme).<br />
Les structures étant <strong>de</strong>s données <strong>de</strong> taille importante, il est plus efficace <strong>de</strong> les transmettre aux fonctions par<br />
lřintermédiaire <strong>de</strong> pointeurs :<br />
-28-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
Exemple :<br />
struct T_Complexe {double re, im ; } ;<br />
double module(struct T_Complexe *x)<br />
{<br />
return (*x).re*(*x).re+(*x).im*(*x).im;<br />
}<br />
Lřusage <strong>de</strong>s pointeurs étant fréquent avec les structures et cette notation étant lour<strong>de</strong> et peu lisible, le C a défini une<br />
autre notation lors <strong>de</strong> lřutilisation <strong>de</strong> pointeurs <strong>de</strong> structures :<br />
double module(struct T_Complexe *x)<br />
{<br />
return x->re* x->re + x->im * x->im;<br />
}<br />
x->re se lit : le champ re <strong>de</strong> la structure pointée par x.<br />
XIV. Le préprocesseur<br />
Le préprocesseur est un programme invoqué automatiquement par le compilateur avant la réalisation <strong>de</strong> la compilation.<br />
Son rôle est dřeffectuer <strong>de</strong>s transformations sur le fichier source. Cřest en réalité le fichier texte créé qui sera transmis<br />
au compilateur.<br />
Les comman<strong>de</strong>s du préprocesseur débutent par le caractère Ř#ř. Elles occupent toute la ligne débutant par Ř#ř et ne sont<br />
pas terminées par Ř ;ř. On peut les étendre sur plusieurs lignes en ayant recours au caractère dřéchappement Ř\ř situé en<br />
fin <strong>de</strong> ligne.<br />
XIV.1. Comman<strong>de</strong> inclu<strong>de</strong>.<br />
#inclu<strong>de</strong> <br />
ou<br />
#inclu<strong>de</strong> "fichier2"<br />
Permet <strong>de</strong> substituer en lieu et place <strong>de</strong> la comman<strong>de</strong> le contenu du fichier désigné.<br />
Les caractères Řř indiquent au préprocesseur <strong>de</strong> rechercher dans les répertoires pris par défaut par le compilateur (en<br />
général les fichiers dřen-tête livrés avec le compilateur). Si le fichier nřa pas été trouvé, il sera recherché dans le<br />
répertoire <strong>de</strong> travail courant.<br />
Les caractères Ř""ř <strong>de</strong>man<strong>de</strong>nt au préprocesseur <strong>de</strong> rechercher dans le répertoire <strong>de</strong> travail courant. Le programmeur<br />
utilise en général cette notation pour inclure les fichiers ".h" conçus par lui-même.<br />
XIV.2. Comman<strong>de</strong> <strong>de</strong>fine.<br />
Cette comman<strong>de</strong> permet <strong>de</strong> définir <strong>de</strong>s constantes ou <strong>de</strong>s macro-définitions.<br />
Constantes :<br />
Exemple :<br />
#<strong>de</strong>fine PI 3.14159265<br />
Macro-définitions :<br />
On définit ici la constante PI en indiquant sa valeur (sans Ř ;ř ni Ř=ř,…).<br />
Par la suite, à chaque fois que le préprocesseur voit une donnée se nommant PI, il la substitue par sa<br />
valeur (en réalisant une substitution <strong>de</strong> texte).<br />
Exemple :<br />
x = 3 * PI / 4 ;<br />
sera remplacé par :<br />
x = 3 * 3.14159265 / 4 ; (cette ligne sera effectivement lue par le compilateur).<br />
Il est très important <strong>de</strong> ne pas mettre <strong>de</strong> Ř ;ř en fin <strong>de</strong> <strong>de</strong>fine, sinon, le compilateur lirait :<br />
x = 3 * 3.14159265 ; / 4 ;<br />
ce qui provoquerait évi<strong>de</strong>mment une erreur à la compilation sur la ligne :<br />
x = 3 * PI / 4 ;<br />
qui paraît syntaxiquement correcte.<br />
Les macro-définitions permettent <strong>de</strong> réaliser <strong>de</strong>s pseudo-fonctions avec une transmission <strong>de</strong> paramètres<br />
ressemblant à celui utilisé dans les fonctions. Le fonctionnement est cependant totalement différent,<br />
puisque les paramètres seront utilisés pour réaliser <strong>de</strong>s substitutions <strong>de</strong> texte. Ce dispositif sera donc<br />
-29-
LICENCE SPI-EEA LANGAGE C M. <strong>Deloizy</strong><br />
beaucoup plus efficace en terme <strong>de</strong> rapidité dřexécution ; Par contre, la taille du co<strong>de</strong> généré sera plus<br />
importante.<br />
Exemple :<br />
#<strong>de</strong>fine produit(a,b) a*b<br />
On pourra ensuite utiliser la macro-fonction produit <strong>de</strong> la manière suivante :<br />
y = produit(3.0,4) ;<br />
Le premier paramètre (a) sera remplacé par (3.0), et le second (b) par (4). Le compilateur verra donc la<br />
ligne :<br />
y = 3.0*4 ;<br />
On peut utiliser la macro-fonction produit avec <strong>de</strong>s expressions plus compliquées :<br />
y = produit(3+1,4*2) ;<br />
ce qui sera transposé par :<br />
y = 3+1*4*2 ;<br />
qui, compte tenu <strong>de</strong> la priorité <strong>de</strong>s opérateurs, donne comme résultat 11 au lieu <strong>de</strong> 32 attendu.<br />
Pour éviter ce type <strong>de</strong> problème, il est préférable dřencadrer lřexpression et les paramètres par <strong>de</strong>s<br />
parenthèses lors <strong>de</strong> la définition <strong>de</strong> macro-fonctions :<br />
#<strong>de</strong>fine produit(a,b) ((a)*(b))<br />
Ainsi, la substitution <strong>de</strong> texte donnera la ligne suivante :<br />
y = ((3+1)*(4*2)) ;<br />
qui est cette fois correcte.<br />
XIV.3. Compilation conditionnelle<br />
La compilation conditionnelle permet au programmeur dřexclure ou non <strong>de</strong>s lignes <strong>de</strong> programmes selon la valeur ou<br />
lřexistence <strong>de</strong> constantes.<br />
Exemples :<br />
#if test==1<br />
… lignes source C 1<br />
#else<br />
… lignes source C 2<br />
#endif<br />
optionnel<br />
Les lignes « source C 1 » seront compilées si la constante test vaut 1. Sinon, seules les lignes « source C 2 » seront<br />
compilées.<br />
On peut également utiliser à la place <strong>de</strong> la comman<strong>de</strong> if les comman<strong>de</strong>s :<br />
#if<strong>de</strong>f nom_<strong>de</strong>_constante<br />
#ifn<strong>de</strong>f nom_<strong>de</strong>_constante<br />
Ces comman<strong>de</strong>s permettent <strong>de</strong> tester lřexistence ou non dřune constante et <strong>de</strong> compiler ou non la suite.<br />
Exemples :<br />
#ifn<strong>de</strong>f DEJA_COMP<br />
#<strong>de</strong>fine DEJA_COMP<br />
…<br />
#endif<br />
#if __TURBOC__<br />
#inclu<strong>de</strong> <br />
#endif<br />
Permet <strong>de</strong> ne pas compiler plusieurs fois la même section <strong>de</strong><br />
programme (utile lors <strong>de</strong> l’inclusion <strong>de</strong> fichiers).<br />
Détection <strong>de</strong> la "signature" du compilateur afin d’inclure un<br />
fichier d’en-tête non portable.<br />
-30-
LICENCE SPI-EEA TRAVAUX DIRIGÉS M. <strong>Deloizy</strong><br />
TD1 : TYPES DE DONNÉES – CODAGE<br />
I. Caractères.<br />
I.1. Indiquer les co<strong>de</strong>s ASCII <strong>de</strong>s caractères suivants :<br />
'A', 'B', 'q', '','*', '0' (zéro), '8', '\r', '\n', '\t'<br />
I.2. La mémoire contient les données suivantes (hexadécimal) :<br />
adresses<br />
données<br />
2A3C 43 27 65 73 74 20 65 6E<br />
2A44 20 41 53 43 49 49 2E 00<br />
Indiquer pour chaque octet le caractère correspondant.<br />
II. Entiers.<br />
On suppose ici que les poids faibles sont situés en adresse basse.<br />
II.1. Écrire en hexadécimal puis en binaire le contenu <strong>de</strong> la mémoire pour les valeurs suivantes (entiers sur 16 bits) :<br />
1234, 37840, 65535, -128, -1<br />
II.2. Donner les résultats <strong>de</strong>s opérations suivantes :<br />
pour <strong>de</strong>s entiers signés codés sur 16 bits<br />
pour <strong>de</strong>s entiers non signés codés sur 16 bits<br />
pour <strong>de</strong>s entiers signés codés sur 32 bits<br />
1000 - 1024<br />
25000 + 30535<br />
65536 - 1<br />
II.3. Calculer les résultats <strong>de</strong>s opérations suivantes (opérateurs du C) :<br />
Mettre le résultat en binaire, hexadécimal et décimal sur 8 bits.<br />
25 & 51<br />
25 | 51<br />
25 ^ 51<br />
~25<br />
-25<br />
III. Chaînes <strong>de</strong> caractères.<br />
Indiquer le contenu mémoire obtenu avec les chaînes <strong>de</strong> caractères suivantes, selon <strong>de</strong>ux codages possibles (nombre <strong>de</strong><br />
caractères en tête ou zéro terminal) :<br />
"TOTO"<br />
"Il fait chaud\n"<br />
"02 + 20 = 22\n"<br />
IV. Virgule flottante.<br />
Étudier les résultats obtenus avec les nombres en virgule flottante codés sur 64 bits, selon la norme IEEE 754 :<br />
e<br />
x m2<br />
S E' F<br />
b 63 b 62 b 52 b 51 b 0<br />
e : exposant<br />
m : mantisse. 1.0 m < 2.0<br />
S : signe. 1 bit. 0 : positif, 1 : négatif<br />
E' = e+1023. 11 bits. 1 E' 2047<br />
F = m-1. Partie fractionnaire <strong>de</strong> la mantisse. 52 bits.<br />
Représenter le contenu mémoire correspondant aux valeurs 1.0, 2.0 et 5.0.<br />
Quelle est la valeur positive la plus petite possible <br />
Quelle est la valeur positive la plus gran<strong>de</strong> possible <br />
Quel est le nombre <strong>de</strong> chiffres significatifs <br />
V. Tableaux<br />
Soit un tableau d'entiers codés sur 16 bits et contenant les valeurs : { 2, 4, 8, 16, 32 }<br />
Représenter le contenu <strong>de</strong> la mémoire correspondant à ce tableau.<br />
Quel est le nombre d'octets nécessaire au stockage du tableau <br />
-31-
LICENCE SPI-EEA TRAVAUX DIRIGÉS M. <strong>Deloizy</strong><br />
I. Écrire un programme affichant « BONJOUR » à lřécran.<br />
TD2 : PREMIERS PROGRAMMES<br />
II. Écrire un programme qui <strong>de</strong>man<strong>de</strong> le prénom <strong>de</strong> lřutilisateur ainsi que son année <strong>de</strong> naissance. Ensuite, le<br />
programme affichera un texte sous la forme suivante :<br />
Bonjour "xxxxx" (prénom).<br />
Ton année <strong>de</strong> naissance est dddd. (année <strong>de</strong> naissance)<br />
III.a. Écrire un programme qui affiche la table <strong>de</strong> multiplication par 5 sous la forme :<br />
5 x 1 = 5<br />
5 x 2 = 10<br />
5 x 3 = 15<br />
....<br />
5 x 9 = 45<br />
III.b. Modifier le programme précé<strong>de</strong>nt en créant une fonction mult à laquelle on transmet le numéro <strong>de</strong> la table à<br />
afficher :<br />
void mult(int table)<br />
Utiliser cette fonction dans un programme qui <strong>de</strong>man<strong>de</strong> à lřutilisateur le numéro <strong>de</strong> la table quřil souhaite visualiser. Le<br />
programme continuera tant que lřutilisateur entre une valeur strictement positive.<br />
TD3 : UTILISATION DE TABLEAUX.<br />
I. Écrire une fonction qui <strong>de</strong>man<strong>de</strong> à lřutilisateur <strong>de</strong> faire lřacquisition <strong>de</strong> n entiers sous la forme suivante :<br />
Nombre <strong>de</strong> valeurs :<br />
Valeur n° 1 :<br />
Valeur n° 2 :<br />
Valeur n° 3 :<br />
....<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
unsigned AcqTab(int tb[], unsigned NbMax);<br />
La fonction retourne le nombre <strong>de</strong> valeurs saisies<br />
tb est le tableau qui doit être chargé<br />
NbMax est le nombre maximal <strong>de</strong> valeurs que peut contenir tb<br />
II. Écrire une fonction qui compte le nombre <strong>de</strong> valeurs paires dans un tableau. Le prototype <strong>de</strong> cette fonction sera :<br />
int nbpairs(int tab[], unsigned nbval);<br />
nbval indique le nombre d'éléments contenus dans le tableau. Pourquoi ce paramètre est-il indispensable <br />
III. Écrire une fonction qui remplit un tableau avec <strong>de</strong>s nombres ni pairs, ni multiples <strong>de</strong> 3, en commençant par 5. Le<br />
prototype <strong>de</strong> cette fonction sera :<br />
void inittab(int tab[], unsigned nbval);<br />
IV. Écrire une fonction trouvant le minimum et le maximum dans un tableau. Le prototype <strong>de</strong> cette fonction sera :<br />
void minmax(double *tab, unsigned nbval, double *min, double *max);<br />
V. Soient les valeurs suivantes stockées dans un tableau : { 2, -3, 1, 0, 5, 2 }<br />
V.1 Effectuer une rotation à gauche du tableau afin d'obtenir : { -3, 1, 0, 5, 2, 2 }. Afficher le résultat.<br />
V.2. Effectuer une rotation à droite du tableau initial afin d'obtenir : { 2,2,-3, 1, 0, 5 }<br />
-32-
LICENCE SPI-EEA TRAVAUX DIRIGÉS M. <strong>Deloizy</strong><br />
TD4 : CONVERSIONS ASCII / NUMÉRIQUES<br />
I. Écrire une fonction retournant un entier correspondant à la valeur numérique contenue dans une chaîne transmise en<br />
paramètre. Le prototype <strong>de</strong> cette fonction sera :<br />
int AscToInt(const char *<strong>de</strong>cstr);<br />
Cette fonction pourra être utilisée par exemple <strong>de</strong> la manière suivante :<br />
...<br />
x = AscToInt("26789");<br />
...<br />
Dans ce cas, x prendra la valeur numérique 26789.<br />
On rappelle qu'un nombre abc peut s'écrire : a<br />
10<br />
<br />
b10<br />
c<br />
II. Écrire une fonction équivalente à la précé<strong>de</strong>nte permettant <strong>de</strong> convertir un nombre écrit en binaire, dont le prototype<br />
sera :<br />
int AscBinToInt(const char *binstr);<br />
III. Faire <strong>de</strong> même pour un nombre écrit en hexadécimal.<br />
int AscHexToInt(const char *hexstr);<br />
IV. Que se passe-t-il si un caractère non prévu est contenu dans la chaîne Proposer un moyen <strong>de</strong> remédier à ce<br />
problème.<br />
TD5 : TRAITEMENTS SUR LES CHAÎNES<br />
I. Écrire une fonction comptant le nombre <strong>de</strong> caractères contenus dans une chaîne. Le prototype <strong>de</strong> cette fonction sera :<br />
int strlen(const char *str);<br />
II.a. Écrire une fonction comptant le nombre <strong>de</strong> caractères i<strong>de</strong>ntiques x contenus dans une chaîne. Le prototype <strong>de</strong> cette<br />
fonction sera :<br />
int nbcar(char x, const char *str); /* recherche x dans str */<br />
II.b. Modifier la fonction précé<strong>de</strong>nte pour qu'elle ne différencie pas les minuscules et majuscules.<br />
III. Écrire une fonction permettant <strong>de</strong> comparer <strong>de</strong>ux chaînes <strong>de</strong> caractères. Le prototype <strong>de</strong> cette fonction sera :<br />
int cmpstr(const char *str1, const char *str2);<br />
L'entier retourné sera positif si str2 est situé après str1 dans un classement alphabétique et 0 si les chaînes sont<br />
i<strong>de</strong>ntiques.<br />
IV. Écrire une fonction comptant le nombre <strong>de</strong> mots dans une phrase. Le prototype <strong>de</strong> cette fonction sera :<br />
int nbmots(const char *str);<br />
Par exemple, si str contient " le petit train passe dans l'alpage…\n " la fonction doit retourner la valeur 7.<br />
TD6 : FICHIERS<br />
I. Écrire un programme affichant à l'écran les fichiers textes dont les noms seront transmis sur la ligne <strong>de</strong> comman<strong>de</strong><br />
lors <strong>de</strong> l'appel du programme.<br />
II. Écrire un programme affichant le contenu d'un fichier quelconque en hexadécimal et en ASCII, sous la forme<br />
suivante :<br />
0000 4D 5A 78 00 BC 00 00 00 A0 04 01 00 FF FF 00 00 MZx.............<br />
0010 00 00 00 00 00 01 00 00 1E 00 00 00 01 00 00 00 ................<br />
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0040 F6 38 F6 38 46 52 41 01 00 52 03 4E 53 43 4F 00 .8.8FRA..R.NSCO.<br />
0050 03 06 00 16 00 1A 00 01 04 FF FF 48 03 02 00 56 ...........H...V<br />
0060 03 03 00 66 03 08 00 7D 03 02 01 FF FF 8C 03 03 ...f............<br />
0070 CC EA 03 9A 03 EB 03 D2 03 EC 03 FC 03 ED 03 14 ................<br />
0080 04 EE 03 33 04 EF 03 69 04 F0 03 8A 04 F1 03 AE ...3...i........<br />
0090 04 F2 03 C9 04 F3 03 00 05 F4 03 23 05 F5 03 57 ...........#...W<br />
00A0 05 F6 03 7A 05 F7 03 84 05 F8 03 B1 05 F9 03 DE ...z............<br />
00B0 05 FA 03 02 06 FB 03 17 06 FC 03 26 06 FD 03 35 ...........&...5<br />
III. Statistiques sur un fichier<br />
III.1. Écrire un programme qui compte les mots contenus dans un fichier texte.<br />
III.2. (optionnel) Modifier le programme pour indiquer (dans l'ordre <strong>de</strong> la fréquence d'apparition) les mots présents dans<br />
le fichier.<br />
-33-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP1 : DÉCLARATIONS, PREMIERS PROGRAMMES, DÉBOGAGE<br />
I. Écrire un programme affichant "Bonjour".<br />
II. Soit le programme suivant :<br />
#inclu<strong>de</strong> <br />
/* Affichage <strong>de</strong> la table <strong>de</strong> multiplication par m */<br />
void mtable(int m, int nmax)<br />
{<br />
int i;<br />
for(i=1; i
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP2 : MANIPULATIONS DE CHAÎNES DE CARACTÈRES<br />
I. Saisie <strong>de</strong> chaînes<br />
Définir un tableau <strong>de</strong> 80 caractères.<br />
Faire la saisie d'une chaîne <strong>de</strong> caractères (limitée à 20 caractères) en utilisant :<br />
la fonction scanf<br />
la fonction gets<br />
la fonction fgets<br />
Dans chaque cas,<br />
Afficher normalement la chaîne saisie (en utilisant printf)<br />
Afficher en hexadécimal le co<strong>de</strong> ASCII <strong>de</strong>s 80 octets du tableau. (On pourra concevoir une fonction qui<br />
affiche en hexadécimal le contenu d'un tableau <strong>de</strong> caractères)<br />
Y a-t-il <strong>de</strong>s caractères indésirables dans la chaîne saisie <br />
Que se passe-t-il si l'utilisateur entre plus <strong>de</strong> 20 caractères Comment remédier à ce problème <br />
Écrire une fonction qui "nettoie" une chaîne saisie par fgets (en enlevant le caractère '\n' résiduel).<br />
II. Traitements sur les chaînes<br />
II.1. Écrire une fonction qui compte le nombre <strong>de</strong> voyelles contenues dans une chaîne (sans distinction <strong>de</strong>s minuscules<br />
et majuscules).<br />
II.2. Écrire une fonction qui renverse une chaîne ("Toto" <strong>de</strong>vient "otoT").<br />
II.3. Écrire une fonction qui duplique chaque caractère d'une chaîne ("Toto" <strong>de</strong>vient "TToottoo").<br />
II.4. Écrire une fonction qui compte le nombre <strong>de</strong> mots contenus dans une chaîne.<br />
-35-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP3 : TABLEAUX DE DONNÉES<br />
I. Acquisition <strong>de</strong> données<br />
I.1. Déclarer un tableau <strong>de</strong> 40 entiers<br />
Écrire une fonction permettant <strong>de</strong> saisir au clavier les nb premiers éléments du tableau (0 nb < 40).<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
void AcqTab(int *tab, unsigned nb);<br />
I.2. Écrire une fonction affichant à l'écran les n premiers nombres d'un tableau, en mettant nbl valeurs par ligne.<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
void AffTab(int *tab, unsigned n, unsigned nbl);<br />
II. Nombres aléatoires<br />
II.1. Écrire une fonction qui remplit un tableau avec n valeurs aléatoires. On utilisera la fonction rand(), définie dans<br />
stdlib.h. Afficher les résultats obtenus.<br />
Exécuter plusieurs fois le programme. Conclure.<br />
II.2. 2 Initialiser le générateur <strong>de</strong> nombres aléatoires en utilisant la fonction srand() (voir prototype). L'initialisation sera<br />
réalisée à l'ai<strong>de</strong> <strong>de</strong> la fonction time() (définie dans time.h).<br />
Observer <strong>de</strong> nouveau les résultats obtenus.<br />
II.3. Écrire une nouvelle fonction qui effectue un tirage <strong>de</strong> 6 valeurs aléatoires distinctes, et comprises entre 1 et 49.<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
unsigned *Loto(void);<br />
Cette fonction retourne un pointeur sur le tableau contenant les 6 valeurs du tirage.<br />
III. Tris<br />
III.1. Constituer un tableau <strong>de</strong> N valeurs aléatoires.<br />
Classer en ordre croissant ce tableau en utilisant l'algorithme <strong>de</strong> votre choix.<br />
III.2. Définir un tableau <strong>de</strong> chaînes <strong>de</strong> caractères.<br />
Classer en ordre croissant, puis en ordre décroissant ce tableau en utilisant la fonction qsort.<br />
2 Exercice optionnel<br />
-36-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP4 : FICHIERS<br />
I. Lecture d'un fichier texte<br />
Éditer (avec un éditeur <strong>de</strong> textes) un texte quelconque <strong>de</strong> quelques lignes.<br />
Enregistrer ce fichier sur le disque.<br />
Créer un programme qui lit ce fichier et affiche son contenu.<br />
Le programme affichera finalement le nombre <strong>de</strong> lignes et <strong>de</strong> caractères composant le fichier.<br />
II. Écriture d'un fichier texte<br />
Écrire un programme qui <strong>de</strong>man<strong>de</strong> à l'utilisateur son nom, prénom, poids, age et sexe (cf. TP1) et sauvergar<strong>de</strong> ces<br />
informations sur le disque dans un fichier texte.<br />
Le nom du fichier sera composé du nom <strong>de</strong> l'individu, suivi d'un nombre <strong>de</strong> 3 chiffres. Ce nombre est incrémenté<br />
automatiquement si nécessaire, afin <strong>de</strong> ne pas effacer un fichier éventuellement existant :<br />
Par exemple, pour Dupont, lors <strong>de</strong> la 1 ère sauvegar<strong>de</strong> on écrit dans "Dupont000.dat".<br />
Lors <strong>de</strong> la 2 ème sauvegar<strong>de</strong>, le fichier créé serait : "Dupont001.dat", etc …<br />
III. Lecture / Écriture d'un fichier texte<br />
Écrire un programme qui lit un fichier texte, renverse les lignes et écrit le résultat dans un nouveau fichier.<br />
Si le fichier à lire contient à l'origine :<br />
Bonjour<br />
Il fait beau<br />
On doit obtenir dans le nouveau fichier :<br />
ruojnoB<br />
uaeb tiaf lI<br />
-37-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP5 : STRUCTURES<br />
I. Définition d'une structure<br />
Définir la structure T_Quot <strong>de</strong> la manière suivante :<br />
type<strong>de</strong>f struct {<br />
int num ;<br />
int <strong>de</strong>n ;<br />
} T_Quot ;<br />
Cette structure permet <strong>de</strong> manipuler <strong>de</strong>s nombres rationnels en indiquant par la valeur du numérateur et la valeur du<br />
dénominateur.<br />
II. Encombrement mémoire<br />
Observer (avec l'opérateur sizeof) l'encombrement mémoire <strong>de</strong> cette structure.<br />
III. Tableau <strong>de</strong> structures<br />
Définir un tableau permettant <strong>de</strong> mémoriser 1000 structures, en initialisant les <strong>de</strong>ux premières structures avec les<br />
valeurs 16/9 et 4/3.<br />
Indiquer l'encombrement mémoire <strong>de</strong> ce tableau.<br />
IV. Acquisition et affichage <strong>de</strong>s champs<br />
Écrire une fonction permettant d'acquérir au clavier une structure T_Quot.<br />
Cette fonction posera les questions suivantes :<br />
Entrer le numérateur :<br />
Entrer le dénominateur :<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
void AcqQuot(T_Quot *q);<br />
Écrire une fonction qui affiche la valeur <strong>de</strong> la structure sous la forme : nnn / ddd (Ex : 16/9)<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
void AffQuot(T_Quot *q);<br />
Écrire une fonction qui affiche la valeur numérique <strong>de</strong> la structure sous la forme : xxx.xxx (Ex. : 1.778)<br />
Le prototype <strong>de</strong> cette fonction sera :<br />
void AffValQuot(T_Quot *q);<br />
V. Fonctions <strong>de</strong> manipulation associées :<br />
Écrire les fonctions suivantes :<br />
Multiplication <strong>de</strong> 2 rationnels :<br />
T_Quot *MulQuot(T_Quot *q1, T_Quot *q2) ;<br />
Multiplie (*q1) et (*q2). Range le résultat dans une mémoire interne à la fonction dont lřadresse est renvoyée.<br />
Addition <strong>de</strong> 2 rationnels :<br />
T_Quot *AddQuot(T_Quot *q1, T_Quot *q2) ;<br />
Ajoute (*q1) et (*q2). Range le résultat dans une mémoire interne à la fonction dont lřadresse est renvoyée.<br />
<br />
3 Simplification <strong>de</strong> rationnels :<br />
void SimplQuot(T_Quot *q) ;<br />
Simplifie la fraction contenue dans (*q). Range le résultat dans (*q).<br />
On utilisera un algorithme <strong>de</strong> recherche du pgcd :<br />
Algorithme d’Eucli<strong>de</strong><br />
ENTREE : Deux entiers a et b. - SORTIE : Leur plus grand diviseur commun, pgcd(a,b).<br />
1. Faire tant que le reste est non nul :<br />
Division entière avec reste <strong>de</strong> a et b : a = q · b + r<br />
a ← b; b ← r<br />
2. Retourner b, qui est alors le plus grand diviseur commun.<br />
Exemple : Calcul du pgdc <strong>de</strong> 2926 et 30030. On obtient le tableau suivant.<br />
a b q r<br />
2926 30030 0 2926<br />
30030 2926 10 770<br />
2926 770 3 616<br />
770 616 1 154<br />
616 154 4 0<br />
Le resultat est donc : pgdc(30030, 2926) = 154.<br />
3 Exercice optionnel<br />
-38-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP6 : ÉTUDE DE FONCTIONS MATHÉMATIQUES<br />
I. Définition <strong>de</strong> fonctions mathématiques<br />
Écrire les fonctions (informatiques) permettant <strong>de</strong> calculer les fonctions mathématiques suivantes :<br />
f ( x)<br />
<br />
1<br />
10<br />
<br />
i0<br />
<br />
sin (2 i<br />
1)<br />
x<br />
2 i<br />
1<br />
<br />
sin( x)<br />
f<br />
2<br />
( x)<br />
f3(<br />
x)<br />
sin(10<br />
x)<br />
exp(<br />
x)<br />
x<br />
Constituer un tableau <strong>de</strong> pointeurs <strong>de</strong> fonctions, permettant d'accé<strong>de</strong>r par la suite aux fonctions préalablement définies.<br />
II. Calcul <strong>de</strong>s fonctions<br />
Écrire un programme qui <strong>de</strong>man<strong>de</strong> à l'utilisateur :<br />
le numéro <strong>de</strong> la fonction qu'il souhaite étudier (1, 2 ou 3)<br />
la valeur minimale <strong>de</strong> l'abscisse (Xmin)<br />
la valeur maximale <strong>de</strong> l'abscisse (Xmax)<br />
le nombre <strong>de</strong> points à utiliser pour l'étu<strong>de</strong> (nbp)<br />
Le programme <strong>de</strong>vra créer <strong>de</strong> manière dynamique un tableau permettant <strong>de</strong> ranger les nbp points calculés (les<br />
ordonnées) <strong>de</strong> la fonction (utiliser malloc(), définie dans stdlib.h)<br />
On cherchera ensuite dans ce tableau les valeurs minimale et maximale <strong>de</strong> la fonction. Ces informations seront affichées<br />
à l'écran.<br />
Remarque : On n'oubliera pas <strong>de</strong> libérer l'espace mémoire alloué dynamiquement dès que les données ne sont plus<br />
nécessaires (utilisation <strong>de</strong> free()).<br />
III. Traitement <strong>de</strong>s exceptions.<br />
Dans certains cas, la fonction mathématique peut déclencher une erreur (par exemple une division par 0). Prévoir la<br />
résolution du problème en utilisant la fonction signal(), définie dans signal.h. Cette fonction permet l'appel d'une<br />
fonction <strong>de</strong> gestion d'erreur dès qu'un "signal" est capté. Dans notre cas, on utilisera le signal SIGFPE (Floating Point<br />
Exception).<br />
IV. Écriture <strong>de</strong>s résultats dans un fichier<br />
Écrire une fonction permettant <strong>de</strong> ranger les couples (abscisses, ordonnées) dans un fichier texte. Chaque ligne du<br />
fichier qui contiendra les valeurs <strong>de</strong> l'abscisse et <strong>de</strong> l'ordonnée, séparées par un caractère ';'.<br />
Ce fichier pourra être récupéré par un autre programme, comme un tableur (type Excel) et ceci permettra ainsi <strong>de</strong><br />
manière simple <strong>de</strong> réaliser le tracé <strong>de</strong> la fonction 4 .<br />
V. Écriture d'une fonction <strong>de</strong> gestion d'erreur<br />
Le programme écrit peut provoquer <strong>de</strong>s erreurs. Écrire une fonction permettant <strong>de</strong> mettre fin au programme (utiliser la<br />
fonction exit()), en affichant un message d'erreur explicite.<br />
Cette fonction aura le prototype suivant (et utilisera vprintf()) :<br />
void ErrPrintf(const char *format, ...);<br />
On pourra ainsi appeler cette fonction <strong>de</strong> la manière suivante :<br />
ErrPrintf("Xmax [%G] doit être supérieur à Xmin [%G].",Xmax,Xmin);<br />
ou bien :<br />
ErrPrintf("Le fichier '%s' ne peut être ouvert",nom_fichier);<br />
etc.…<br />
4 Exercice facultatif.<br />
-39-
LICENCE SPI-EEA TRAVAUX PRATIQUES M. <strong>Deloizy</strong><br />
TP7 : ACQUISITION ET TRAITEMENT DE DONNÉES<br />
I. Signal analogique<br />
I.1 Échantillonner un signal analogique avec les cartes d'entrées-sorties.<br />
On prendra :<br />
F E = 1KHz<br />
Nombre d'échantillons = 1024<br />
I.2. Déterminer numériquement :<br />
Les valeurs extrêmes du signal (en volts)<br />
La valeur et l'instant <strong>de</strong> la plus forte pente<br />
II. Filtre numérique.<br />
On met en œuvre un filtre dont l'équation <strong>de</strong> récurrence s'écrit :<br />
ek<br />
1<br />
yk<br />
yk<br />
1<br />
yk<br />
<br />
N<br />
U<br />
filtre<br />
Y<br />
Déterminer expérimentalement la nature du filtre.<br />
La fréquence d'échantillonnage est égale à 1 kHz.<br />
Quels sont le gain et la fréquence <strong>de</strong> coupure pour N = 1 et N = 16<br />
-40-
LICENCE SPI-EEA TABLES DE CODAGE DES CARACTÈRES M. <strong>Deloizy</strong><br />
ASCII :<br />
EBCDIC :<br />
Windows-1252 (CP1252)<br />
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF<br />
0x NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI<br />
1x DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US<br />
2x SP ! " # $ % & ' ( ) * + , - . /<br />
3x 0 1 2 3 4 5 6 7 8 9 : ; < = > <br />
4x @ A B C D E F G H I J K L M N O<br />
5x P Q R S T U V W X Y Z [ \ ] ^ _<br />
6x ` a b c d e f g h i j k l m n o<br />
7x p q r s t u v w x y z { | } ~ DEL<br />
8x € ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ţ<br />
9x Ř ř Ŗ ŗ • Ŕ ŕ ˜ š › œ ţ Ÿ<br />
Ax NBSP ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯<br />
Bx ° ± ² ³ ´ µ · ¸ ¹ º » ¼ ½ ¾ ¿<br />
Cx À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï<br />
Dx Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß<br />
Ex à á â ã ä å æ ç è é ê ë ì í î ï<br />
Fx ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ<br />
-41-
LICENCE SPI-EEA PROTOTYPES (CSTDLIB) M. <strong>Deloizy</strong><br />
<br />
void assert(int expression);<br />
<br />
int isalnum(int c);<br />
int isalpha(int c);<br />
int iscntrl(int c);<br />
int isdigit(int c);<br />
int isgraph(int c);<br />
int islower(int c);<br />
int isprint(int c);<br />
int ispunct(int c);<br />
int isspace(int c);<br />
int isupper(int c);<br />
int isxdigit(int c);<br />
int tolower(int c);<br />
int toupper(int c);<br />
<br />
errno<br />
EDOM<br />
ERANGE<br />
<br />
FLT_RADIX<br />
FLT_ROUNDS<br />
FLT_DIG<br />
DBL_DIG<br />
LDBL_DIG<br />
FLT_EPSILON<br />
DBL_EPSILON<br />
LDBL_EPSILON<br />
FLT_MANT_DIG<br />
DBL_MANT_DIG<br />
LDBL_MANT_DIG<br />
FLT_MAX<br />
DBL_MAX<br />
LDBL_MAX<br />
FLT_MAX_EXP<br />
DBL_MAX_EXP<br />
LDBL_MAX_EXP<br />
FLT_MIN<br />
DBL_MIN<br />
LDBL_MIN<br />
FLT_MIN_EXP<br />
DBL_MIN_EXP<br />
LDBL_MIN_EXP<br />
BIBLIOTHÈQUES (CSTDLIB)<br />
<br />
CHAR_BIT<br />
CHAR_MAX<br />
CHAR_MIN<br />
SCHAR_MAX<br />
SCHAR_MIN<br />
UCHAR_MAX<br />
SHRT_MAX<br />
SHRT_MIN<br />
USHRT_MAX<br />
INT_MAX<br />
INT_MIN<br />
-42-
LICENCE SPI-EEA PROTOTYPES (CSTDLIB) M. <strong>Deloizy</strong><br />
UINT_MAX<br />
LONG_MAX<br />
LONG_MIN<br />
ULONG_MAX<br />
<br />
struct lconv<br />
struct lconv* localeconv(void);<br />
char* setlocale(int category, const char* locale);<br />
LC_ALL<br />
LC_NUMERIC<br />
LC_MONETARY<br />
LC_COLLATE<br />
LC_CTYPE<br />
LC_TIME<br />
NULL<br />
<br />
HUGE_VAL<br />
double exp(double x);<br />
double log(double x);<br />
double log10(double x);<br />
double pow(double x, double y);<br />
double sqrt(double x);<br />
double ceil(double x);<br />
double floor(double x);<br />
double fabs(double x);<br />
double l<strong>de</strong>xp(double x, int n);<br />
double frexp(double x, int* exp);<br />
double modf(double x, double* ip);<br />
double fmod(double x, double y);<br />
double sin(double x);<br />
double cos(double x);<br />
double tan(double x);<br />
double asin(double x);<br />
double acos(double x);<br />
double atan(double x);<br />
double atan2(double y, double x);<br />
double sinh(double x);<br />
double cosh(double x);<br />
double tanh(double x);<br />
<br />
jmp_buf<br />
int setjmp(jmp_buf env);<br />
void longjmp(jmp_buf env, int val);<br />
<br />
SIGABRT<br />
SIGFPE<br />
SIGILL<br />
SIGINT<br />
SIGSEGV<br />
SIGTERM<br />
SIG_DFL<br />
SIG_ERR<br />
SIG_IGN<br />
void (*signal(int sig, void (*handler)(int)))(int);<br />
int raise(int sig);<br />
-43-
LICENCE SPI-EEA PROTOTYPES (CSTDLIB) M. <strong>Deloizy</strong><br />
<br />
va_list<br />
void va_start(va_list ap, lastarg);<br />
type va_arg(va_list ap, type);<br />
void va_end(va_list ap);<br />
<br />
NULL<br />
offsetof(stype, m)<br />
ptrdiff_t<br />
size_t<br />
<br />
BUFSIZ<br />
EOF<br />
FILENAME_MAX<br />
FOPEN_MAX<br />
L_tmpnam<br />
NULL<br />
SEEK_CUR<br />
SEEK_END<br />
SEEK_SET<br />
TMP_MAX<br />
_IOFBF<br />
_IOLBF<br />
_IONBF<br />
stdin<br />
stdout<br />
st<strong>de</strong>rr<br />
FILE<br />
fpos_t<br />
size_t<br />
FILE* fopen(const char* filename, const char* mo<strong>de</strong>);<br />
FILE* freopen(const char* filename, const char* mo<strong>de</strong>, FILE* stream);<br />
int fflush(FILE* stream);<br />
int fclose(FILE* stream);<br />
int remove(const char* filename);<br />
int rename(const char* oldname, const char* newname);<br />
FILE* tmpfile();<br />
char* tmpnam(char s[L_tmpnam]);<br />
int setvbuf(FILE* stream, char* buf, int mo<strong>de</strong>, size_t size);<br />
void setbuf(FILE* stream, char* buf);<br />
int fprintf(FILE* stream, const char* format, ...);<br />
int printf(const char* format, ...);<br />
int sprintf(char* s, const char* format, ...);<br />
int vfprintf(FILE* stream, const char* format, va_list arg);<br />
int vprintf(const char* format, va_list arg);<br />
int vsprintf(char* s, const char* format, va_list arg);<br />
int fscanf(FILE* stream, const char* format, ...);<br />
int scanf(const char* format, ...);<br />
int sscanf(char* s, const char* format, ...);<br />
int fgetc(FILE* stream);<br />
char* fgets(char* s, int n, FILE* stream);<br />
int fputc(int c, FILE* stream);<br />
char* fputs(const char* s, FILE* stream);<br />
int getc(FILE* stream);<br />
int getchar(void);<br />
char* gets(char* s);<br />
int putc(int c, FILE* stream);<br />
int putchar(int c);<br />
int puts(const char* s);<br />
int ungetc(int c, FILE* stream);<br />
size_t fread(void* ptr, size_t size, size_t nobj, FILE* stream);<br />
-44-
LICENCE SPI-EEA PROTOTYPES (CSTDLIB) M. <strong>Deloizy</strong><br />
size_t fwrite(const void* ptr, size_t size, size_t nobj, FILE* stream);<br />
int fseek(FILE* stream, long offset, int origin);<br />
long ftell(FILE* stream);<br />
void rewind(FILE* stream);<br />
int fgetpos(FILE* stream, fpos_t* ptr);<br />
int fsetpos(FILE* stream, const fpos_t* ptr);<br />
void clearerr(FILE* stream);<br />
int feof(FILE* stream);<br />
int ferror(FILE* stream);<br />
void perror(const char* s);<br />
<br />
EXIT_FAILURE<br />
EXIT_SUCCESS<br />
RAND_MAX<br />
NULL<br />
div_t<br />
ldiv_t<br />
size_t<br />
int abs(int n);<br />
long labs(long n);<br />
div_t div(int num, int <strong>de</strong>nom);<br />
ldiv_t ldiv(long num, long <strong>de</strong>nom);<br />
double atof(const char* s);<br />
int atoi(const char* s);<br />
long atol(const char* s);<br />
double strtod(const char* s, char** endp);<br />
long strtol(const char* s, char** endp, int base);<br />
unsigned long strtoul(const char* s, char** endp, int base);<br />
void* calloc(size_t nobj, size_t size);<br />
void* malloc(size_t size);<br />
void* realloc(void* p, size_t size);<br />
void free(void* p);<br />
void abort();<br />
void exit(int status);<br />
int atexit(void (*fcm)(void));<br />
int system(const char* s);<br />
char* getenv(const char* name);<br />
void* bsearch(const void* key, const void* base, size_t n, size_t size, int<br />
(*cmp)(const void* keyval, const void* datum));<br />
void qsort(void* base, size_t n, size_t size, int (*cmp)(const void*, const<br />
void*));<br />
int rand(void);<br />
void srand(unsigned int seed);<br />
<br />
NULL<br />
size_t<br />
char* strcpy(char* s, const char* ct);<br />
char* strncpy(char* s, const char* ct, size_t n);<br />
char* strcat(char* s, const char* ct);<br />
char* strncat(char* s, const char* ct, size_t n);<br />
int strcmp(const char* cs, const char* ct);<br />
int strncmp(const char* cs, const char* ct, size_t n);<br />
int strcoll(const char* cs, const char* ct);<br />
char* strchr(const char* cs, int c);<br />
char* strrchr(const char* cs, int c);<br />
size_t strspn(const char* cs, const char* ct);<br />
size_t strcspn(const char* cs, const char* ct);<br />
char* strpbrk(const char* cs, const char* ct);<br />
char* strstr(const char* cs, const char* ct);<br />
size_t strlen(const char* cs);<br />
char* strerror(int n);<br />
char* strtok(char* s, const char* t);<br />
-45-
LICENCE SPI-EEA PROTOTYPES (CSTDLIB) M. <strong>Deloizy</strong><br />
size_t strxfrm(char* s, const char* ct, size_t n);<br />
void* memcpy(void* s, const void* ct, size_t n);<br />
void* memmove(void* s, const void* ct, size_t n);<br />
int memcmp(const void* cs, const void* ct, size_t n);<br />
void* memchr(const void* cs, int c, size_t n);<br />
void* memset(void* s, int c, size_t n);<br />
<br />
CLOCKS_PER_SEC<br />
NULL<br />
clock_t<br />
time_t<br />
struct tm<br />
clock_t clock(void);<br />
time_t time(time_t* tp);<br />
double difftime(time_t time2, time_t time1);<br />
time_t mktime(struct tm* tp);<br />
char* asctime(const struct tm* tp);<br />
char* ctime(const time_t* tp);<br />
struct tm* gmtime(const time_t* tp);<br />
struct tm* localtime(const time_t* tp);<br />
size_t strftime(char* s, size_t smax, const char* fmt, const struct tm* tp);<br />
-46-
LICENCE SPI-EEA MÉMENTO M. <strong>Deloizy</strong><br />
MÉMENTO DU LANGAGE C<br />
D’après : http://www.inln.cnrs.fr/IMG/pdf/memento-2.pdf<br />
Structure <strong>de</strong> base<br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
int main()<br />
{<br />
// Programme...<br />
return 0 ;<br />
}<br />
inclusion <strong>de</strong>s en-têtes <strong>de</strong> librairie<br />
début <strong>de</strong> la fonction principale<br />
retour <strong>de</strong> la fonction principale système dřexploitation<br />
Variables et constantes<br />
int i=165;<br />
Nombre entier<br />
long j=8219829; short k=1; Nombres entiers long et courts<br />
char c=’z’;<br />
Caractère (1 octet en général).<br />
float x=3.162e0 ;<br />
Flottant codé souvent sur 4 octets (32 bits)<br />
double y=3.1415926535e0 ; Flottant codé souvent sur 8 octets<br />
double tab[10] ; Tableau <strong>de</strong> dix double. Indices 0 à 9.<br />
char nom[30] = "fichier" ; Chaîne <strong>de</strong> caractères (tableau <strong>de</strong> char)<br />
const int N=10 ;<br />
Constante<br />
#<strong>de</strong>fine N 10<br />
ŖConstanteŗ (en fait substitution)<br />
Entrées et sorties<br />
Entrées/sorties standards :<br />
float x;<br />
scanf("%f", &x); lecture <strong>de</strong> x au clavier<br />
printf("Le resultat est : %f \n", x); écriture <strong>de</strong> x à lřécran<br />
Les indicatifs suivants sont utilisés pour les différents types <strong>de</strong> données.<br />
%f float %lf double %s char[], chaîne<br />
%d int %c char %x entier en hexadécimal, adresse<br />
On peut également entrer %15.10lf pour avoir un double affiché sur 15 cases avec 10 chiffres après la virgule.<br />
Fichiers :<br />
FILE *masortie, *monentree ;<br />
pointeurs sur <strong>de</strong>s fichiers<br />
monentree = fopen("entree.txt","r") ; ouverture en lecture du fichier entree.txt<br />
masortie = fopen("sortie.txt","w") ; ouverture en écriture du fichier sortie.txt<br />
fscanf(monentree,"%f",&x);<br />
lecture <strong>de</strong> la variable x dans le fichier entree.txt<br />
fprintf(masortie,"%f\n",x);<br />
écriture dans le fichier sortie.txt<br />
close(monentree) ; close(masortie) ; fermeture <strong>de</strong>s fichiers<br />
Tests, choix, boucles<br />
La structure <strong>de</strong> contrôle if-else if-else<br />
if (x == y && a != b )<br />
{ à faire si x = y ET a b<br />
}<br />
else if (x > y || a y OU a ≤ b<br />
}<br />
else<br />
{ à faire si les <strong>de</strong>ux premières propositions sont fausses<br />
}<br />
-47-
LICENCE SPI-EEA MÉMENTO M. <strong>Deloizy</strong><br />
La boucle for<br />
for(i=0;i 0.001)<br />
{ action à répéter tant que > 10 −3<br />
}<br />
La boucle do-while<br />
do<br />
{ action à répéter tant que > 10 −3<br />
} while(Delta > 0.001) ;<br />
Dans la boucle while, le test sřeffectue une première fois avant <strong>de</strong> commencer la boucle. Dans la boucle do-while, le<br />
test sřeffectue après la boucle et la boucle sera donc faite au moins une fois.<br />
Fonctions<br />
Fonction retournant une valeur<br />
int f1(float x, char c) fonction prenant un flottant et un char et retournant un entier<br />
{ texte <strong>de</strong> la fonction<br />
· · ·<br />
return 1 ; retourne un entier à la fin<br />
}<br />
Fonction ne retournant rien<br />
Une fonction <strong>de</strong> type void ne retourne pas <strong>de</strong> valeur.<br />
void f2(float x[]) fonction prenant un tableau <strong>de</strong> flottants et ne retournant rien<br />
{ texte <strong>de</strong> la fonction<br />
pas <strong>de</strong> retour à la fin ou return seul. (return ;)<br />
}<br />
Déclaration d’une fonction et utilisation<br />
On déclare une fonction pour lřutiliser dans une autre :<br />
int f1(float, char) ;<br />
void f2(float[]) ;<br />
On lřutilise avec <strong>de</strong>s variables ou <strong>de</strong>s constantes comme paramètres :<br />
i = f1(y,c);<br />
j = f1(10.0,’y’);<br />
f2(tab) ;<br />
Pointeurs et allocation <strong>de</strong> mémoire<br />
Pointeurs<br />
float *pf ; un pointeur sur float (variable contenant une adresse mémoire)<br />
float x=3 ; un float égal à 3<br />
pf = &x ; le pointeur <strong>de</strong>vient égal à lřadresse <strong>de</strong> x<br />
*pf = 4 ; la valeur stockée à cette adresse est modifiée<br />
Allocation <strong>de</strong> mémoire<br />
On peut réserver <strong>de</strong> lřespace en mémoire après le démarrage du programme grâce à la fonction malloc qui retourne un<br />
pointeur sans type particulier.<br />
pf = (float*) malloc(10*sizeof(float));<br />
malloc réserve 10 cases en mémoire pouvant chacune contenir un flottant. Elle renvoie lřadresse <strong>de</strong> la première case<br />
mémoire. On transforme cette adresse en type float*, puis on la stocke dans pf.<br />
On accè<strong>de</strong> au contenu <strong>de</strong> la case mémoire 5 <strong>de</strong> différentes manières<br />
x = pf[5] ; ou bien x = *(pf+5) ;<br />
On libère la mémoire à lřai<strong>de</strong> <strong>de</strong> la comman<strong>de</strong> free<br />
free(pf) ;<br />
-48-
LICENCE SPI-EEA MÉMENTO M. <strong>Deloizy</strong><br />
Pointeur <strong>de</strong> fonction<br />
double (*pfonc)(double) ; Pointeur <strong>de</strong> fonction pouvant pointer vers une fonction qui prend un double en<br />
paramètre et retourne un double.<br />
pfonc = cos ; Le pointeur pointe sur cosinus<br />
x = pfonc(3.14) ; il remplace cosinus<br />
Structures et définition <strong>de</strong> type<br />
On peut définir un type comp (nombres complexes) <strong>de</strong> la manière suivante :<br />
type<strong>de</strong>f struct<br />
{ double re ;<br />
double im;<br />
} comp ;<br />
On lřutilise<br />
comp z1 ;<br />
z1.re = 1.0 ; z1.im = 2.0 ;<br />
En vrac...<br />
On dispose <strong>de</strong>s opérateurs arithmétiques : +, -, *, / et %. Ce <strong>de</strong>rnier donne le reste dans une division entière.<br />
Lřopérateur ^ correspond au OU exclusif (opération bit à bit)<br />
On dispose <strong>de</strong>s raccourcis i++ pour i=i+1, x+=3.5 pour x = x + 3.5 .<br />
De même on a les raccourcis : i--, x*=2, x/=1.5...<br />
Lřopérateur (float) convertit en flottant, (int) en entier...<br />
Des constantes mathématiques sont définies avec une gran<strong>de</strong> précision dans math.h. Notamment π sous le nom<br />
<strong>de</strong> M_PI.<br />
-49-
LICENCE SPI-EEA TABLE DES MATIÈRES M. <strong>Deloizy</strong><br />
Table <strong>de</strong>s Matières<br />
Introduction .................................................................................................................................................................. 2<br />
Description du langage ................................................................................................................................................. 2<br />
I. Constitution dřun programme C ......................................................................................................................... 2<br />
I.1. Généralités .................................................................................................................................................. 2<br />
I.2. Syntaxe ....................................................................................................................................................... 2<br />
I.2.a. Commentaires. ................................................................................................................................. 2<br />
I.2.b. Noms <strong>de</strong> symboles. .......................................................................................................................... 2<br />
I.2.c. Minuscules et majuscules. ............................................................................................................... 2<br />
I.3. Mots clés ..................................................................................................................................................... 3<br />
II. Types <strong>de</strong> variables ............................................................................................................................................. 3<br />
II.1. Les types <strong>de</strong> base ....................................................................................................................................... 3<br />
II.1.a. char : ................................................................................................................................................ 3<br />
II.1.b. int : .................................................................................................................................................. 3<br />
II.1.c. float : ............................................................................................................................................... 3<br />
II.2. Les types dérivés ....................................................................................................................................... 3<br />
II.2.a. unsigned char : ................................................................................................................................ 3<br />
II.2.b. signed char : .................................................................................................................................... 3<br />
II.2.c. unsigned int ou unsigned : ............................................................................................................... 3<br />
II.2.d. short : .............................................................................................................................................. 3<br />
II.2.e. unsigned short : ............................................................................................................................... 3<br />
II.2.f. long int ou long : .............................................................................................................................. 3<br />
II.2.g. unsigned long int ou unsigned long : .............................................................................................. 3<br />
II.2.h. double : ........................................................................................................................................... 3<br />
II.2.i. long double : .................................................................................................................................... 4<br />
II.2.j. Dynamique <strong>de</strong>s nombres : ................................................................................................................ 4<br />
II.3. Les types composés ................................................................................................................................... 4<br />
II.3.a. les tableaux : .................................................................................................................................... 4<br />
II.3.b. les structures : ................................................................................................................................. 4<br />
II.3.c. les unions : ...................................................................................................................................... 5<br />
II.4. Autres types ............................................................................................................................................... 5<br />
II.4.a. les types définis par le programmeur .............................................................................................. 5<br />
II.4.b. void ................................................................................................................................................. 5<br />
III. La déclaration <strong>de</strong>s variables ............................................................................................................................. 5<br />
IV. Constantes ....................................................................................................................................................... 5<br />
V. Organisation générale d'un module ................................................................................................................... 7<br />
VI. Constitution d'une fonction ............................................................................................................................. 7<br />
VI.1. Définition d'une fonction ......................................................................................................................... 7<br />
VI.2. Prototypes ................................................................................................................................................ 8<br />
VII. Blocs d'instructions ........................................................................................................................................ 8<br />
VII.1. Opérateurs ............................................................................................................................................... 9<br />
VII.1.a. Opérateurs arithmétiques :............................................................................................................ 9<br />
VII.1.b. Opérateurs logiques : ................................................................................................................... 9<br />
VII.1.c. Opérateurs d'affectation : ............................................................................................................. 9<br />
VII.1.d. Opérateur ternaire : .................................................................................................................... 10<br />
VII.1.e. Séquenceur : ............................................................................................................................... 10<br />
VII.1.f. Opérateurs unaires : .................................................................................................................... 10<br />
VII.2. Expressions ........................................................................................................................................... 11<br />
VII.3. Instructions <strong>de</strong> contrôle <strong>de</strong> déroulement ............................................................................................... 11<br />
VII.3.a. Tests si … sinon … ..................................................................................................................... 11<br />
VII.3.b. Boucles tant que … faire : .......................................................................................................... 11<br />
VII.3.c. Boucles faire … tant que : .......................................................................................................... 12<br />
VII.3.d. Boucles for .............................................................................................................................. 12<br />
VII.3.e. Tests énumératifs (switch … case) ............................................................................................. 12<br />
VII.3.f. Rupture <strong>de</strong> séquence break : .................................................................................................... 13<br />
VII.3.g. Rupture <strong>de</strong> séquence continue : ............................................................................................ 13<br />
VII.3.h. Branchements inconditionnels ................................................................................................... 13<br />
VIII. Portée <strong>de</strong>s données ...................................................................................................................................... 13<br />
VIII.1. Donnée globale au programme ............................................................................................................ 14<br />
VIII.2. Donnée locale à un module ................................................................................................................. 14<br />
VIII.3. Donnée locale à une fonction .............................................................................................................. 14<br />
-50-
LICENCE SPI-EEA TABLE DES MATIÈRES M. <strong>Deloizy</strong><br />
VIII.4. Donnée locale à un bloc d'instructions ................................................................................................ 14<br />
IX. Classes d'allocation........................................................................................................................................ 14<br />
IX.1. static ....................................................................................................................................................... 15<br />
IX.2. auto ......................................................................................................................................................... 15<br />
IX.3. const ....................................................................................................................................................... 15<br />
IX.4. register.................................................................................................................................................... 15<br />
IX.5. volatile.................................................................................................................................................... 15<br />
X. Les pointeurs ................................................................................................................................................... 16<br />
X.1. Définition ................................................................................................................................................ 16<br />
X.2. Arithmétique <strong>de</strong>s pointeurs...................................................................................................................... 16<br />
X.3. Utilité <strong>de</strong>s pointeurs ................................................................................................................................. 17<br />
X.3.a. Les tableaux ..................................................................................................................................... 17<br />
X.3.b. Chaînes <strong>de</strong> caractères ....................................................................................................................... 17<br />
X.3.c. Fonctions et pointeurs ...................................................................................................................... 17<br />
XI. Les fichiers .................................................................................................................................................... 18<br />
XI.1. Notion <strong>de</strong> flux ........................................................................................................................................ 18<br />
XI.2. Flux en sortie. ......................................................................................................................................... 19<br />
XI.3. Flux en entrée. ........................................................................................................................................ 19<br />
XI.4. Fonctions <strong>de</strong> gestion ............................................................................................................................... 19<br />
XII. Fonctions standard ....................................................................................................................................... 19<br />
XII.1. Manipulation <strong>de</strong> chaînes <strong>de</strong> caractères ............................................................................... 19<br />
XII.1.a. Traitement <strong>de</strong> données brutes ..................................................................................................... 20<br />
XII.1.b. Copie et concaténation : ............................................................................................................. 20<br />
XII.1.c. Comparaisons <strong>de</strong> chaînes <strong>de</strong> caractères : .................................................................................... 20<br />
XII.1.d. Recherche <strong>de</strong> séquences : ........................................................................................................... 21<br />
XII.1.e. Fonctions diverses : .................................................................................................................... 21<br />
XII.2. Entrées sorties ...................................................................................................................... 22<br />
XII.2.a. Entrées / Sorties formatées : ....................................................................................................... 22<br />
XII.2.b. Spécifications <strong>de</strong> format (pour printf et scanf) : ......................................................................... 22<br />
XII.2.c. Fonctions d'entrées : ................................................................................................................... 23<br />
XII.2.d. Fonctions <strong>de</strong> sorties : .................................................................................................................. 23<br />
XII.2.e. Gestion <strong>de</strong> fichiers (flux) :.......................................................................................................... 24<br />
XII.2.f. Exemple : copie <strong>de</strong> fichier texte ................................................................................................. 25<br />
XII.3. Fonctions utilitaires : ........................................................................................................... 25<br />
XII.3.a. Conversion <strong>de</strong> chaînes <strong>de</strong> caractères : ........................................................................................ 25<br />
XII.3.b. Générateur <strong>de</strong> nombres aléatoires : ............................................................................................ 26<br />
XII.3.c. Fouilles et tris : ........................................................................................................................... 26<br />
XII.3.d. Allocation <strong>de</strong> mémoire : ............................................................................................................. 26<br />
XII.3.e. Fonctions système : .................................................................................................................... 27<br />
XII.3.f. Opérations sur <strong>de</strong>s entiers : ......................................................................................................... 27<br />
XIII. Structures .................................................................................................................................................... 28<br />
XIV. Le préprocesseur ......................................................................................................................................... 29<br />
XIV.1. Comman<strong>de</strong> inclu<strong>de</strong>. ............................................................................................................................. 29<br />
XIV.2. Comman<strong>de</strong> <strong>de</strong>fine. .............................................................................................................................. 29<br />
Constantes : ................................................................................................................................................. 29<br />
Macro-définitions : ..................................................................................................................................... 29<br />
XIV.3. Compilation conditionnelle ................................................................................................................. 30<br />
TD1 : Types <strong>de</strong> données – Codage ............................................................................................................................ 31<br />
TD2 : Premiers programmes ..................................................................................................................................... 32<br />
TD3 : Utilisation <strong>de</strong> tableaux. .................................................................................................................................... 32<br />
TD4 : Conversions ASCII / numériques ................................................................................................................... 33<br />
TD5 : Traitements sur les chaînes ............................................................................................................................. 33<br />
TD6 : Fichiers ............................................................................................................................................................. 33<br />
TP1 : Déclarations, Premiers programmes, Débogage ........................................................................................... 34<br />
TP2 : Manipulations <strong>de</strong> Chaînes <strong>de</strong> Caractères....................................................................................................... 35<br />
TP3 : Tableaux <strong>de</strong> données ........................................................................................................................................ 36<br />
TP4 : Fichiers .............................................................................................................................................................. 37<br />
TP5 : Structures ......................................................................................................................................................... 38<br />
-51-
LICENCE SPI-EEA TABLE DES MATIÈRES M. <strong>Deloizy</strong><br />
TP6 : Étu<strong>de</strong> <strong>de</strong> fonctions mathématiques ................................................................................................................. 39<br />
TP7 : Acquisition et Traitement <strong>de</strong> données ............................................................................................................ 40<br />
Bibliothèques (Cstdlib)............................................................................................................................................... 42<br />
................................................................................................................................................................. 42<br />
................................................................................................................................................................. 42<br />
................................................................................................................................................................. 42<br />
................................................................................................................................................................... 42<br />
................................................................................................................................................................. 42<br />
................................................................................................................................................................ 43<br />
.................................................................................................................................................................. 43<br />
............................................................................................................................................................... 43<br />
................................................................................................................................................................ 43<br />
................................................................................................................................................................ 44<br />
................................................................................................................................................................ 44<br />
.................................................................................................................................................................. 44<br />
................................................................................................................................................................. 45<br />
................................................................................................................................................................. 45<br />
................................................................................................................................................................... 46<br />
Mémento du langage C .............................................................................................................................................. 47<br />
Structure <strong>de</strong> base ...................................................................................................................................................... 47<br />
Variables et constantes ............................................................................................................................................. 47<br />
Entrées et sorties ...................................................................................................................................................... 47<br />
Fichiers : .................................................................................................................................................................. 47<br />
Tests, choix, boucles ................................................................................................................................................ 47<br />
La structure <strong>de</strong> contrôle if-else if-else ................................................................................................................. 47<br />
La boucle for ........................................................................................................................................................ 48<br />
La boucle while ................................................................................................................................................... 48<br />
La boucle do-while .............................................................................................................................................. 48<br />
Fonctions .................................................................................................................................................................. 48<br />
Fonction retournant une valeur ............................................................................................................................ 48<br />
Fonction ne retournant rien .................................................................................................................................. 48<br />
Déclaration dřune fonction et utilisation ............................................................................................................. 48<br />
Pointeurs et allocation <strong>de</strong> mémoire .......................................................................................................................... 48<br />
Pointeurs .............................................................................................................................................................. 48<br />
Allocation <strong>de</strong> mémoire ........................................................................................................................................ 48<br />
Pointeur <strong>de</strong> fonction............................................................................................................................................. 49<br />
Structures et définition <strong>de</strong> type ................................................................................................................................ 49<br />
En vrac... .................................................................................................................................................................. 49<br />
Table <strong>de</strong>s Matières ........................................................................................................................................................... 50<br />
-52-