Sie sind auf Seite 1von 162

Initiation au langage C

---------------------------------------------------------------
Module A2I-1: Informatique 1
Masters:
* Électronique et Systèmes de Communication (ESCom)
* Mécanique et Énergétique(ME)
* Physique et Sciences de la Matière(PSM)

Pr. A. ZIYYAT

2007/2008
    1. Présentation du langage C par l’exemple
-------------------------------------------------------------------
1.1. Un exemple de programme en langage C :

Voici un programme en C :
#include <stdio.h>
#define TVA 18.6
main()
{
float HT;
float TTC;
printf ("Veuillez entrer le prix H.T. :");
scanf("%f",&HT);
TTC=HT*(1+(TVA/100));
printf("Prix T.T.C. :%f\n",TTC);
}
Voici un exemple de l’exécution de ce programme:
Veuillez entrer le prix H.T. :100
Prix T.T.C. :118.600000
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.2 Structure d’un programme en langage C

La ligne : main()
C’est une entête de fonction.
Dans ce cas, le programme ne possède qu'une seule fonction, la fonction
principale (main function). Cette ligne est obligatoire en C : elle définit le
"point d'entrée" du programme, c'est à dire l'endroit où débutera l'exécution
du programme.
Le nom main est imposé. Le programme principal vient à la suite de cette
entête. Il est délimité par des accolades { et }.
Les instructions situées entre ces accolades forment un bloc, dit bloc
d’instructions.
Le bloc d’instruction de notre exemple comporte des déclarations de
variables et des instructions.
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.3 Déclarations
Les deux instructions :
float HT;
float TTC;
sont des déclarations.
Elles sont sous la forme :
type listevariables;
Une variable est une case mémoire de l'ordinateur, que l'on se réserve pour
notre programme.
On définit le nom que l'on choisit pour chaque variable, ainsi que son type,
ici float, c'est à dire réel (type dit à virgule flottante, d'où ce nom). Les trois
types scalaires de base du C sont l'entier (int), le réel (float) et le caractère
(char).
On ne peut jamais utiliser de variable sans l'avoir déclarée
auparavant.
Une faute de frappe devrait donc être facilement détectée.
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.3 Instructions
Une instruction est un ordre élémentaire que l'on donne à la machine, qui
manipulera les données (variables) du programme, ici soit par appel de
fonctions (printf , scanf) soit par affectation (=).

Toutes les instructions se terminent par un ;.


Notre programme comporte 4 instructions:
1: printf ("Veuillez entrer le prix H.T. :");
2: scanf("%f",&HT);
3: TTC=HT*(1+(TVA/100));
4: printf("Prix T.T.C. :%f\n",TTC);

Voyons ces quatre instructions:


    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.3 Instructions
L’instruction : printf ("Veuillez entrer le prix H.T. :");
appelle en fait une fonction prédéfinie (fournie avec le langage C)
nommée printf. Ici, cette fonction reçoit un argument qui est :
"Veuillez entrer le prix H.T. :"
Les guillemets servent à délimité une "chaine de caractères" (suite
de caractères).
printf: affiche à l'écran le texte qu'on lui donne (entre parenthèses,
comme tout ce que l'on donne à une fonction, et entre guillemets,
comme toute constante texte en C).
L’autre instruction contenant printf à la fin du programme, soit :
printf("Prix T.T.C. :%f\n",TTC);
affiche le résultat stocké dans TTC. Seulement cette fois ci, la
fonction « printf » reçoit ici deux arguments. Pour comprendre son
fonctionnement, il faut savoir que le premier argument de prinf est
ce que l’on nomme un « Format ». Il s’agit d’une commande
précisant comment afficher les informations qui sont fournis par les
arguments.
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.3 Instructions

scanf("%f",&HT);
scanf attend que l'on entre une valeur au clavier, puis la met dans
la mémoire (on préfère dire variable) HT, sous format réel (%f). La
fonction scanf reçoit ici deux arguments.
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.3 Instructions
TTC=HT*(1+(TVA/100));
une affectation : on commence par diviser TVA par 100 (à cause
des parenthèses), puis on y ajoute 1, puis on le multiplie par le
contenu de la variable HT.
Le résultat de ce calcul est stocké (affecté) dans la variable cible
TTC.
Une affectation se fait toujours dans le même sens : on détermine
(évalue) tout d'abord la valeur à droite du signe =, en faisant tous
les calculs nécessaires, puis elle est transférée dans la mémoire
dont le nom est indiqué à gauche du =. On peut donc placer une
expression complexe à droite du =, mais à sa gauche seul un nom
de variable est possible, aucune opération.
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.4 Directives du pré processeur
Les directives du pré processeur commencent toujours par #
Exemple: #include.
Ici la fonction principale main() contient la fonction printf(). En réalité le
compilateur ne connaît pas la fonction printf() bien qu'il s'agisse d'une
fonction standard du langage C. Cette fonction est effectivement stockée
dans un fichier annexe, contenant une librairie de fonctions, appelé fichier
de définition (dits aussi fichier d'en-tête ou fichier header), dont l’extension
est .h.
Il s'agit donc de préciser au compilateur dans quel fichier se trouve la
définition de la fonction printf()...
Celle-ci se trouve dans le fichier d'en-tête appelé stdio.h.
L'incorporation de la déclaration de la fonction printf() se fait au moyen de
l'instruction #include (que l'on place en début de fichier) suivie des balises
< et > contenant le nom de fichier contenant la définition de la fonction. La
déclaration include doit se trouver avant toute utilisation des méthodes
déclarées, sinon le compilateur générera au minimum un warning
    1. Présentation du langage C par
l’exemple
-------------------------------------------------------------------
1.4 Directives du pré processeur
Les directives du pré processeur commencent toujours par #
#include : inclure le fichier définissant (déclarant) les fonctions
standard d'entrées/sorties (en anglais STanDard In/Out), qui feront
le lien entre le programme et la console (clavier/écran). Dans cet
exemple il s'agit de scanf et printf.

#define : définit une constante. A chaque fois que le compilateur


rencontrera, dans sa traduction de la suite du fichier en langage
machine, le mot TVA, ces trois lettres seront remplacées par 18.6.
Ces transformation sont faites dans une première passe (appelée
pré compilation), où l'on ne fait que du "traitement de texte", c'est
à dire des remplacements d'un texte par un autre sans chercher à
en comprendre la signification.
Il existe d'autres commandes du pré-processeur qui seront
détaillées dans ce cours.
Les instructions dédiées au pré-processeur ne se terminent pas
par un point-virgule !
    2. Quelques règles d’écriture
-------------------------------------------------------------------
2.1 Les identificateurs
En C, on désigne les objets (variables, fonctions, etc.) que l'on
manipule par un nom, appelé aussi « identificateur ».

Pour être valide, le premier caractère d'un identificateur doit


obligatoirement être une lettre (A...Z, a...z) ou un underscore (_)

Les caractères suivants sont choisis parmi les lettres (A...Z, a...z),
les chiffres (0...9) ou l'underscore ( _).
La norme ANSI n'impose aucune limite sur la longueur d'un nom.
Toutefois le compilateur ne tiendra compte que des 32 premiers
caractères.
Attention : le C est sensible à la casse (case sensitive) C'est à
dire qu'il fait la distinction entre les majuscules et les minuscules.
Ex.: les spécifications du langage C précisent que la fonction
principale doit être appelée main() et non Main() ou MAIN()
    2. Quelques règles d’écriture
-------------------------------------------------------------------
Exemples d’identificateurs:

Correct Incorrect Raison

Variable Nom de Variable comporte des espaces

Nom_De_Variable 123Nom_De_Variable commence par un chiffre

nom_de_variable toto@mailcity.com caractère spécial @

nom_de_variable_1 Nom-de-variable signe – interdit

_707 float nom réservé


    2. Quelques règles d’écriture
-------------------------------------------------------------------
2.2 les mots-clés
Les noms réservés en C sont les mots-clé du langage. Ci-dessous la liste
de tous les noms réservés par la norme ANSI. Ces noms ne peuvent être
utilisés comme identificateurs d’objets (noms de variables, de fonctions ou
de types). Il est possible que certains compilateurs y ajoutent quelques
mots qui leur sont propres.

Liste des noms réservés:


auto break case, char, const continue

default do double else enum extern


float for goto if int Long
register return short signed sizeof static
struct switch Typedef union unsigned void
volatile while
    2. Quelques règles d’écriture
-------------------------------------------------------------------
2.3 Les séparateurs

Deux identificateurs successifs entre lesquels la syntaxe n’impose


aucun signe particulier (tel que: , = ; * ( ) [ ] { }) doivent impérativement
être séparés soit par un espace, soit par une fin de ligne.
float x,y et non floatx,y
float x,y,z et plus lisiblement float x, y, z

2.4 Le format libre


En C, la mise en page est parfaitement libre
Les fins de ligne jouent le rôle de séparateurs, comme un espace,
sauf dans les constantes chaînes, où elle sont interdites)
•Une ligne peut comporter plusieurs instructions
•Une instruction peut s’étendre sur plusieurs lignes
•Attention à la lisibilité du programme
    2. Quelques règles d’écriture
-------------------------------------------------------------------
2.5 Les commentaires

Les commentaires sont des textes explicatifs destinés aux lecteurs


du programme et qui n’ont aucune incidence sur le compilateur.
En C, il est possible d'insérer un commentaire partout où l'insertion
d'un espace est possible.

Un commentaire commence par une barre oblique suivie d'une


étoile ( /* ), et se termine par une étoile suivie d'une barre oblique
( */ ). Tout ce qui est compris entre les deux symboles est
totalement ignoré par le compilateur.
/* Ceci est un commentaire */

Le symbole // permet de mettre en commentaire toute la ligne qui la


suit (i.e. les caractères à droite de ce symbole sur la même ligne).
La notation // est généralement réservée pour mettre en
commentaire une ligne de code que l'on souhaite désactiver
temporairement.
    2. Quelques règles d’écriture
-------------------------------------------------------------------
2.5 Les commentaires
Il y a toutefois quelques règles à respecter:

•Les commentaires peuvent être placés n'importe où dans le fichier


source
•Les commentaires ne peuvent contenir le délimiteur de fin de
commentaire (*/)
•Les commentaires ne peuvent être imbriqués
•Les commentaires peuvent être écrits sur plusieurs lignes
•Les commentaires ne peuvent pas couper un mot du programme
en deux
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.1 Notions de variable
Une variable permet de stocker une valeur. Le type de valeurs
stockées dépend du type de la variable.
L'opérateur = permet d'affecter une valeur à une variable. Toutes
les variables doivent être définies (ou au moins déclarées) avant
d'être utilisées.
On peut initialiser une variable lors de sa définition en lui affectant
directement une valeur.
Pour un même type, on peut réunir plusieurs définitions de
variables sur une même instruction.
Exemple:.
int x1, X2 = 18;
double X3;
X3 = X2 + 25;
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.1 Notions de variable
En C, il faut préciser le type de donnée, ce qui permet de connaître
l'occupation mémoire (le nombre d'octets) de la donnée ainsi que
sa représentation.
*des nombres : entiers (int) ou réels, c'est-à-dire à virgules (float)
*des pointeurs (pointer) : permettent de stocker l'adresse d'une
autre donnée, ils « pointent » vers une autre donnée

Une variable se déclare de la façon suivante :


type Nom_de_la_variable;
ou bien s'il y a plusieurs variables du même type :
type Nom_de_la_variable1, Nom_de_la_variable2, ...;

En C il existe plusieurs types de données. Les types de base sont


néanmoins au nombre de 3:
Entier, Flottant et Caractère
    3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.2 Les types de base

Voici un tableau donnant les types de données en langage C :

Type de donnée Signification Taille (en octets) Plage de valeurs acceptée


char Caractère 1 -128 à 127
unsigned char Caractère non signé 1 0 à 255
short int Entier court 2 -32 768 à 32 767
unsigned short int Entier court non signé 2 0 à 65 535
2 (sur processeur 16 bits) -32 768 à 32 767
int Entier
4 (sur processeur 32 bits) -2 147 483 648 à 2 147 483 647
2 (sur processeur 16 bits) 0 à 65 535
unsigned int Entier non signé
4 (sur processeur 32 bits) 0 à 4 294 967 295
long int Entier long 4 -2 147 483 648 à 2 147 483 647
unsigned long int Entier long non signé 4 0 à 4 294 967 295
float Flottant (réel) 4 3.4*10-38 à 3.4*1038
double Flottant double 8 1.7*10-308 à 1.7*10308
long double Flottant double long 10 3.4*10-4932 à 3.4*104932
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.3 Les types de base

Nombre entier (int)


Un nombre entier est un nombre sans virgule qui peut être exprimé dans
différentes bases :
Base décimale : l'entier est représenté par une suite de chiffres unitaires
(de 0 à 9) ne devant pas commencer par le chiffre 0
Base hexadécimale : l'entier est représenté par une suite d'unités (de 0 à 9
ou de A à F (ou a à f)) devant commencer par 0x ou 0X (0 ici est le chiffre
0)
Base octale : l'entier est représenté par une suite d'unités (incluant
uniquement des chiffres de 0 à 7) devant commencer par le chiffre 0
Les entiers sont signés par défaut, cela signifie qu'ils comportent un signe.

Le type int peut être précédé par les mots-clés: short, long.
Chacun de ces types peut être spécifié comme étant sans signe en le
précédant du mot-clé unsigned : unsigned int, unsigned long... . .
short a = 12, b = 19;
unsigned long d = 3123456789ul;
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.3 Les types de base
Nombre à virgule (float)
Un nombre à virgule flottante est un nombre à virgule, il peut
toutefois être représenté de différentes façons :
•un entier décimal : 895
•un nombre comportant un point (et non une virgule) : 845.32
•une fraction : 27/11
•un nombre exponentiel, c'est-à-dire un nombre (éventuellement à
virgule) suivi de la lettre e (ou E), puis d'un entier correspondant à
la puissance de 10 (signé ou non, c'est-à-dire précédé d'un + ou
d'un -) : 2.75e-2 35.8E+10 .25e-2
Les nombres réels sont des nombres à virgule flottante, c'est-à-
dire un nombre dans lequel la position de la virgule n'est pas fixe,
et est repérée par une partie de ses bits (appelée l'exposant), le
reste des bits permettent de coder le nombre sans virgule (
la mantisse).
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.3 Les types de base
Nombre à virgule (float)
Les nombres de type float sont codés sur 32 bits dont :
23 bits pour la mantisse, 8 bits pour l'exposant et 1 bit pour le
signe

Les nombres de type double sont codés sur 64 bits dont :


52 bits pour la mantisse, 11 bits pour l'exposant et 1 bit pour le
signe
Les nombres de type long double sont codés sur 80 bits dont :
64 bits pour la mantisse, 15 bits pour l'exposant et 1 bit pour le
signe

La précision des nombres réels est approchée. Elle dépend par le


nombre de positions décimales, suivant le type de réel elle sera au
moins : de 6 chiffres pour le type float
de 15 chiffres pour le type double
de 17 chiffres pour le type long double
  3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.3 Les types de base
Caractère (char)
Le type char (provenant de l'anglais character) permet de stocker
un objet sur 8bits, exemple:la valeur ASCII d'un caractère, c'est-à-
dire un nombre entier !
Par défaut les nombres sont signés, cela signifie qu'ils comportent
un signe
Une donnée de type char est signée!
Par contre, on peut la faire précéder du mot-clé unsigned pour
quelle ne soit plus signé: unsigned char
Exemple: pour stocker la lettre B (son code ASCII est 66), on
pourra définir cette donnée soit par le nombre 66, soit en notant 'B'
où les apostrophes simples signifient code ascii de...

Il n'existe pas de type de données pour les chaînes de caractères


(suite de caractères) en langage C. Pour créer une chaîne de
caractères on utilisera donc des tableaux contenant dans chacune
de ses cases un caractère...
    3. LES VARIABLES - TYPES DE DONNEES

-------------------------------------------------------------------
3.4 Les constantes
Une constante est une variable dont la valeur est inchangeable lors de
l'exécution d'un programme.
En langage C, les constantes sont définies grâce à la directive du
préprocesseur #define, qui permet de remplacer toutes les occurrences du
mot qui le suit par la valeur immédiatement derrière elle.
Par exemple la directive : #define _Pi 3.1415927

Avec cette méthode les constantes ne sont pas typées. Il est ainsi préférable
d'utiliser le mot clef const, qui permet de déclarer des constantes typées :
const int dix = 10;
Cela permet d'éviter certains problèmes du #define, qui fait du « chercher-
remplacer » textuel sans réfléchir.
On distingue quatre types de constantes : entières, flottantes, caractères et
chaînes.
   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.4 les constantes entières
Les constantes entières sont représentées par une suite de chiffres (en
décimal par défaut) précédée éventuellement par un signe (+ ou - ). Si cette
suite commence par 0, la constante s'exprime en octal (base 8). Si cette suite
commence par 0x ou 0X, la constante s'exprime en héxadécimal (base 16).
Par défaut, une constante entière est de type int. Si la constante se termine
par l ou L, elle est de type long. Si, elle se termine par u ou U, elle est de type
unsigned.
Les constantes entières
Constante Valeur décimale Type
1924 1924 int

0110 96 ( = 82 + 81) int

0xFF 255 ( = 15 . 161 + 15) int

-123L -123 long

0200U 128 unsigned int

0xFFFFUL 65535 unsigned long


   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.4 les constantes réelles
Une constante réelle (on dit aussi flottante) est constituée d'une partie entière,
d'un point décimale, d'une partie décimale, de la lettre e ou E et enfin d'un
exposant entier éventuellement négatif. Certains de ces éléments peuvent être
omis mais pour être considérée comme réelle, une constante doit contenir un
point décimal ou un exposant. Par défaut, une constante réelle est de type
double. Si la constante est terminée par la lettre f, elle est alors de type float.

Les constantes réelles


Constante Valeur décimale Type
1. 1 double

7e3 7 . 103 = 7000 double

.1e3 0,1 . 103 = 100 double

-123.12e-2 -123,12 . 10-2 = -1,2312 double


-12.5f -12,5 float
   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.4 les constantes caractères
Une constante caractère est de type char. Elle est constituée d'un caractère
écrit entre apostrophes ('). La valeur de cette constante est la valeur de ce
caractère dans le codage de la machine utilisée (en général le codage ASCII).
Exemple: ‘b’ ‘Z’ ‘+’ ‘&’

Il est possible d’utiliser directement le code du caractère en l’exprimant à la


suite du caractère antislash \ :
• soit sous forme octale
• soit sous forme hexadécimale précédée de x
Exemple:
‘A’ ‘\x41’ ‘\101’
‘\n’ ‘\x0a’ ‘\12’ ‘\012’
‘\a’ ‘\x07’ ‘\x7’ ‘\07’ ‘\007’
   CODE ASCII
   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.4 les constantes caractères
Certains caractères spéciaux ou non imprimables possèdent une
représentation conventionnelle utilisant le caractère antislash ( \).
Les constantes caractères
Effet ASCII Codage C
fin de ligne NL (LF) \n

tabulation HT \t

retour arrière BS \b

retour chariot CR \r

saut de page FF \f

signal sonore BEL \a

barre oblique inverse \ \\

point d'interrogation ? \?

apostrophe ' \'

guillemet " \"


   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.4 les constantes chaînes
Les constantes chaînes de caractères s'écrivent entre des guillemets ("). Elles
sont constituées d'une suite de caractères. Comme pour les constantes
caractères, on peut utiliser le caractère d'échappement pour saisir des
caractères spéciaux. Le compilateur ajoute tout seul le caractère NUL (\0) en
fin de chaîne. Une chaîne est de type pointeur sur caractère (char *) et pointe
sur un tableau de caractères contenant la suite des caractères complétée par
le caractère NUL de fin de chaîne (\0).

"Voici une chaîne terminée par une fin de ligne\n"


   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.5 Initialisation
1. Directive #define
2. Initialisation lors de la declaration
Exemple:
int n=15;
n est une variable de type int, initialisée à 15

const int n=25;


Toute instruction modifiant la valeur de n sera rejetée par le
compilateur
   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.6 Conversion de type de données
On appelle conversion de type de données le fait de modifier le type
d'une donnée en un autre.
Exemple:. On travaille sur sur une variable en virgule flottante (type
float), il se peut que l'on veuille « supprimer les chiffres après la
virgule », c'est-à-dire convertir un float en int.

Cette opération peut être réalisée de deux manières

1) conversion implicite : une conversion implicite consiste en une


modification du type de donnée effectuée automatiquement par le
compilateur. Cela signifie que lorsque l'on va stocker un type de
donnée dans une variable déclarée avec un autre type, le compilateur
ne retournera pas d'erreur mais effectuera une conversion implicite de
la donnée avant de l'affecter à la variable.
int x; x = 8.324; x contiendra après affectation la valeur 8.
   3. LES VARIABLES - TYPES DE DONNEES
-------------------------------------------------------------------
3.6 Conversion de type de données

2) conversion explicite : une conversion explicite (appelée aussi


opération de cast) consiste en une modification du type de donnée
forcée. Cela signifie que l'on utilise un opérateur dit de cast pour
spécifier la conversion. L'opérateur de cast est tout simplement le
type de donnée, dans lequel on désire convertir une variable, entre
des parenthèses précédant la variable.
int x; x = (int)8.324; x contiendra après affectation la valeur 8.
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.1 La fonction printf

printf est une fonction externe inclue dans la bibliothèque de fonctions C


standards. Elle permet d'afficher à l'écran des informations provenant du
programme.
Elle prend un nombre d'arguments variable. Son premier argument est une
chaîne de caractères spécifiant le format d'affichage. Les arguments suivants
sont les valeurs qu'il faudra afficher. C'est le contenu du format qui permet de
dire comment les arguments suivants seront affichés :
printf(format, arg1, ... , argN);
Le format est interprété de la manière suivante :
•les caractères ordinaires sont affichés tel quel ;
•certains caractères précédés d'une barre oblique inverse (\ ) permettent de
faire de la mise en page (tabulation, passage à la ligne, ...).
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.1 La fonction printf
•une séquence commençant par le caractère % sera remplacer à l'affichage
par la valeur d'un argument. Le caractère qui suit le % précise le type de
l'argument et la manière dont il sera affiché (tableau suivant).
Séquences spéciales dans un printf.
Séquence l'argument remplaçant la séquence doit être
% c un caractère seul
% s une chaîne de caractère
% d un entier (affiché en décimal)
% o un entier (affiché en octal)
% x un entier (affiché en héxadécimal)
% u un entier non signé (affiché en décimal)
% f un réel (affiché normalement)
% e un réel (affiché en notation exponentielle)
% g un réel (au mieux entre f et e)
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.1 La fonction printf
On peut introduire entre le % et le caractère de spécification de format
d'affichage quelques caractères de contrôles d'affichage :
•le caractère ‘-’ permet d'afficher l'argument aligné à gauche (par défaut à
droite).
•le caractère ‘+’ fait qu'un nombre est toujours affiché avec son signe (par
défaut seul le moins est affiché).
•un nombre indique la longueur totale exacte (ou minimale en caractères) pour
afficher l'argument. Par défaut:
– Entier: nombre de caractères nécessaires
– Flottant: 6 chiffres après la virgule
•le caractère ‘.’ suivi d'un nombre permet de spécifier pour les valeurs réels le

nombre de chiffres après la virgule.


   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.1 La fonction printf
double a=3.141592653589793115997963;
Exemple:
printf("Pi = %e n", a);
printf("Pi = %f n", a);
printf("Pi = %15f n", a);
printf("Pi = %18.13f n", a);
printf("Pi = %+.13f n", a);
printf("Pi = %-+18.13f n", a);
printf("Pi = %.25f n", a);

Affiche :
Pi = 3.141593e+00
Pi = 3.141593
Pi = 3.141593
Pi = 3.1415926535898
Pi = +3.1415926535898
Pi = +3.1415926535898
Pi = 3.1415926535897931159979630
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.2 La fonction scanf

scanf permet de lire et d'interpréter du texte saisie par l'utilisateur au


clavier.
Comme printf, cette fonction utilise un format suivi d'un nombre
variable d'arguments que scanf devra lire.
Comme ces arguments vont être modifiés par la fonction, il faut
toujours lui envoyer des pointeurs sur les variables à lire.
Dans le format, c'est encore le caractère % qui spécifie l'utilisation des
arguments.
Nous donnons dans le tableau suivant la liste des principales
séquences utilisables.
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.2 La fonction scanf
Séquences spéciales dans un scanf.
Séquence interprétation de la saisie type de l'argument
% c un caractère seul char *

% s une chaîne de caractère char *

% d un entier en décimal int *

% o un entier en octal (précédé d'un 0) int *


% x un entier en héxa (précédé de 0x) int *
% u un entier non signé décimal unsigned int *

% f un réel float *

% e un réel float *

% g un réel float *
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.2 La fonction scanf
Attention : il faut faire précéder les caractères spécifiant un entier (d, o, x, u)
du caractère l pour spécifier que l'entier est de type long * ou du caractère h
pour spécifier que l'entier est de type short *. De même pour les réels, si le
caractère est précédé d'un l alors le type est double *.
Exemples :
double a;
int g;
char str[300];

printf("Donnez la valeur de a :");


scanf("%lf", &a);

printf("Donnez la valeur de g (en octal) :");


scanf("%o", &g);

printf("Donnez la valeur de str :");


scanf("%s", str);

Remarque : dans le cas d'un tableau de caractères, il ne faut pas mettre de &
devant le nom du tableau puisque ce nom représente déjà un pointeur sur le
tableau. .
   4. ENTREES - SORTIES
-------------------------------------------------------------------
4.3 putchar et getchar
La macro putchar
putchar (c) joue le rôle de: printf ("%c", c)

La macro getchar
getchar (c) joue le rôle de: scanf ("%c", &c)

Avec la différence dans la directive: #include <stdio.h>


L’oubli de cette directive engendre une erreur à l’édition de lien
   5. LES OPERATEURS
-------------------------------------------------------------------
5.1 Les opérateurs
Les opérateurs sont des symboles qui permettent de manipuler des variables,
c'est-à-dire effectuer des opérations, les évaluer, etc.
On distingue plusieurs types d'opérateurs :
• les opérateurs de calcul
• les opérateurs d'assignation
• les opérateurs d'incrémentation
• les opérateurs de comparaison
• les opérateurs logiques
• (les opérateurs bit-à-bit)
• (les opérateurs de décalage de bit)
   5. LES OPERATEURS
-------------------------------------------------------------------
5.2 Les opérateurs de calcul
Les opérateurs de calcul permettent de modifier mathématiquement la valeur
d'une variable.
Ces opérateurs ne sont à priori définis que pour deux opérandes ayant le
même type. Il fournissent un résultat du même type que leurs opérandes.

Opérateur Dénomination Effet Exemple Résultat (avec x valant 7)


+ opérateur d'addition Ajoute deux valeurs x+3 10
opérateur de
- Soustrait deux valeurs x-3 4
soustraction
opérateur de
* Multiplie deux valeurs x*3 21
multiplication
/ opérateur de division Divise deux valeurs x/3 2.3333333
Affecte une valeur à une Met la valeur 3 dans la
= opérateur d'affectation x=3
variable variable x
   5. LES OPERATEURS
-------------------------------------------------------------------
5.3 Les opérateurs d’assignation
Ces opérateurs permettent de simplifier des opérations telles que ajouter une
valeur dans une variable et stocker le résultat dans la variable. Une telle
opération s'écrirait habituellement de la façon suivante par exemple : x=x+2
Avec les opérateurs d'assignation il est possible d'écrire cette opération sous
la forme suivante : x+=2
Ainsi, si la valeur de x était 7 avant opération, elle sera de 9 après...
Les autres opérateurs du même type sont les suivants :
Opérateur Effet
+= additionne deux valeurs et stocke le résultat dans la variable (à gauche)
-= soustrait deux valeurs et stocke le résultat dans la variable
*= multiplie deux valeurs et stocke le résultat dans la variable
/= divise deux valeurs et stocke le résultat dans la variable
L'opérateur d'affectation = renvoie aussi une valeur, qui est celle de la variable
après affectation. Cela permet notamment de faire des affectations en
cascade :
a = b = c = 1; ce qui correspond à :
a = (b = (c = 1));
   5. LES OPERATEURS
-------------------------------------------------------------------
5.4 Les opérateurs d’incrémentation
Ce type d'opérateur permet de facilement augmenter ou diminuer d'une unité
une variable. Ces opérateurs sont très utiles pour des structures telles que des
boucles, qui ont besoin d'un compteur (variable qui augmente de un en un).
Un opérateur de type x++ permet de remplacer des notations lourdes telles
que x=x+1 ou bien x+=1.

Opérateur Dénomination Effet Syntaxe Résultat (avec x valant 7)


++ Incrémentation Augmente d'une unité la variable x++ 8
-- Décrémentation Diminue d'une unité la variable x-- 6
   5. LES OPERATEURS
-------------------------------------------------------------------
5.5 Les opérateurs de comparaison
Résultat (avec x
Opérateur Dénomination Effet Exemple
valant 7)
==
A ne pas confondre Compare deux valeurs et Retourne 1 si x est
opérateur d'égalité x==3
avec le signe vérifie leur égalité égal à 3, sinon 0
d'affectation (=) !
Vérifie qu'une variable est
opérateur Retourne 1 si x est
< strictement inférieure à x<3
d'infériorité stricte inférieur à 3, sinon 0
une valeur
Vérifie qu'une variable est Retourne 1 si x est
opérateur
<= inférieure ou égale à une x<=3 inférieur ou égal à 3,
d'infériorité
valeur sinon 0
Vérifie qu'une variable est Retourne 1 si x est
opérateur de
> strictement supérieure à x>3 supérieur à 3, sinon
supériorité stricte
une valeur 0
Vérifie qu'une variable est Retourne 1 si x est
opérateur de
>= supérieure ou égale à une x>=3 supérieur ou égal à
supériorité
valeur 3, sinon 0
Retourne 1 si x est
opérateur de Vérifie qu'une variable est
!= x!=3 différent de 3, sinon
différence différente d'une valeur
0

Exemple: int x= (3*4)<(4*5); : x vaut 1


   5. LES OPERATEURS
-------------------------------------------------------------------
5.6 Les opérateurs logiques (booléens)
Ce type d'opérateur permet de vérifier si plusieurs conditions sont
vraies. Les opérations logiques considèrent un opérande comme faux si sa valeur est
0 et vrai dans tous les autres cas.

Opérateur Dénomination Effet Syntaxe


|| OU logique Vérifie qu'une des conditions est réalisée ((condition1)||(condition2))
&& ET logique Vérifie que toutes les conditions sont réalisées ((condition1)&&(condition2))
Inverse l'état d'une variable booléenne (retourne
! NON logique (!condition)
la valeur 1 si la variable vaut 0, 0 si elle vaut 1)

Par convention, le résultat de ces opérateurs est 1 (vrai) ou 0 (faux) .


Par exemple, dans le programme suivant, x vaut 1 et y vaut 0 :
int n = 0, m = 10, x, y;
x = (n < 20) && m;
y = !((n > 20) || (m == 10));
   5. LES OPERATEURS
-------------------------------------------------------------------
5.6 Les opérateurs bit à bit
Ce type d'opérateur traite ses opérandes comme des données binaires, plutôt que des
données décimales, hexadécimales ou octales. Ces opérateurs traitent ces données
selon leur représentation binaire mais retournent des valeurs numériques standard dans
leur format d'origine.
Les opérateurs suivants effectuent des opérations bit-à-bit, c'est-à-dire avec des bits de
même poids.
Opérateur Dénomination Effet Syntaxe Résultat
Retourne 1 si les deux bits de même poids sont 9 & 12 (1001 &
& ET bit-à-bit 8 (1000)
à1 1100)
Retourne 1 si l'un ou l'autre des deux bits de 9 | 12 (1001 | 13
| OU bit-à-bit
même poids est à 1 (ou les deux) 1100) (1101)
OU bit-à-bit Retourne 1 si l'un des deux bits de même poids 9 ^ 12 (1001 ^
^ 5 (0101)
exclusif est à 1 (mais pas les deux) 1100)
   5. LES OPERATEURS
-------------------------------------------------------------------
5.7 Les opérateurs de décalage de bits
Ce type d'opérateur traite ses opérandes comme des données binaires d'une longueur
de 32 bits, plutôt que des données décimales, hexadécimales ou octales. Ces
opérateurs traitent ces données selon leur représentation binaire mais retournent des
valeurs numériques standard dans leur format d'origine.
Les opérateurs suivants effectuent des décalages sur les bits, c'est-à-dire qu'ils décalent
chacun des bits d'un nombre de positions vers la gauche ou vers la droite. La première
opérande désigne la donnée sur laquelle on va faire le décalage, la seconde désigne le
nombre de décalages.

Opérateur Dénomination Effet Syntaxe Résultat


Décale les bits vers la gauche (multiplie par 2 à
chaque décalage). Les zéros qui sortent à gauche 6 << 1 12
<< Décalage à gauche
sont perdus, tandis que des zéros sont insérés à (110 << 1) (1100)
droite
Décale les bits vers la droite (divise par 2 à
6 >> 1
Décalage à droite avec chaque décalage). Les zéros qui sortent à droite
>> (0110 >> 3 (0011)
conservation du signe sont perdus, tandis que le bit non nul de poids
1)
plus fort est recopié à gauche
   5. LES OPERATEURS
-------------------------------------------------------------------
5.8 Les priorités
Lorsque l'on associe plusieurs opérateurs, il faut que le programmeur sache
dans quel ordre les traiter. Voici donc dans l'ordre décroissant les priorités de
tous les opérateurs. On spécifie, pour chaque groupe d'opérateurs de priorité
égale, le sens d'évaluation. Opérateurs Évaluation
() [] -> . 
! ~ ++ -- + - * & sizeof 
* / % 
+ - 
<< >> 
< <= > >= 
== != 
& 
^ 
| 
&& 
|| 
?: 
= += -= *= /= %= &= ^= |= <<= >>= 
, 
   5. LES OPERATEURS
-------------------------------------------------------------------
5.8 Les priorités
Un opérateur unaire est toujours plus prioritaire que le même opérateur binaire
: par exemple, l'opérateur - unaire (opposé) est prioritaire sur l'opérateur -
binaire (soustraction).
Le sens d'évaluation spécifie dans quel ordre sont évaluées des expressions
de même niveau de priorité. Par exemple, l'expression :
a = b - c - d; est équivalente à :
a = (b - c) - d; puisque l'opérateur - (binaire) est évalué de gauche à droite.
En revanche, l'expression :
a -= b -= c; est équivalente à :
a -= (b -= c); puisque l'opérateur -= est évalué de droite à gauche.
À tout programmeur (quel que soit son niveau), il est fortement conseillé
d'utiliser les parenthèses pour gérer explicitement l'ordre d'utilisation des
opérateurs plutôt que de se fier à sa connaissance de ce tableau de priorité.
Cela évite de se tromper et rend surtout le programme plus lisible.
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.1 Structure conditionnelle/Structure de boucle
Structure conditionnelle: ce sont des instructions qui permettent de tester si
une condition est vraie ou non.
Ces structures conditionnelles peuvent être associées à des structures qui se
répètent suivant la réalisation de la condition, on appelle ces structures des
structures de boucle ou structure itératives.

Notion de bloc
Une expression suivie d'un point-virgule est appelée instruction.
Exemple d'instruction : a=a+b;

Lorsque l'on veut regrouper plusieurs instructions, on peut créer ce que l'on appelle un
bloc, c'est-à-dire un ensemble d'instructions (suivies respectivement par des points-
virgules) et comprises entre les accolades { et }.
Les instructions if, while et for peuvent par exemple être suivies d'un bloc d'instructions
à exécuter...
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.2 L'instruction if (Structure de choix: instruction SI…ALORS…)
L'instruction if permet d'exécuter une série d'instructions si une condition est
réalisée. La syntaxe de cette expression est la suivante :
if (condition réalisée) { liste d'instructions;}

Remarques :
•la condition doit être entre des parenthèses
•s'il n'y a qu'une instruction, les accolades ne sont pas nécessaires...
•il est possible de définir plusieurs conditions à remplir avec les opérateurs ET
et OU (&& et ||)
Exemple: l'instruction suivante teste si les deux conditions sont vraies :
if ((condition1)&&(condition2))
L'instruction suivante exécutera les instructions si l'une ou l'autre des deux
conditions est vraie :
if ((condition1)||(condition2))
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.3 L'instruction if ….else (instruction SI…ALORS…SINON)
L'instruction if dans sa forme basique ne permet de tester qu'une
condition, or la plupart du temps on aimerait pouvoir choisir les
instructions à exécuter en cas de non réalisation de la condition...
L'expression if ... else permet d'exécuter une autre série d'instructions
en cas de non-réalisation de la condition.
La syntaxe de cette expression est la suivante :
if (condition réalisée)
{ liste d'instructions
}
Else
{ autre série d'instructions
}
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.3 L'instruction if et if … else
Organigrammes :
Instruction if Instruction if …..else

oui  non  oui  non 


condition  condition  
vraie  vraie 

bloc d'  bloc 1 d'  bloc 2 d' 


instructions  instructions  instructions 

suite du programme  suite du programme 
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.4 Autre façon d’écriture du if …else
Il est possible de faire un test avec une structure beaucoup moins lourde
grâce à la structure suivante :

(condition) ? instruction si vrai : instruction si faux

Remarques :
•la condition doit être entre des parenthèses
•Lorsque la condition est vraie, l'instruction de gauche est exécutée
•Lorsque la condition est fausse, l'instruction de droite est exécutée
•En plus d'être exécutée, la structure ?: renvoie la valeur résultant de
l'instruction exécutée. Ainsi, cette forme ?: est souvent utilisée comme suit :
position = ((enAvant == 1) ? compteur+1 : compteur-1);
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.3 L'instruction if ….else
Il est possible d'enchaîner plusieurs tests successifs grâce à else if :

if (condition1)
/* si condition1 est vraie */
instruction
else if (condition2)
/* si condition1 est fausse et condition2 est vraie */
instruction
else
/* si les deux conditions sont fausses */
instruction
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.5 L’instruction switch (structure de choix multiples)
L'instruction switch permet de faire plusieurs tests de valeurs sur le contenu
d'une même variable (instruction AU CAS OU ... FAIRE .. ).
Ce branchement conditionnel simplifie beaucoup le test de plusieurs valeurs
d'une variable, car cette opération aurait été compliquée (mais possible) avec
des if imbriqués. Sa syntaxe est la suivante :
switch (Variable de type char ou int) {
case Valeur1 : Liste d'instructions;
break;
case Valeur2 : Liste d'instructions;
break;
case Valeurs... : Liste d'instructions;
break;
default: Liste d'instructions;
}
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.5 L’instruction switch
Les parenthèses qui suivent le mot clé switch indiquent une
expression dont la valeur est testée successivement par chacun des
case. Lorsque l'expression testée est égale à une des valeurs suivant
un case, la liste d'instructions qui suit celui-ci est exécutée. Le mot clé
break indique la sortie de la structure conditionnelle. Le mot clé
default précède la liste d'instructions qui sera exécutée si l'expression
n'est jamais égale à une des valeurs.

Remarques:
N'oubliez pas d'insérer des instructions break entre chaque test, ce
genre d'oubli est difficile à détecter car aucune erreur n'est signalée...
En effet, lorsque l'on omet le break, l'exécution continue dans les
blocs suivants !
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.5 L’instruction switch
Remarques:
Cet état de fait peut d'ailleurs être utilisé judicieusement afin de faire exécuter
les mêmes instructions pour différentes valeurs consécutives, on peut ainsi
mettre plusieurs cases avant le bloc :

switch(variable) {
case 1:
case 2: { instructions exécutées pour variable = 1 ou pour variable =
2}
break;
case 3: { instructions exécutées pour variable = 3 uniquement }
break;
default: { instructions exécutées pour toute autre valeur de variable }
}
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6 LES BOUCLES
Les boucles sont des structures qui permettent d'exécuter plusieurs
fois la même série d'instructions jusqu'à ce qu'une condition ne soit
plus réalisée...
On appelle parfois ces structures instructions répétitives ou bien
itérations.
La façon la plus commune de faire une boucle est de créer un
compteur (une variable qui s'incrémente, c'est-à-dire qui augmente
de 1 à chaque tour de boucle) et de faire arrêter la boucle lorsque le
compteur dépasse une certaine valeur. Voyons les trois types de
boucles en C:
La boucle for
La boucle while
La boucle do … while
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.1 L’instruction FOR (Instruction Pour)

L'instruction for permet d'exécuter plusieurs fois la même série


d'instructions : c'est une boucle !
Dans sa syntaxe, il suffit de préciser le nom de la variable qui sert de
compteur (et éventuellement sa valeur de départ, la condition sur la
variable pour laquelle la boucle s'arrête (basiquement une condition
qui teste si la valeur du compteur dépasse une limite) et enfin une
instruction qui incrémente (ou décrémente) le compteur.
La syntaxe de cette expression est la suivante :
for (compteur; condition de continuité; modification du compteur)
{liste d'instructions;
}
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.1 L’instruction FOR (Instruction Pour)
Organigramme:

initialisation 

Par exemple :
for (i=1; i<6; i++) {printf(" %d", i);} condition de  
continuité vraie 
Cette boucle affiche 5 fois la valeur de i, non 
oui 
c'est-à-dire 1, 2, 3, 4, 5.
Elle commence à i=1,
bloc d'instructions 
vérifie que i est bien inférieur à 6,
etc. jusqu'à atteindre la valeur i=6,
pour laquelle la condition ne sera
modification 
plus réalisée, suite du programme 

la boucle s'interrompra
et le programme continuera son cours.
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.1 L’instruction FOR (Instruction Pour)
Remarque:

•il faudra toujours vérifier que la boucle a bien une condition de sortie
(i.e. le compteur s'incrémente correctement)
•une instruction printf(); dans votre boucle est un bon moyen pour
vérifier la valeur du compteur pas à pas en l'affichant !
•il faut bien compter le nombre de fois que l'on veut faire exécuter la
boucle :
–for(i=0;i<10;i++) exécute 10 fois la boucle (i de 0 à 9)
–for(i=0;i<=10;i++) exécute 11 fois la boucle (i de 0 à 10)
–for(i=1;i<10;i++) exécute 9 fois la boucle (i de 1 à 9)
–for(i=1;i<=10;i++) exécute 10 fois la boucle (i de 1 à 10)
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.2 L'instruction while (La boucle TANT QUE ... FAIRE ... )
L'instruction while représente un autre moyen d'exécuter plusieurs fois
la même série d'instructions.
La syntaxe de cette expression est la suivante :
while (condition réalisée) { liste d'instructions;}
Cette instruction exécute la liste d'instructions tant que (while est un
mot anglais qui signifie tant que) la condition est réalisée.
Le test se fait d'abord, le bloc d'instructions n'est pas forcément exécuté.
les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une seule
instruction.

Attention:
La condition de sortie pouvant être n'importe quelle structure
conditionnelle, les risques de boucle infinie (boucle dont la condition
est toujours vraie) sont grands, c'est-à-dire qu'elle risque de provoquer
un plantage du programme en cours d'exécution !
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.2 L'instruction while (La boucle TANT QUE ... FAIRE ... )
Organigramme:

Par exemple :
i=1;
while (i<6) oui  non 
condition 
{printf(" %d", i); i++;} vraie 
Cette boucle affiche 5 fois la valeur de i,
c'est-à-dire 1, 2, 3, 4, 5.
Au début i=1, bloc d' 
vérifie que i est bien inférieur à 6, et l’affiche, instructions 
etc. jusqu'à atteindre la valeur i=6,
pour laquelle la condition ne sera
plus réalisée,
la boucle s'interrompra
et le programme continuera son cours.
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.6.3 L'instruction do while (La boucle REPETER … TANT QUE )
L'instruction do … while représente un autre moyen d'exécuter une boucle.
La syntaxe de cette expression est la suivante :
do{liste d'instructions;}
while (expression); bloc d' 
instructions 

non 
condition 
oui  vraie 

suite du programme 

Le test se faisant après, le bloc est exécuté au moins une fois.


Remarque: les {} ne sont pas nécessaires lorsque le bloc ne comporte qu'une
seule instruction.
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.7. Saut inconditionnel (CONTINUE )
Il peut être nécessaire de faire sauter à la boucle une ou plusieurs
valeurs sans pour autant mettre fin à celle-ci.
La syntaxe de cette expression est « continue; »
(cette instruction se place dans une boucle !), on l'associe
généralement à une structure conditionnelle, sinon les lignes situées
entre cette instruction et la fin de la boucle seraient obsolètes.
Exemple : On veut imprimer pour x allant de 1 à 10 la valeur de 1/(x-7)
; Pour x=7, il y aura une erreur. Heureusement, grâce à l'instruction
continue il est possible de traiter cette valeur à part puis de continuer
la boucle !
x=1;while (x<=10) {
if (x == 7) {printf("Division par zéro !"); x++; continue;}
a = 1/(x-7);printf("%f", a); x++;
}
   6. LES INSTRUCTIONS DE CONTRÔLE
-------------------------------------------------------------------
6.7. Arrêt inconditionnel (break )
L'instruction break permet d'arrêter une boucle (for ou bien while) au
cas où on veut arrêter prématurément la boucle, pour une autre
condition que celle précisée dans l'en-tête de la boucle.
Il s'agit, tout comme continue, de l'associer à une structure
conditionnelle, sans laquelle la boucle ne ferait jamais plus d'un tour !
Dans l'exemple de tout à l'heure, par exemple si l'on ne savait pas à
quel moment le dénominateur (x-y) s'annule, il serait possible de faire
arrêter la boucle en cas d'annulation du dénominateur, pour éviter une
division par zéro !
for (x=1; x<=10; x++){
a = x-y; if (a == 0) {printf("Division par 0");break; }
printf("%f", 1/a);
}
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Nous avons déjà vu les types de base disponibles en C. Nous allons
maintenant aborder les types plus complexes que sont les tableaux, les
pointeurs et les structures.

7.1 TABLEAUX
On appelle tableau une variable composée de données de même
type,
type stockée de manière contiguë en mémoire (les unes à la suite
des autres).
Pour déclarer un tableau, il faut donner le type de ses éléments puis son nom
et enfin sa taille entre crochets. Tous les éléments d'un tableau sont
obligatoirement du même type.
Syntaxe: type Nom_du_tableau [Nombre d'éléments];
On peut utiliser des tableaux de dimension 2 ou plus.

Définition de tableaux:
Dans l'exemple suivant, nous définissons deux tableaux de 100
éléments, l'un contenant des float, l'autre des int.
float VecteurA[100];
int VecteurB[100];
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
initialisation d'un tableau
On peut initialiser un tableau dès sa déclaration en lui affectant une
liste de valeurs séparées par des virgules et entourée par des
accolades. L'exemple suivant initialise le tableau toto:
int toto[5] = {4, 6, 8, 12, 20};
– Le nombre de valeurs entre accolades ne doit pas être supérieur au
nombre d'éléments du tableau
– Les valeurs entre accolades doivent être des constantes (l'utilisation de
variables provoquera une erreur du compilateur)
– Si le nombre de valeurs entre accolades est inférieur au nombre
d'éléments du tableau, les derniers éléments sont initialisés à 0
– Il doit y avoir au moins une valeur entre accolades
Un cas particulier est l'initialisation d'un tableau de caractères pour laquelle on
peut utiliser une chaîne de caractères. Les deux lignes suivantes sont
équivalentes :
char Str[20] = {'B', 'o', 'n', 'j', 'o', 'u', 'r'};
char Str[20] = "Bonjour";
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Calcul de la taille du tableau
Etant donné qu'un tableau est composé d'un nombre fixé d'éléments d'un type
donné, la taille d'un tableau est déterminée dès sa définition.
Pour connaître la taille d'un tableau, c'est-à-dire déterminer le nombre d'octets
que celui-ci occupe en mémoire, il y a deux possibilités :
Calculer manuellement la taille du tableau : il suffit de multiplier la taille du
type d'élément par le nombre d'éléments qui composent le tableau
Utiliser l'opérateur sizeof() : l'opérateur sizeof() permet de retourner
directement la taille de l'élément qui lui est passé en argument, ainsi en lui
passant un tableau comme opérande, sizeof() est capable de vous retourner
directement la taille de celui-ci
Voici différents exemples de tableaux, et leurs tailles respectives :
Définition du tableau Taille du tableau (en octets)
char Tableau1[12] 1 * 12 = 12
short int Tableau2[10] 2 * 10 = 20
float Tableau3[8] 4 * 8 = 32
double Tableau4[15] 8 * 15 = 120
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Accès aux valeurs d'un tableau
Pour accéder à un élément du tableau, il faut donner le nom du tableau, suivi
de l'indice de l'élément entre l'opérateur [ ] (crochets) :
Nom_du_tableau[indice ]

Pour un tableau de taille N:


•l'indice du premier élément est 0
•L’indice du dernier élément est (N -1)
•L’indice est toujours positif
•L’indice peut être une expression

Dans l'exemple suivant, on stocke dans le troisième élément de Tab la valeur


du ième élément :
Tab[2] = Tab[i - 1];
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Tableau à N dimensions
Définition
Un tableau multidimensionnel se définit de la manière suivante :
type Nom_du_tableau [a1][a2][a3] ... [aN]
Chaque élément entre crochets désigne le nombre d'éléments dans
chaque dimension.
Le nombre de dimensions n'est pas limité.
Un tableau d'entiers positifs à deux dimensions (3 lignes, 4 colonnes)
se définira avec la syntaxe suivante :
int Tableau [3][4] On peut représenter un tel tableau de la manière
suivante (Tableau [i: ligne][j:colonne]) :
Tableau[0][0] Tableau[0][1] Tableau[0][2] Tableau[0][3]
Tableau[1][0] Tableau[1][1] Tableau[1][2] Tableau[1][3]
Tableau[2][0] Tableau[2][1] Tableau[2][2] Tableau[2][3]
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Initialisation d'un tableau multidimensionnel
L'initialisation d'un tableau multidimensionnel se fait à peu près de la même
façon que pour les tableaux unidimensionnels. Il y a donc plusieurs façons
d'initialiser un tableau multidimensionnel :
1) Initialisation individuelle de chaque élément :
Nom_du_tableau [0][0] = 2; Nom_du_tableau [0][1] = 3;...

2) Initialisation grâce à des boucles :


Il faut faire des boucles imbriquées correspondant chacune à un indice d'une
dimension. Par exemple les éléments de Tableau[3][4] pourront être initialisés
à 0 par les instructions suivantes :
int i,j;
for (i=0; i<=2; i++){
for (j=0; j<=3; j++){Tableau[i][j] = 0;}
}
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
Initialisation d'un tableau multidimensionnel
1) Initialisation à la définition :
type Nom_du_tableau [Taille1][Taille2]...[TailleN] = {a1, a2, ... aN};
Les valeurs sont attribuées aux éléments successifs en incrémentant
d'abord les indices de droite, c'est-à-dire pour un tableau à 2
dimensions : [0][0], [0][1], [0][2] ... puis [1][0] etc.

Accès aux valeurs d'un tableau


Pour accéder à un élément d'un tableau, on utilise l'opérateur [] pour
chaque dimension. La valeur mise entre crochets peut être un calcul.
Exemple :
Tab[2][3] = 10;
Attention: Ne pas utiliser Tab[2,3]
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.2 POINTEURS
Un pointeur contient l'adresse en mémoire d'un objet d'un type
donné. Ainsi, on parle de « pointeur sur int » ou de « pointeur sur
double ». L'utilisation des pointeurs en C est l'un des points les plus
complexes du langage. Mais c'est aussi une fonctionnalité qui rend le
C très puissant surtout si on l'utilise avec les fonctions d‘allocation
dynamique de la mémoire.
Définition de pointeur:
Pour définir un pointeur, on doit écrire le type d'objet sur lequel il
pointera suivi du caractère * pour préciser que c'est un pointeur puis
enfin son nom.
Dans l'exemple suivant, p est défini comme un pointeur sur un double
et q est défini comme un pointeur sur un pointeur sur int :
double * p;
int * * q;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.2 POINTEURS
Attention : dans la définition d'un pointeur, le caractère * est rattaché au nom
qui le suit et non pas au type. Ainsi, dans la définition qui suit, p est bien un
pointeur sur char mais t est simplement une variable de type char. La seconde
ligne, par contre, définit deux pointeurs sur double :
char * p, t;
double * p2, * p3;

Adresse d'un objet


Pour récupérer l'adresse en mémoire d'un objet, on utilise l'opérateur & . Cette
adresse pourra être stockée dans un pointeur. Dans l'exemple suivant, le
pointeur p contient l'adresse en mémoire de la variable car :
char car;
char * p;

p = & car;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.2 POINTEURS
Accès au contenu d'un pointeur
Pour accéder au contenu de l'adresse mémoire pointée par un
pointeur, on utilise l'opérateur * . Ainsi, en continuant l'exemple
précédent, la ligne suivante stockera dans la variable car le caractère
A puisque p pointe sur son adresse en mémoire :
*p = 'A';

Adresses et tableaux
On peut récupérer l'adresse de n'importe quel objet. Par exemple, il
est possible d'obtenir l'adresse d'un élément d'un tableau (dans cet
exemple, le onzième élément) :
double a[20];
double * p;
p = & (a[10]); Par convention, le nom d'un tableau est une constante
égale à l'adresse du premier élément du tableau. En continuant
l'exemple précédent, les deux lignes suivantes sont équivalentes :
p = & a[0];
p = a;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.2 POINTEURS
calculs sur les pointeurs
Il est possible de faire des calculs sur les pointeurs. On peut ajouter ou
soustraire une valeur entière à un pointeur. Dans l'exemple suivant, p pointe à
la fin sur le troisième élément du tableau a (donc sur a[2]) :
double a[20];
double * p;
p = & (a[10]);
p = p - 8;
Pour effectuer ce calcul tous les opérateurs classiques d'addition et de
soustraction sont utilisables en particulier les opérateurs d'incrémentation.
Nous avons vu qu'une chaîne de caractères se terminait toujours par le
caractère de code ASCII 0 (\0). L'exemple suivant permet de compter le
nombre de caractères stockés dans le tableau de caractères str (le caractère
nul ne fait pas partie du compte) :
char * p = str;
int NbCar = 0;
while ( *p != '\0') {
p++;
NbCar++;
}
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.2 POINTEURS
calculs sur les pointeurs (suite)
L'arithmétique des pointeurs en C a cette particularité que l'opération
dépend du type de variable pointée, ajouter 1 consistant à ajouter à
l'adresse la taille de l'objet pointé.
En effet, les calculs sur pointeurs et l'utilisation de l'opérateur [] d'accès à un
élément d'un tableau peuvent être considérés comme équivalent. Sachant que
Tab est un tableau de double, les deux lignes suivantes sont équivalentes :
Tab[45] = 123.456;
*(Tab + 45) = 123.456; Ceci est tellement vrai qu'on peut même utiliser un
pointeur directement comme un tableau.
Les deux écritures suivantes sont donc exactement équivalentes que p soit le
nom d'un pointeur ou celui d'un tableau :
p[i] est équivalent à *(p + i)
On a le même type d'équivalence au niveau des paramètres d'une fonction.
Les deux lignes suivantes déclarent toutes les deux que le paramètre p de la
fonction f est un pointeur sur double :
void f(double * p);
void f(double q[]);
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
En général, les types de base que propose le C ne suffisent pas pour
stocker les données à utiliser dans un programme. Par exemple, il
serait bien embêtant de devoir utiliser deux variables de type double
pour stocker un nombre complexe. Heureusement le C permet de
déclarer de nouveaux types.
Déclaration d'une structure
Une structure possède un nom et est composée de plusieurs
champs. Chaque champ à son propre type et son propre nom. Pour
déclarer un structure on utilise le mot-clé struct :
struct nomStructure {
type1 champ1;
...
typeN champN;
};
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
Voici un exemple qui déclare une structure permettant de stocker un nombre
complexe :
struct complex {
double reel; /* partie reelle */
double imag; /* partie imaginaire */
};
Accès aux champs
A partir de cette déclaration, il est possible d'utiliser ce nouveau type.
L'opérateur . permet d'accéder à l'un des champs d'une structure. En
continuant l'exemple précédent, les lignes suivantes initialisent un complexe à
la valeur (2 + 3i).
struct complex a;

a.reel = 2;
a.imag = 3;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
Utilisation de typedef
Le mot-clé typedef permet d'associer un nom à un type donné.
On l'utilise suivi de la déclaration d'un type (en général une structure
ou une union) puis du nom qui remplacera ce type. Ceci permet, par
exemple, de s'affranchir de l'emploi de struct à chaque utilisation d'un
complexe. Il n'est pas alors nécessaire de donner un nom à la
structure. L'exemple précédent peut donc se réécrire de la manière
suivante :
typedef struct {
double reel; /* partie reelle */
double imag; /* partie imaginaire */
} complexe;
complexe a;
a.reel = 2;
a.imag = 3;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
Initialisation et affectation
Il est possible d'affecter une variable de type structure dans une autre variable
du même type. Le contenu de chacun des champs de la première variable
sera alors recopié dans le champ correspondant de la seconde variable. On
peut initialiser une variable de type structure dès sa définition en lui affectant
une liste de valeurs séparées par des virgules et entourées par des accolades.
complexe a = { 1, 0 }; /* le reel 1 */
complexe b;

b = a;

Il est par contre impossible de comparer ou d'effectuer des calculs entre deux
structures.
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
Exemple de structures imbriquées
On peut imbriquer plusieurs structures. Dans l'exemple suivant nous déclarons
une structure pour stocker une commande d'un client contenant :
la référence du produit commandé (refProd),
une sous-structure (prix) stockant : le prix unitaire hors taxe (HT) et le taux de
TVA associé (TVA),
le nombre d'unités commandées (q),
la remise accordée en pourcentage (remise).
Cette structure se déclare de la manière suivante :
typedef struct {
int refProd; /* reference produit */
struct {
double HT; /* prix hors taxe */
double TVA; /* taux de TVA en pourcentage */
} prix;
int q; /* quantite commandee */
double remise; /* remise en pourcentage */
} commande;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
Exemple de structures imbriquées(suite)

Pour accéder aux champs de la sous-structure, il faut utiliser deux fois


l'opérateur . d'accès aux champs. En supposant que com (commande com;)
contienne une telle commande, voici le calcul du prix total :

double P_TTC, P_AvantRemise, P_Total;

P_TTC = com.prix.HT * (1 + com.prix.TVA / 100);

P_AvantRemise = P_TTC * com.q;

P_Total = P_AvantRemise – (P_AvantRemise * com.remise / 100);


  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.3 STRUCTURES (struct)
les pointeurs sur structures
L'utilisation de pointeurs sur structures est très courante en C. Voici
un exemple d'utilisation d'un pointeur sur un complexe :
complexe a = { 3.5, -5.12 }; complexe * p = &a;
(*p).reel = 1;
(*p).imag = -1; /* a vaut (1 - i) */
Nous avons été obligé de mettre des parenthèses autour de *p car
l'opérateur . est plus prioritaire que l'opérateur * . Cela rend difficile la
lecture d'un tel programme. Heureusement, l'utilisation de pointeurs
sur structures est si courante que le C définit l'opérateur -> pour
accéder aux champs d'une structure via un pointeur. Les deux
expressions suivantes sont donc équivalentes :
(*pointeur).champ équivalent à pointeur->champ
Ainsi l'exemple précédent s'écrit beaucoup plus facilement de la
manière suivante :
complexe a = { 3.5, -5.12 };
complexe * p = &a;
p->reel = 1;
p->imag = -1; /* a vaut (1 - i) */
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.4 STRUCTURES (union)
les unions
Les unions se déclarent de la même manière que les structures.
union nom_type {déclaration des champs} liste_variables ;
Elles possèdent donc elles aussi des champs typés. Mais on ne peut
utiliser qu'un seul champ à la fois.
En fait tous les champs d'une union se partagent le même espace
mémoire. Les unions sont rarement nécessaires sauf lors de la
programmation système.
Les champs peuvent être de tout type, y compris structures. On les
utilise comme les structures, avec les opérateurs "." et "->".
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.4 STRUCTURES (union)
Exemple
Supposons que l'on désire écrire un package mathématique qui manipulera
des nombres qui seront implémentés par des int, tant que la précision des
entiers de la machine sera suffisante, et qui passera automatiquement à une
représentation sous forme de réels dès que ce ne sera plus le cas. Il sera
nécessaire de disposer de variables pouvant prendre soit des valeurs entières,
soit des valeurs réelles.
Ceci peut se réaliser en C, grâce au mécanisme des unions. ex:
union nombre
{
int i;
float f;
}
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.4 STRUCTURES (union)
Exemple: les unions
Dans l'exemple précédent, si on déclare la variable n comme étant de type
union nombre par:
union nombre n;
cette variable pourra posséder soit une valeur entière, soit une valeur réelle,
mais pas les deux à la fois.
Accès aux champs de l'union
Cet accès se fait avec le même opérateur sélection (note .) que celui qui sert a
accéder aux champs des structures.
Dans l'exemple précèdent, si on désire faire posséder à la variable n une
valeur entière, on pourra écrire:
n.i = 10;
si on désire lui faire posséder une valeur réelle, on pourra écrire:
n.f = 3.14159;
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.4 Les opérateurs sur les pointeurs, tableaux et
structures
Le tableau suivant récapitule les cinq opérateurs que nous avons vu sur les
pointeurs, tableaux et structures.

Opérateurs Signification
[] (binaire) accès à un élément d'un tableau
& (unaire) adresse de
* (unaire) contenu de
-> (binaire) accès à un champs pointé par
. (binaire) accès à un champs
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.5 Allocation dynamique de mémoire
La taille déclarée d'un tableau est définie à la compilation.
Dans le cas d'une taille inconnue à l'avance, il faut surdimensionner le
tableau (et donc réserver des mémoires dont on ne servira que
rarement, aux dépends d'autres variables ou tableaux).

C'est pour cela qu'on les appelle des tableaux statiques.


En C, le lien entre les tableaux et pointeurs permet la notion de
tableaux dynamiques : on peut définir la dimension d'un tableau lors
de l'exécution. Il faut d'abord réserver une zone de mémoire contiguë,
de la taille désirée (mais pas plus). Il faut avoir déclaré une variable
pointeur qui contiendra l'adresse du début du tableau.
A l'exécution, lorsque l'on connaît la taille désiré, on peut réserver une
zone mémoire (dans la zone appelée "tas" ou "heap") par les
fonctions :
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.5 Allocation dynamique de mémoire
- void *malloc(int taille) : réserve une zone mémoire contiguë de taille octets,
et retourne un pointeur sur le début du bloc réservé. Retourne le pointeur
NULL en cas d'erreur (en général car pas assez de mémoire).
-void *calloc(int nb, int taille) : équivalent à malloc(nb*taille).
Exemple : float *tab;int nb;
puts("taille désirée ?"); scanf("%d",&nb);
tab=(float*)calloc(nb,sizeof(float));
malloc et calloc nécessitent un cast pour que le compilateur ne signale
pas d'erreur.
- void free(void *pointeur) libère la place réservée auparavant par
malloc ou calloc. Pointeur est l'adresse retournée lors de l'allocation.
En quittant proprement le programme, la mémoire allouée est
automatiquement restituée même si on omet d'appeler free.
Ces fonctions sont définies dans stdlib.h ou alloc.h (suivant le
compilateur).
  7. TABLEAUX, POINTEURS ET STRUCTURES

-------------------------------------------------------------------
7.5 Allocation dynamique de mémoire
Une fois la zone de mémoire réservée, on peut y accéder soit par
"l'écriture pointeurs" soit par "l'écriture tableaux", puisqu'elles sont
équivalentes. Pour le dernier exemple :

Premier élément : *tab ou tab[0]


Pour I’iéme élément : *(tab+i) ou tab[i]
Adresse du iéme élément (pour scanf par exemple) : tab+i ou &(tab[i])

Une erreur fréquente consiste à "perdre" l'adresse du début de la


zone allouée (par tab=quelque chose, ou parce que tab était une
variable locale qui ne vit plus) et donc il devient alors impossible
d'accéder au début de la zone, ni de la libérer.
  8. LES FONCTIONS
-------------------------------------------------------------------
8.1 La notion de fonction
On appelle fonction un sous-programme qui permet d'effectuer un
ensemble d'instructions par simple appel de la fonction.
Les fonctions permettent d'exécuter dans plusieurs parties du
programme une série d'instructions, cela permet une simplicité du
code et donc une taille de programme minimale.

La définition d'une fonction


Avant d'être utilisée, une fonction doit être définie car pour l'appeler
dans le corps du programme, il faut que le compilateur la connaisse,
c'est-à-dire qu'il connaisse son nom, ses arguments et les instructions
qu'elle contient.

La définition d'une fonction se fait selon la syntaxe suivante :


type_de_donnee Nom_De_La_Fonction (type1 argument1, type2
argument2, ...)(pas de ;)
{
liste d'instructions
}
  8. LES FONCTIONS
-------------------------------------------------------------------
Exemple:
Voici, par exemple, la définition d'une fonction qui calcule la moyenne
de deux nombres :
double moyenne ( double a, double b )
{ return( (a + b) / 2); }

Remarques :
•type_de_donnee représente le type de valeur que la fonction est
sensée retourner

•Si la fonction ne renvoie aucune valeur, on la fait alors précéder du


mot-clé void

•Si aucun type de donnée n'est précisé(cela n’est pas bon!), le type
int est pris par défaut
  8. LES FONCTIONS
-------------------------------------------------------------------
•Le nom de la fonction suit les mêmes règles que les noms de
variables
–le nom doit commencer par une lettre
–un nom de fonction peut comporter des lettres, des chiffres et les
caractères _ et & (les espaces ne sont pas autorisés !)
–le nom de la fonction, comme celui des variables est sensible à la casse
(différenciation entre les minuscules et majuscules)

•Les arguments sont facultatifs, mais s'il n'y a pas d'arguments, les
parenthèses doivent rester présentes

•Il ne faut pas oublier de refermer les accolades


-Le nombre d'accolades ouvertes (fonction, boucles et autres
structures) doit être égal au nombre d'accolades fermées !
-La même chose s'applique pour les parenthèses, les crochets ou les
guillemets !

•Une fois cette étape franchie, votre fonction ne s'exécutera pas tant
que l'on ne fait pas appel à elle quelque part dans le programme!
  8. LES FONCTIONS
-------------------------------------------------------------------
Retour du résultat
Le mot-clé return est suivi d'une expression. La valeur de cette expression
sera le résultat de la fonction. La dernière instruction d'une fonction doit être
une instruction return permettant de renvoyer le résultat.
Il est possible d'utiliser return n'importe où et plusieurs fois dans une fonction.
La fonction s'arrêtera immédiatement et le résultat sera renvoyé.
Néanmoins, dans le cadre d'une programmation structurée, l'instruction return
ne devrait apparaître que comme dernière instruction sauf si cela est
nécessaire.
La syntaxe de l'instruction return est simple : : return (valeur_ou_variable);
Le type de valeur retourné doit correspondre à celui qui a été précisé dans la
définition (et le prototype).
Appel d'une fonction
Pour appeler une fonction, il suffit de mettre son nom suivi de la liste des
valeurs à donner aux paramètres entre parenthèses.
Un appel de fonction est considérée comme une expression du type du
résultat de la fonction et la valeur de cette expression est le résultat de
l'exécution de la fonction. Dans l'exemple suivant, c contiendra la valeur
moyenne de 30 et 75 :
c = moyenne(30, 75);
  8. LES FONCTIONS
-------------------------------------------------------------------
Type du résultat de la fonction
Le type de la valeur retournée par une fonction peut être n'importe quel type
(un type de base ou même une structure). La fonction suivante calcule la
somme de deux nombres complexes :
complexe AddComplexe(complexe op1, complexe op2) {
complexe somme;
somme.reel = op1.reel + op2.reel;
somme.imag = op1.imag + op2.imag;
return (somme);
}

Le type void permet de spécifier que la fonction ne renvoie aucun résultat.


Dans ce cas, pour terminer l'exécution de la fonction, on peut utiliser le mot-
clé return seul ou plus simplement atteindre la fin des instructions.
Le type void mit seul à la place de la liste des arguments permet aussi de
spécifier que la fonction ne prend aucun argument. Voici une fonction qui ne
fait qu'afficher un message sur la sortie standard :
void AffMessage(void) {
printf("Voici un message\n");
}
  8. LES FONCTIONS
-------------------------------------------------------------------
Corps de la fonction
On appelle corps de la fonction le bloc d'instructions qui commence
après l'accolade ouvrante qui suit la liste des paramètres et qui se
termine par l'accolade fermante correspondante.

Comme tout autre bloc, le corps de la fonction peut débuter par une
série de définitions de variables. Ces variables sont appelées
variables locales. Chaque appel de la fonction crée de nouvelles
instances des variables locales.

Les fonctions C sont réentrantes. Cela signifie qu'elles peuvent être


appelées récursivement (voir plus loin).
  8. LES FONCTIONS
-------------------------------------------------------------------
Paramètres d'une fonction (Arguments)
Il n'y a théoriquement pas de limite au nombre de paramètres.
Chaque paramètre doit être défini par son type suivi de son nom. Comme pour
le type du résultat, le type d'un paramètre peut être soit un type de base soit
une structure.
Passage par valeur
Les paramètres peuvent être considérés comme des variables locales à la
fonction.
Lors de l'appel de la fonction, la valeur de chaque paramètre est recopiée
dans un nouvel espace mémoire réservé pour ce paramètre.
Une fonction peut donc localement modifier le contenu de ses paramètres. Les
valeurs utilisées lors de l'appel ne seront absolument pas modifiées.
Dans l'exemple suivant, la variable a à la fin de la fonction f reste égale à 1 :

void g (int param) { param = 150;}


void f (void)
{ int a = 1;
g(a);
}
  8. LES FONCTIONS
-------------------------------------------------------------------
Utilisation des pointeurs comme paramètres
Le passage des paramètres par valeur ne permet donc pas de modifier une
variable de la fonction appelante.
Pour pouvoir la modifier, Il faut envoyer non pas la valeur d'une variable mais
son adresse en mémoire (c'est à dire un pointeur sur cette variable).

La fonction appelée peut alors modifier le contenu de cet emplacement


mémoire (et donc le contenu de la variable elle-même).
Voici une fonction qui divise une variable de type int par un diviseur. Le
résultat de la fonction est le reste de cette division. Le premier paramètre est
un pointeur sur la variable à diviser et le second paramètre est le diviseur :

int DiviseEtReste(int * val, int diviseur) {


int reste = (*val) % diviseur;
*val /= diviseur;
return reste;
}
Ex: *val=7 , diviseur=3, reste=7%3=1 car 7=3* 2 +1
*val=7/3=2
Valeur retournée DiviseEtReste=reste=1 et la variable pointée par val a été
modifiée de 7 à 2
  8. LES FONCTIONS
-------------------------------------------------------------------
Utilisation des pointeurs comme paramètres
On utilise aussi souvent des pointeurs pour éviter de recopier des grosses
structures ou pour travailler sur des tableaux de valeurs. Voici, par exemple,
une fonction permettant de calculer la moyenne des valeurs stockées dans un
tableau. Le premier paramètre est un pointeur sur le tableau et le second est
le nombre de valeurs stockées :
double MoyenneTableau(double *Tab, int nbVal) {
double somme = 0;
int indice;
for (indice = 0; indice < nbVal; indice++) {
somme += Tab[indice];
}
return somme / nbVal;
}
Pour utiliser cette fonction, on peut l'appeler de la manière suivante :
void f(void) {
double Tableau[1000];
double moyenne;
/* initialisation des valeurs de Tableau */
...
moyenne = MoyenneTableau(Tableau, 1000);
...
}
  8. LES FONCTIONS
-------------------------------------------------------------------
La fonction main
La fonction dont le nom est main est une fonction particulière dans un
programme C. C'est elle qui est exécutée en premier lorsqu'on lance un
programme. Le programme s'arrête lorsque l'exécution de cette fonction se
termine.

Elle peut être définie de différentes manières. Un programme simple définit


main de la manière suivante :
int main(void) {
...
}
Le type de main est int afin de permettre de retourner au système
d'exploitation un code d'erreur (0 si tout se passe bien).
  8. LES FONCTIONS
-------------------------------------------------------------------
Prototype d'une fonction
•Le prototype d'une fonction est une description d'une fonction qui est définie
plus loin dans le programme. On place donc le prototype en début de
programme (avant la fonction principale main()).
•Cette description permet au compilateur de « vérifier » la validité de la
fonction à chaque fois qu'il la rencontre dans le programme, en lui indiquant :
Le type de valeur renvoyée par la fonction
Le nom de la fonction
Les types d'arguments
•Contrairement à la définition de la fonction, le prototype n'est pas suivi du
corps de la fonction (contenant les instructions à exécuter), et ne comprend
pas le nom des paramètres (seulement leur type).
• Un prototype de fonction ressemble donc à ceci :
Type_de_donnee_renvoyee Nom_De_La_Fonction(type_argument1,
type_argument2, ...); Le prototype est une instruction, il est donc suivi d'un
point-virgule !Voici quelques exemples de prototypes :
void Affiche_car(char, int);int Somme(int, int);
  8. LES FONCTIONS
-------------------------------------------------------------------
Récursivité
Comme tout autre bloc, le corps de la fonction peut débuter par une série de
définitions de variables. Ces variables sont appelées variables locales.
Chaque appel de la fonction crée de nouvelles instances des variables
locales.

Les fonctions C sont réentrantes. Cela signifie qu'elles peuvent être appelées
récursivement.
La suite de Fibonacci se définit récursivement de la manière suivante :

Fib(0)=1 et Fib (1)=1 et Fib (n)= Fib (n-1)+ Fib (n-2)


La fonction C suivante permet de calculer Fib(n):

unsigned long Fib(unsigned long n) {


unsigned long resultat;
if (n < 2L) { resultat = 1L;
} else {
resultat = Fib(n - 1) + Fib(n - 2);
}
return resultat;
  8. LES FONCTIONS
-------------------------------------------------------------------
Déclaration et stockage des variables
Une variable doit être définie par le programmateur dans une déclaration, où
l'on indique le nom que l'on désire lui donner, son type (int, float,...) pour que
le compilateur sache combien de mémoire il doit lui réserver et les opérateurs
qui peuvent lui être associés, mais aussi comment elle doit être gérée
(visibilité, durée de vie,...).

Déclarations locales
Dans tout bloc d'instructions, avant la première instruction, on peut déclarer
des variables. Elles seront alors "locales au bloc" :elles n'existent qu'à
l'intérieur du bloc. Ces variables sont mises en mémoire dans une zone de
type "pile" : quand, à l'exécution, on arrive sur le début du bloc ({), on réserve
la mémoire nécessaire aux variables locales au sommet de la pile (ce qui en
augmente la hauteur), et on les retire en quittant le bloc.
Cette période est appelée sa durée de vie. Mais pendant sa durée de vie, une
variable peut être visible ou non. Elle est visible : dans le texte source du bloc
d'instruction à partir de sa déclaration jusqu'au }, mais tant qu'une autre
variable locale de même nom ne la cache pas.
Par contre elle n'est pas visible dans une fonction appelée par le bloc (puisque
son code source est hors du bloc).
  8. LES FONCTIONS
-------------------------------------------------------------------
La notion de portée d'un nom
La portée d'un nom représente la région (ou les régions) dans le
programme source où un nom est connu du compilateur.

Les fonctions définies dans un fichier source C sont visibles (et donc
utilisables) dans tout le programme sauf si leur définition est précédée
du mot-clé static. Dans ce dernier cas, la fonction n'est visible que
dans le fichier source la contenant.

Les variables définies à l'extérieur de toutes les fonctions (et donc à


l'extérieur de tous les blocs) sont appelées des variables globales.
Elles sont visibles dans tout le programme sauf si leur définition est
précédée du mot-clé static. Dans ce cas, la variable n'est utilisable
que dans le fichier source la contenant.
  8. LES FONCTIONS
-------------------------------------------------------------------
Exemple :
#include <stdio.h>
int doubl(int b) {int c; c=2*b; b=0; return(c); }
int main(void) { int a=5; printf("%d %d\n",doubl(a),a); }

A l'entrée du bloc main, création de a, à qui l'on donne la valeur 5.


Puis appel de doubl : création de b au sommet de la pile, on lui donne la
valeur de a.
Puis entrée dans le bloc, création sur la pile de c, on lui donne la valeur
b*2=10, on annule b (mais pas a), on rend 10 à la fonction appelante, et on
libère le sommet de la pile (c et b n'existent plus) mais a reste (avec son
ancienne valeur) jusqu'à la sortie de main.
On affichera donc : 10 5.
  8. LES FONCTIONS
-------------------------------------------------------------------
Autre Exemple :
int main(void);
{int a=1; [1] [1] a=1
{int b=2; [2] [2] a=1 | b=2
{int a=3; [3] [3] a=1 | b=2 | a=3 : seul le a le plus haut est visible (a=3),
l'autre vit encore (valeur 1 gardée) mais n'est plus visible.

fonction(a); [4] [4a] a=1 | b=2 | a=3 | b=3 : entrée dans la fonction, recopie de
l'argument réel (a) dans l'argument formel (b). Mais a n'est plus
visible.
[4b] a=1 | b=2 | a=3 | b=3 | c=0
[4c] a=1 | b=2 | a=3 | b=3 | c=11 : quand le compilateur cherche
la valeur de b, il prend la plus haute de la pile donc 3 (c'est la seule
visible), met le résultat dans le c le plus haut. L'autre b n'est pas modifié.
[4d] a=1 | b=2 | a=3 : suppression des variables locales b et c
du sommet de la pile
} [5] a=1 | b=2 : sortie de bloc donc libération de la pile
fonction(a); [6] [6a] a=1 | b=2 | b=1 : l'argument réel (a) n'est plus le même qu'en [4a]
[6b] a=1 | b=2 | b=1 | c=0
[6c] a=1 | b=2 | b=1 | c=9
[6d] a=1 | b=2 : suppression b et c
} [7] a=1
} [8] la pile est vide, on quitte le programme

int fonction (int b) [a]


{int c=0; [b]
c=b+8; [c]
} [d]
  8. LES FONCTIONS
-------------------------------------------------------------------
La classe peut être :
•auto (ou omise, c'est la classe par défaut pour les variables locales) :
la variable est créée à l'entrée du bloc (dans la pile) et libérée
automatiquement à sa sortie (comme expliqué plus haut).
•register : la variable est créée, possède la même durée de vie et
visibilité qu'une classe auto, mais sera placée dans un registre du
(micro)processeur. Elle sera donc d'un accès très rapide.. les
compilateurs optimisés choisissent de mettre en registre des variables
auto, et souvent de manière plus pertinente que vous.
•static : la variable ne sera pas dans la pile mais dans la même zone
que le code machine du programme. Sa durée de vie sera donc celle
du programme. Elle ne sera initialisée qu'une fois, au début du
programme, et restera toujours réservée. En retournant dans un bloc,
elle possédera donc encore la valeur qu'elle avait à la précédente
sortie. Sa visibilité reste la même (limitée au bloc). Une variable
statique permet en général un gain en temps d'exécution contre une
perte en place mémoire.
  8. LES FONCTIONS
-------------------------------------------------------------------
La déclaration de variables

Pour faire juste une déclaration d'une variable qui sera définie plus
tard ou dans un autre fichier source, il faut précéder la définition du
mot-clé extern.

Ainsi, les deux lignes suivantes déclarent que a et b existent sans leur
réserver d'espace en mémoire :

extern char a[100];


extern double *b;

À partir du moment où ces déclarations sont faites, le compilateur peut


utiliser a et b puisqu'il connaît leur type.
  8. LES FONCTIONS
-------------------------------------------------------------------
Déclarations globales
Une déclaration faite à l'extérieur d'un bloc d'instructions (en général
en début du fichier) est dite globale. La variable est stockée en
mémoire statique, sa durée de vie est celle du programme. Elle est
visible de sa déclaration jusqu'à la fin du fichier. Elle sera initialisée
une fois, à l'entrée du programme (initialisée à 0 si pas d'autre
précision). Le format d'une déclaration globale est identique à une
déclaration locale, seules les classes varient.
Par défaut, la variable est publique, c'est à dire qu'elle pourra même
être visible dans des fichiers compilés séparément (et reliés au link).
La classe static, par contre, rend la visibilité de la variable limitée au
fichier actuel.
La classe extern permet de déclarer une variable d'un autre fichier (et
donc ne pas lui réserver de mémoire ici, mais la rendre visible). Elle
ne doit pas être initialisée ici. Une variable commune à plusieurs
fichiers devra donc être déclarée sans classe dans un fichier (et y être
initialisée), extern dans les autres.
  8. LES FONCTIONS
-------------------------------------------------------------------
Exemples de déclarations globales :

int i,j; /* publiques, initialisées à 0 */


static int k=1; /* privée, initialisée à 1 */
extern int z; /*déclarée (et initialisée) dans un autre fichier */
float produit(float,float); /* prototype d'une fonction définie plus loin dans
ce fichier */
extern void échange(int *a, int *b); /* prototype d'une fonction définie
dans un autre fichier */
  8. LES FONCTIONS
-------------------------------------------------------------------
Déclaration de type
La norme ANSI permet de définir de nouveaux types de variables par
typedef.
structure : typedef type_de_base nouveau_nom;
Ceci permet de donner un nom à un type donné, mais ne crée aucune
variable. Une déclaration typedef est normalement globale et publique.
exemple :
typedef long int entierlong; /* définition d'un nouveau type */
entierlong i; /* création d'une variable i de type entierlong */
typedef entierlong *pointeur; /* nouveau type : pointeur = pointeur
d'entierlong */
pointeur p; /* création de p (qui contiendra une adresse), peut être
initialisé par =&i */
Remarques : Le premier typedef pouvait être remplacé par un #define
mais pas le second. L'utilisation du typedef permet de clarifier les
programmes, puisqu'on peut définir un nom de type pour déclarer des
variables dont la fonction sera clairement détaillée :
typedef float prix; typedef float quantite; prix a,b,c;
quantite x,y;
  8. LES FONCTIONS
-------------------------------------------------------------------
Les bibliothèques standards
En C, il n'existe aucune commande spécifique pour faire
communiquer le programme avec l'extérieur. On utilise des fonctions
externes fournies par le système sur lequel le programme doit
fonctionner.
La norme C impose que tous les compilateurs fournissent un certain
nombre de fonctions standards dont le fonctionnement et les
paramètres sont définis par la norme. Chaque système peut proposer
ses propres fonctions spécifiques en plus des fonctions standards.
Dans ces fonctions standards, on trouve entre autre:
•des fonctions de calcul mathématique (log, cos, sin, sqrt, etc.)
•des fonctions d'entrées/sorties (printf, fprintf, scanf, fscanf, getc, putc,
etc.)
•des fonctions d'accès aux fichiers (fopen, fclose, fread, fwrite, etc.)
•des fonctions de manipulation de chaînes de caractères (strlen,
strcpy, strcat, etc.)
•des fonctions de gestion de la mémoire (malloc, free, calloc, etc.).
  9. LES FICHIERS
-------------------------------------------------------------------
Etude des fonctions permettant au programme
d'échanger des informations avec des "fichiers".

Fichier: un ensemble d'informations situé sur une


"mémoire de masse" telle que le disque ou la disquette.

En C: tous les périphériques, qu'ils soient d'archivage


(disque, disquette,...) ou de communication (clavier,
écran, imprimante,...), peuvent être considérés comme
des fichiers.

Ainsi, en définitive, les entrées-sorties


conversationnelles apparaîtront comme un cas
particulier de la gestion de fichiers.
  9. LES FICHIERS
-------------------------------------------------------------------
on distingue traditionnellement deux techniques de
gestion de fichiers :

- l'accès séquentiel consiste à traiter les informations


"séquentiellement", c'est-à-dire dans l'ordre où elles
apparaissent (ou apparaîtront) dans le fichier,

-l'accès direct consiste à se placer immédiatement sur


l'information souhaitée, sans avoir à parcourir celles
qui la précèdent.

-la distinction entre accès séquentiel et accès direct n'a


plus véritablement de raison d'être.
  9. CRÉATION SÉQUENTIELLE D'UN FICHIER
-------------------------------------------------------------------
Voici un programme qui se contente d'enregistrer
séquentiellement dans un fichier une suite de nombres entiers
qu'on lui fournit au clavier.

#include <stdio.h>
main(){
char nomfich[21] ; int n ;
FILE * sortie ;
printf ("nom du fichier à créer : ") ;
scanf ("%20s", nomfich) ;
sortie = fopen (nomfich, "w") ;
do{ printf ("donnez un entier : ") ;
scanf ("%d", &n) ;
if (n) fwrite (&n, sizeof(int), 1, sortie) ;
}while (n) ;
fclose (sortie) ;
}
  9. CRÉATION SÉQUENTIELLE D'UN
FICHIER
-------------------------------------------------------------------
nomfich : tableau de caractères destiné à contenir, sous forme
d'une chaîne, le nom du fichier que l'on souhaite créer.
FILE * sortie ;
signifie que sortie est un pointeur sur un objet de type FILE. C’est
un modèle de structure défini dans le fichier stdio.h (par une
instruction typedef, ce qui explique l'absence du mot struct).

La fonction fopen est ce que l'on nomme une fonction d'ouverture


de fichier. Elle possède deux arguments :
-le nom du fichier concerné, fourni sous forme d'une chaîne de
caractères; (chemin,répertoire,...) permettant de préciser l'endroit
où se trouve le fichier.
--une indication, sous forme d'une chaîne, précisant les options
d’ouverture. Ici, on trouve w(abréviation de write) qui permet de
réaliser une "ouverture en écriture". Plus précisément, si le fichier
cité n'existe pas, il sera créé par fopen. S'il existe déjà, son ancien
contenu deviendra inaccessible. Autrement dit, après l'appel de
cette fonction, on se retrouve dans tous les cas en présence d'un
fichier "vide".
  9. CRÉATION SÉQUENTIELLE D'UN
FICHIER
-------------------------------------------------------------------
Le remplissage du fichier est réalisé par la répétition de
l'appel :
fwrite (&n, sizeof(int), 1, sortie) ;

La fonction fwrite possède quatre arguments précisant :


- l'adresse d'un bloc d'informations (ici &n),
- la taille d'un bloc, en octets : ici sizeof(int) ; notez l'emploi
de l'opérateur sizeof qui assure la portabilité du programme,
- le nombre de blocs de cette taille que l'on souhaite
transférer dans le fichier (ici 1),
-l'adresse de la structure décrivant le fichier (sortie).

Enfin, la fonction fclose réalise ce que l'on nomme une


"fermeture" de fichier. Elle force l'écriture sur disque du
tampon associé au fichier.
  9. LISTE SÉQUENTIELLE D'UN FICHIER
-------------------------------------------------------------------
Voici maintenant un programme qui permet de lister le contenu
d'un fichier quelconque tel qu'il a pu être créé par le programme
précédent.

#include <stdio.h>
main(){
char nomfich[21] ;int n ;
FILE * entree ;
printf ("nom du fichier à lister : ") ;
scanf ("%20s", nomfich) ;
entree = fopen (nomfich, "r") ;
while ( fread (&n, sizeof(int), 1, entree), ! feof(entree) )
printf ("\n%d", n) ;
fclose (entree) ;
}
  9. LISTE SÉQUENTIELLE D'UN FICHIER
-------------------------------------------------------------------
On trouve cette fois, dans l'ouverture du fichier, l'indication r
(abréviation de read). Elle précise que le fichier en question ne
sera utilisé qu'en lecture. Il est donc nécessaire qu'il existe déjà
(nous verrons un peu plus loin comment traiter convenablement le
cas où il n'existe pas).

La lecture dans le fichier se fait par un appel de la fonction fread :


fread (&n, sizeof(int), 1, entree)
dont les arguments sont comparables à ceux de fwrite. Mais, cette
fois, la condition d'arrêt de la boucle est :
feof (entree)

Celle-ci prend la valeur vrai (c'est-à-dire 1) lorsque la fin du fichier


a été rencontrée. Notez bien qu'il n'est pas suffisant d'avoir lu le
dernier octet du fichier pour que cette condition prenne la valeur
vrai. Il est nécessaire d'avoir tenté de lire au-delà ; c'est ce qui
explique que nous ayons examiné cette condition après l'appel de
fread et non avant.
  9. L'ACCÈS DIRECT
-------------------------------------------------------------------
Les fonctions fread et fwrite lisent ou écrivent un certain nombre
d'octets dans un fichier, à partir d'une "position courante".
Cette dernière n'est rien d'autre qu'un "pointeur" dans le fichier,
c'est-à-dire un nombre précisant le rang du prochain octet à lire ou
à écrire.
Après chaque opération de lecture ou d'écriture, ce pointeur se
trouve incrémenté du nombre d'octets transférés. C'est ainsi que
l'on réalise un accès séquentiel au fichier.
Mais il est possible d'agir directement sur ce pointeur de fichier à
l'aide de la fonction fseek.
Cela permet ainsi de réaliser des lectures ou des écritures en
n'importe quel point du fichier, sans avoir besoin de parcourir
toutes les informations qui précèdent.
On peut ainsi réaliser ce que l'on nomme généralement un "accès
direct".
  9. L'ACCÈS DIRECT
-------------------------------------------------------------------
#include <stdio.h>
main()
{ char nomfich[21] ;
int n ;
long num ;
FILE * entree ;
printf ("nom du fichier à consulter : ") ;
scanf ("%20s", nomfich) ;
entree = fopen (nomfich, "r") ;
while ( printf (" numéro de l'entier recherché : "),
scanf ("%ld", &num), num )
{ fseek (entree, sizeof(int)*(num-1), SEEK_SET) ;
fread (&n, sizeof(int), 1, entree) ;
printf (" valeur : %d \n", n) ;
}
fclose (entree) ;
}
  9. L'ACCÈS DIRECT
-------------------------------------------------------------------
fseek ( entree, sizeof(int)*(num-1), SEEK_SET) ;
Avec trois arguments :
- le fichier concerné (désigné par le pointeur sur une structure de type
FILE, tel qu'il a été fourni par fopen),
- un entier de type long spécifiant la valeur que l'on souhaite donner au
pointeur de fichier. Il faut noter que l'on dispose de trois manières d'agir
effectivement sur le pointeur, le choix entre les trois étant fait par
l'argument suivant,
- le choix du mode d'action sur le pointeur de fichier : il est défini par une
constante entière. Les valeurs suivantes sont prédéfinies dans <stdio.h> :
* SEEK_SET (en général 0) : désigne un déplacement (en octets) depuis le
début du fichier.
* SEEK_CUR (en général 1) : désigne un déplacement exprimé à partir de
la position courante ; il s'agit donc en quelque sorte d'un déplacement
relatif dont la valeur peut, le cas échéant, être négative.
•SEEK_END (en général 2) : désigne un déplacement depuis la fin du
fichier.
La "formule" : sizeof(int) * (num-1)
se justifie par le fait que nous nous sommes convenu que, pour
l'utilisateur, le premier entier du fichier porterait le rang 1 et non 0.
  9. Tentative de positionnement hors fichier
-------------------------------------------------------------------
Lorsque l'on accède ainsi directement à l'information d'un fichier,
le risque existe de tenter de se positionner en dehors du fichier.
En principe, la fonction fseek fournit :
- la valeur 0 lorsque le positionnement s'est déroulé correctement,
- une valeur quelconque dans le cas contraire.
Toutefois, beaucoup d'implémentations ne respectent pas la
norme à ce sujet. Dans ces conditions, il faut programmer une
protection efficace en déterminant, en début de programme, la
taille effective du fichier à consulter. Pour cela, il suffit de vous
positionner en fin de fichier avec fseek, puis de faire appel à la
fonction ftell qui vous restitue la position courante du pointeur de
fichier. Ainsi, dans notre précédent programme, nous pourrions
introduire les instructions :
long taille ;
.....
fseek (entree, 0, SEEK_END) ;
taille = ftell (entree) ;
Il suffit alors de vérifier que la position de l'enregistrement
demandé (ici : sizeof(int)*(num-1)) est bien inférieure à la valeur de
taille pour éviter tout problème.
  9. LES ENTRÉES-SORTIES FORMATÉES ET
LES FICHIERS DE TEXTE
-------------------------------------------------------------------
fread et fwrite réalisent un transfert d'information (entre mémoire
et fichier) que l'on pourrait qualifier de "brut« : sans aucune
transformation de l'information.
Les octets qui figurent dans le fichier sont des "copies
conformes" de ceux qui apparaissent en mémoire.
Mais, en langage C, il est également possible d'accompagner ces
transferts d'information d'opérations de "formatage" analogues à
celles que réalisent printf ou scanf.
Les fichiers concernés par ces opérations de formatage sont alors
ce que l'on a coutume d'appeler des "fichiers de type texte" ou
encore des "fichiers de texte".
Ce sont des fichiers que vous pouvez manipuler avec un éditeur
quelconque, un traitement de texte quelconque ou, plus
simplement, lister par les commandes appropriées du système
d'exploitation (TYPE ou PRINT sous DOS, pr ou more sous
UNIX,...).
  9. LES ENTRÉES-SORTIES FORMATÉES ET
LES FICHIERS DE TEXTE
-------------------------------------------------------------------
Dans les fichiers de texte, chaque octet représente un caractère.
Généralement, on y trouve des caractères de fin de ligne (\n), de
sorte qu'ils apparaissent comme une suite de lignes. Les
fonctions permettant de travailler avec des fichiers de texte ne
sont rien d'autre qu'une généralisation aux fichiers de celles que
nous avons déjà rencontrées pour les entrées-sorties
conversationnelles. Nous nous contenterons donc d'en fournir
une brève liste :
fscanf ( fichier, format, liste_d'adresses )
fprintf ( fichier, format, liste_d'expressions )
fgetc ( fichier )
fputc (entier, fichier )
fgets ( chaîne, lgmax, fichier )
fputs ( chaîne, fichier )
La signification de leurs arguments est la même que pour les
fonctions conversationnelles correspondantes. Seule fgets
comporte un argument entier (lgmax) de contrôle de longueur. Il
précise le nombre maximal de caractères (y compris le \0 de fin)
qui seront placés dans la chaîne.
  9. LES ENTRÉES-SORTIES FORMATÉES ET
LES FICHIERS DE TEXTE
-------------------------------------------------------------------
Dans les fichiers de texte, chaque octet représente un caractère.
Généralement, on y trouve des caractères de fin de ligne (\n), de
sorte qu'ils apparaissent comme une suite de lignes. Les
fonctions permettant de travailler avec des fichiers de texte ne
sont rien d'autre qu'une généralisation aux fichiers de celles que
nous avons déjà rencontrées pour les entrées-sorties
conversationnelles. Nous nous contenterons donc d'en fournir
une brève liste :
fscanf ( fichier, format, liste_d'adresses )
fprintf ( fichier, format, liste_d'expressions )
fgetc ( fichier )
fputc (entier, fichier )
fgets ( chaîne, lgmax, fichier )
fputs ( chaîne, fichier )
La signification de leurs arguments est la même que pour les
fonctions conversationnelles correspondantes. Seule fgets
comporte un argument entier (lgmax) de contrôle de longueur. Il
précise le nombre maximal de caractères (y compris le \0 de fin)
qui seront placés dans la chaîne.
  9. LES DIFFÉRENTES POSSIBILITÉS
D'OUVERTURE D'UN FICHIER
-------------------------------------------------------------------
Les modes offerts par fopen.
r : lecture seulement ; le fichier doit exister.
w : écriture seulement. Si le fichier n'existe pas, il est créé. S'il existe, son
(ancien) contenu est perdu.
a : écriture en fin de fichier (append). Si le fichier existe déjà, il sera
"étendu". S'il n'existe pas, il sera créé – on se ramène alors au mode w.
r+ : mise à jour (lecture et écriture). Le fichier doit exister. Il n'est pas
possible de réaliser une lecture à la suite d'une écriture ou une écriture à
la suite d'une lecture, sans positionner le pointeur de fichier par fseek.
Il est toutefois possible d'enchaîner plusieurs lectures ou écritures
consécutives (de façon séquentielle).
w+ : création pour mise à jour. Si le fichier existe, son (ancien) contenu
sera détruit. S'il n'existe pas, il sera créé. Notez que l'on obtiendrait un
mode comparable à w+ en ouvrant un fichier vide (mais existant) en mode
r+.
a+ : extension et mise à jour. Si le fichier n'existe pas, il sera créé. S'il
existe, le pointeur sera positionné en fin de fichier.
t ou b : lorsque l'implémentation distingue les fichiers de texte des autres,
il est possible d'ajouter l'une de ces deux lettres à chacun des 7 modes
précédents. La lettre t précise que l'on a affaire à un fichier de texte ; la
lettre b précise que l'on a affaire à un fichier"binaire".
  9. LES FICHIERS PRÉDÉFINIS
-------------------------------------------------------------------
Un certain nombre de fichiers sont connus du langage C, sans
qu'il soit nécessaire ni de les ouvrir ni de les fermer :

stdin : unité d'entrée (par défaut, le clavier)


stdout : unité de sortie (par défaut, l'écran)
stderr : unité d'affichage des messages d'erreurs (par défaut,
l'écran)
On trouve parfois également :
stdaux : unité auxiliaire
stdprt : imprimante
  8. LES FONCTIONS
-------------------------------------------------------------------
Les bibliothèques standards
En C, il n'existe aucune commande spécifique pour faire
communiquer le programme avec l'extérieur. On utilise des fonctions
externes fournies par le système sur lequel le programme doit
fonctionner.
La norme C impose que tous les compilateurs fournissent un certain
nombre de fonctions standards dont le fonctionnement et les
paramètres sont définis par la norme. Chaque système peut proposer
ses propres fonctions spécifiques en plus des fonctions standards.
Dans ces fonctions standards, on trouve entre autre:
•des fonctions de calcul mathématique (log, cos, sin, sqrt, etc.)
•des fonctions d'entrées/sorties (printf, fprintf, scanf, fscanf, getc, putc,
etc.)
•des fonctions d'accès aux fichiers (fopen, fclose, fread, fwrite, etc.)
•des fonctions de manipulation de chaînes de caractères (strlen,
strcpy, strcat, etc.)
•des fonctions de gestion de la mémoire (malloc, free, calloc, etc.).
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
La norme ANSI fournit à la fois la description du langage C et le
contenu d'une bibliothèque "standard".
Cette bibliothèque est subdivisée en plusieurs "sous-
bibliothèques" ; à chaque sous-bibliothèque est associé un fichier
"en-tête" (d'extension H) comportant essentiellement :
–les en-têtes des fonctions correspondantes,
–les définitions des macros correspondantes,
–les définitions de certains symboles utiles au bon fonctionnement
des fonctions ou macros de la sous-bibliothèque.

Le présent chapitre décrit les principales fonctions prévues par la


norme. Chaque paragraphe correspond à une sous-bibliothèque et
précise quel est le nom du fichier en-tête correspondant.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1 - ENTRÉES-SORTIES (STDIO.H )

1.1 Gestion des fichiers


fopen FILE * fopen (const char * nom fichier,
const char * mode)
ouvre le fichier dont le nom est fourni, sous forme d'une
chaîne, à l'adresse indiquée par nomfichier. Fournit, en retour,
un "flux" (pointeur sur une structure de type prédéfini FILE),
ou un pointeur nul si l'ouverture a échoué. Les valeurs
possibles de mode définissent les différentes possibilités
d’ouverture d’un fichier .

fclose int fclose (FILE * flux)


Vide éventuellement le tampon associé au flux concerné,
désalloue l'espace mémoire attribué à ce tampon et ferme le
fichier correspondant. Fournit la valeur EOF en cas d'erreur et
la valeur 0 dans le cas contraire.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
Les modes offerts par fopen.
r : lecture seulement ; le fichier doit exister.
w : écriture seulement. Si le fichier n'existe pas, il est créé. S'il existe, son
(ancien) contenu est perdu.
a : écriture en fin de fichier (append). Si le fichier existe déjà, il sera
"étendu". S'il n'existe pas, il sera créé – on se ramène alors au mode w.
r+ : mise à jour (lecture et écriture). Le fichier doit exister. Il n'est pas
possible de réaliser une lecture à la suite d'une écriture ou une écriture à
la suite d'une lecture, sans positionner le pointeur de fichier par fseek.
Il est toutefois possible d'enchaîner plusieurs lectures ou écritures
consécutives (de façon séquentielle).
w+ : création pour mise à jour. Si le fichier existe, son (ancien) contenu
sera détruit. S'il n'existe pas, il sera créé. Notez que l'on obtiendrait un
mode comparable à w+ en ouvrant un fichier vide (mais existant) en mode
r+.
a+ : extension et mise à jour. Si le fichier n'existe pas, il sera créé. S'il
existe, le pointeur sera positionné en fin de fichier.
t ou b : lorsque l'implémentation distingue les fichiers de texte des autres,
il est possible d'ajouter l'une de ces deux lettres à chacun des 7 modes
précédents. La lettre t précise que l'on a affaire à un fichier de texte ; la
lettre b précise que l'on a affaire à un fichier"binaire".
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.2 Ecriture formatée
Toutes ces fonctions utilisent une chaîne de caractères nommée format,
composée à la fois de caractères quelconques et de codes de format.
int fprintf (FILE * flux, const char * form at, ...)
Convertit les valeurs éventuellement mentionnées dans la liste
d'arguments (...) en fonction du format spécifié, puis écrit le résultat dans
le flux indiqué. Fournit le nombre de caractères effectivement écrits ou
une valeur négative en cas d'erreur.

int printf (const ch ar * form at, ...)


Convertit les valeurs éventuellement mentionnées dans la liste
d'arguments (...) en fonction du format spécifié, puis écrit le résultat sur la
sortie standard (stdout). Fournit le nombre de caractères effectivement
écrits ou une valeur négative en cas d'erreur.
Notez que : printf (format, ...) ;est équivalent à : fprintf (stdout, format, ...) ;

int sprintf (char * ch , const char * form at, ...)


Convertit les valeurs éventuellement mentionnées dans la liste
d'arguments (...) en fonction du format spécifié et place le résultat dans la
chaîne d'adresse ch, en le complétant par un caractère \0. Fournit le
nombre de caractères effectivement écrits (sans tenir compte du \0) ou
une valeur négative en cas d'erreur.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
Les codes de format utilisables avec ces trois fonctions
Chaque code de format a la structure suivante :
% [drapeaux] [largeur] [.précision] [h|l|L] conversion
les crochets ([ et ]) signifient que ce qu'ils renferment est facultatif.
Les différentes "indications" se définissent comme suit :
drapeaux :
- : justification à gauche
+ : signe toujours présent
^ : impression d'un espace au lieu du signe +
# : forme "alternée" ; elle n'affecte que les types o, x, X, e, E, f,
g et G comme suit :
o : fait précéder de 0 toute valeur non nulle
x ou X : fait précéder de 0x ou 0X la valeur affichée
e, E ou f : le point décimal apparaît toujours
g ou G : même effet que pour e ou E, mais de plus les
zéros de droite ne seront pas supprimés
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
largeur (n désigne une constante entière positive écrite en
notation décimale) :

n : au minimum, n caractères seront affichés, éventuellement


complétés par des blancs à gauche

0n : au minimum, n caractères seront affichés, éventuellement


complétés par des zéros à gauche

* : la largeur effective est fournie dans la "liste d'expressions"


10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
précision (n désigne une constante entière positive écrite en notation décimale) :
.n : la signification dépend du "caractère de conversion" , de la manière suivante :
d, i, o, u, x ou X : au moins n chiffres seront imprimés. Si le nombre comporte
moins de n chiffres, l'affichage sera complété à gauche par des zéros. Cela
n'est pas contradictoire avec l'indication de largeur, si celle ci est supérieure à
n. En effet, dans ce cas, le nombre pourra être précédé à la fois d'espaces et
de zéros
e, E ou f : on obtiendra n chiffres après le point décimal, avec arrondi du
dernier
g ou G : on obtiendra au maximum n chiffres significatifs
c : sans effet
s : au maximum n caractères seront affichés. Notez que cela n'est pas
contradictoire avec l'indication de largeur
.0 : la signification dépend du caractère de conversion, comme suit :
d, i, o, u, x ou X : choix de la valeur par défaut de la précision (voir ci-dessous)
e, E ou f : pas d'affichage du point décimal
* : la valeur effective de n est fournie dans la "liste d'expressions"
rien : choix de la valeur par défaut, à savoir :
1 pour d, i, o, u, x ou X
6 pour e, E ou f
tous les chiffres significatifs pour g ou G
tous les caractères pour s
sans effet pour c
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
h|l|L :
h : l'expression correspondante est d'un type short int (signé
ou non).
Ce code ne peut avoir une éventuelle signification que pour les
caractères de conversion : d, i, o, u, x ou X)
l : Ce code précise que l'expression correspondante est de
type long int. Il n'a de signification que pour les caractères de
conversion : d, i, o, u, x ou X
L : Ce code précise que l'expression correspondante est de
type long double. Il n'a de signification que pour les caractères
de conversion : e, E, f, g ou G
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
Conversion : il s'agit d'un caractère qui précise à la fois le type de
l'expression (en italique) et la façon de présenter sa valeur:
d : signed int, affiché en décimal
o : unsigned int, affiché en octal
u : signed int, affiché en décimal
x : unsigned int, affiché en hexadécimal (lettres minuscules)
X : signed int, affiché en hexadécimal (lettres majuscules)
f : double, affiché en notation décimale
e : double, affiché en notation exponentielle (avec la lettre e)
E : double, affiché en notation exponentielle (avec la lettre E)
g : double, affiché suivant le code f ou e (ce dernier étant utilisé lorsque l'exposant
obtenu est soit supérieur à la précision désirée, soit inférieur à -4)
G : double, affiché suivant le code f ou E (ce dernier étant utilisé lorsque l'exposant
obtenu est soit supérieur à la précision désirée, soit inférieur à -4)
c : char
s : pointeur sur une "chaîne"
% : affiche le caractère "%", sans faire appel à aucune expression de la liste
n : place, à l'adresse désignée par l'expression de la liste (du type pointeur sur un
entier), le nombre de caractères écrits jusqu'ici
p : pointeur, affiché sous une forme dépendant de l'implémentation
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.3 Lecture formatée
Ces fonctions utilisent une chaîne de caractères nommée format,
composée à la fois de caractères quelconques et de codes de format dont
la signification est décrite ci après.

int fscanf (FILE * flux, const char * format, ...)


Lit des caractères sur le flux spécifié, les convertit en tenant compte du
format indiqué et affecte les valeurs obtenues aux différentes variables de
la liste d'arguments (...). Fournit le nombre de valeurs lues
convenablement ou la valeur EOF si une erreur s'est produite ou si une fin
de fichier a été rencontrée avant qu'une seule valeur ait pu être lue.

int scanf (const char * format, ...)


scanf (format, ...) est équivalent à :fscanf (stdin, format, ...)

int sscanf (char * ch , const char * format, ...)


Lit des caractères dans la chaîne d'adresse ch, les convertit en tenant
compte du format indiqué et affecte les valeurs obtenues aux différentes
variables de la liste d'arguments (...). Fournit le nombre de valeurs lues
convenablement.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
Règles communes à ces fonctions
a) Il existe six caractères dits "séparateurs", à savoir : l'espace, la tabulation horizontale (\t), la
fin de ligne (\n), le "retour chariot" (\r), la tabulation verticale (\v) et le changement de page (\f)

b) L'information est recherchée dans un "tampon", image d'une ligne. Il y a donc une certaine
désynchronisation entre ce que l'on frappe au clavier (lorsque l'unité standard est connectée à
ce périphérique) et ce que lit la fonction. Lorsqu'il n'y a plus d'information disponible dans le
tampon, il y a déclenchement de la lecture d'une nouvelle ligne. Pour décrire l'exploration de ce
tampon, il est plus simple de faire intervenir un indicateur de position que nous nommerons
"pointeur".

c) La rencontre dans le format d'un caractère séparateur provoque l'avancement du pointeur


jusqu'à la rencontre d'un caractère qui ne soit pas un séparateur.

d) La rencontre dans le format d'un caractère différent d'un séparateur (et de %) provoque la
prise en compte du caractère courant (celui désigné par le pointeur). Si celui-ci correspond au
caractère du format, la fonction poursuit son exploration du format. Dans le cas contraire, il y a
arrêt prématuré de la fonction.

e) Lors du traitement d'un code de format, l'exploration s'arrête :


- à la rencontre d'un caractère invalide par rapport à l'usage qu'on doit en faire
(point décimal pour un entier, caractère différent d'un chiffre ou d'un signe
pour du numérique,...). Si la fonction n'est pas en mesure de fabriquer une
valeur, il y a arrêt prématuré de l'ensemble de la lecture,
- à la rencontre d'un séparateur,
- lorsque la longueur (si elle a été spécifiée) a été atteinte.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
Les codes de format utilisés par ces fonctions
Chaque code de format a la structure suivante :
% [*] [largeur] [h|l|L] conversion
les crochets ([ et ]) signifient que ce qu'ils renferment est facultatif. Les différentes
"indications" se définissent comme suit :

* : la valeur lue n'est pas prise en compte ; elle n'est donc affectée à
aucun élément de la liste

largeur : nombre maximal de caractères à prendre en compte (on peut en


lire moins s'il y a rencontre d'un séparateur ou d'un caractère invalide)

h|l|L :
h : l'élément correspondant est l'adresse d'un "short int". Ce modificateur n'a
de signification que pour les caractères de conversion : d, i, n, o, u, ou x
l : l'élément correspondant est l'adresse d'un élément de type :
- long int pour les caractères de conversion d, i, n, o, u ou x
- double pour les caractères de conversion e ou f
L : l'élément correspondant est l'adresse d'un élément de type long double. Ce
modificateur n'a de signification que pour les caractères de conversion e, f ou
g.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
conversion :
Ce caractère précise à la fois le type de l'élément correspondant (nous
l'avons indiqué ici en italique) et la manière dont sa valeur sera exprimée.
Les types numériques indiqués correspondent au cas où aucun
modificateur n'est utilisé (voir ci-dessus).

Il ne faut pas perdre de vue que l'élément correspondant est toujours


désigné par son adresse. Ainsi, par exemple, lorsque nous parlons de
"signed int", il faut lire : "adresse d'un signed int" ou encore "pointeur sur
un signed int«

d : signed int exprimé en décimal


o : signed int exprimé en octal
i : signed int exprimé en décimal, en octal ou en hexadécimal
u : unsigned int exprimé en décimal
x : int (signed ou unsigned) exprimé en hexadécimal
f, e ou g : float écrit indifféremment en notation décimale
(éventuellement sans point) ou exponentielle (avec e ou E)
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
conversion :
c : suivant la "longueur", correspond à :
- un caractère lorsque aucune longueur n'est spécifiée ou que celle-ci est égale à 1
- une "suite" de caractères lorsqu'une longueur différente de 1 est spécifiée. Dans
ce cas, il ne faut pas perdre de vue que la fonction reçoit une adresse et que donc,
dans ce cas, elle lira le nombre de caractères spécifiés et les rangera à partir de
l'adresse indiquée. Il est bien sûr préférable que la place nécessaire ait été
réservée. Notez bien qu'il ne s'agit pas ici d'une véritable chaîne, puisqu'il n'y aura
pas (à l'image de ce qui se passe pour le code %s) d'introduction du caractère \0 à
la suite des caractères rangés en mémoire

s : chaîne de caractères. Il ne faut pas perdre de vue que la fonction la fonction


reçoit une adresse et que donc, dans ce cas, elle lira tous les caractères jusqu'à la
rencontre d'un séparateur (ou un nombre de caractères égal à la longueur
éventuellement spécifiée) et elle les rangera à partir de l'adresse indiquée. Il est
donc préférable que la place nécessaire ait été réservée. Notez bien qu'ici un
caractère \0 est stocké à la suite des caractères rangés en mémoire et que sa place
aura dû être prévue (si l'on lit n caractères, il faudra de la place sur n+1)
%
n : int, dans lequel sera placé le nombre de caractères lus correctement jusqu'ici.
Aucun caractère n'est donc lu par cette spécification

p : pointeur exprimé en hexadécimal, sous la forme employée par printf (elle


dépend de l'implémentation)
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.4 Entrées -sorties de caractères
fgetc int fgetc (FILE * flux)
Lit le caractère courant du flux indiqué. Fournit :
- le résultat de la conversion en int du caractère c (considéré comme
unsigned int) si l'on n'était pas en fin de fichier
- la valeur EOF si la fin de fichier était atteinte
Notez que fgetc ne fournit de valeur négative qu'en cas de fin de fichier,
quel que soit le code employé pour représenter les caractères et quel que
soit l'attribut de signe attribué par défaut au type char.
fgets char * fgets (char * ch , int n, FILE * flux)
Lit au maximum n-1 caractères sur le flux mentionné (en s'interrompant
éventuellement en cas de rencontre d'un caractère \n), les range dans la
chaîne d'adresse ch, puis complète le tout par un caractère \0. Le
caractère \n, s'il a été lu, est lui aussi rangé dans la chaîne (donc juste
avant le \0). Cette fonction fournit en retour :
- la valeur NULL si une éventuelle erreur a eu lieu ou si une fin de fichier a
été rencontrée,
- l'adresse ch, dans le cas contraire.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.4 Entrées -sorties de caractères

fputc int fputc (int c, FILE * flux)


Ecrit sur le flux mentionné la valeur de c, après conversion en unsigned
char. Fournit la valeur du caractère écrit (qui peut donc, éventuellement,
être différente de celle du caractère reçu) ou la valeur EOF en cas d'erreur.
fputs int fputs (const char * ch, FILE * flux)
Ecrit la chaîne d'adresse ch sur le flux mentionné. Fournit la valeur EOF
en cas d'erreur et une valeur non négative dans le cas contraire.
getc int getc (FILE * flux)
Macro effectuant la même chose que la fonction fgetc.
getchar int getchar (void)
Macro effectuant la même chose que l'appel de la macro :
fgetc (stdin)
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.4 Entrées -sorties de caractères
gets char * gets (char * ch )
Lit des caractères sur l'entrée standard (stdin), en s'interrompant à la
rencontre d'une fin de ligne (\n) ou d'une fin de fichier, et les range dans la
chaîne d'adresse ch, en remplaçant le \n par \0. Fournit :
- la valeur NULL si une erreur a eu lieu ou si une fin de fichier a été
rencontrée, alors qu'aucun caractère n'a encore été lu,
- l'adresse ch, dans le cas contraire.
putc int putc (int c, FILE * flux)
Macro effectuant la même chose que la fonction fputc.
putchar int putchar (int c)
Macro effectuant la même chose que l'appel de la macro putc, avec stdout
Ainsi : putchar (c) est équivalent à :putc (c, stdout)
puts int puts (const char * ch )
Ecrit sur l'unité standard de sortie (stdout) la chaîne d'adresse ch, suivie
d'une fin de ligne (\n). Fournit EOF en cas d'erreur et une valeur non
négative dans le cas contraire.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.5 Entrées -sorties sans formatage

fread size_t fread (void * adr, size_t taille, size_t


nblocs, FILE * flux)
Lit, sur le flux spécifié, au maximum nblocs de taille octets chacun
et les range à l'adresse adr. Fournit le nombre de blocs réellement
lus.

fwrite size_t fwrite (const void * adr, size_t taille,


size_t nblocs, FILE * flux)
Ecrit, sur le flux spécifié, nblocs de taille octets chacun, à partir de
l'adresse adr. Fournit le nombre de blocs réellement écrits.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.6 Action sur le pointeur de fichier

fseek int fseek (FILE * flux, long noct, int org)


Place le pointeur du flux indiqué à un endroit défini comme étant situé à
noct octets de l'"origine" spécifiée par org :
org = SEEK_SET correspond au début du fichier
org = SEEK_CUR correspond à la position actuelle du pointeur
org = SEEK_END correspond à la fin du fichier
Dans le cas des "fichiers de texte" (si l'implémentation les différencie des
autres), les seules possibilités autorisées
sont l'une des deux suivantes :
* noct = 0
* noct a la valeur fournie par ftell (voir ci-dessous) et org = SEEK_SET

ftell long ftell (FILE *flux)


Fournit la position courante du pointeur du flux indiqué (exprimée en
octets par rapport au début du fichier) ou la valeur -1L en cas d'erreur.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
1.7 Gestion des erreurs

feof int feof (FILE * flux)


Fournit une valeur non nulle si l'indicateur de fin de fichier du flux
indiqué est activé et la valeur 0 dans le cas contraire.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
2 - TESTS DE CARACTÈRES ET CONVERSIONS MAJUSCULES-
MINUSCULES (CTYPE.H )
isalnum int isalnum (char c)
Fournit la valeur 1 (vrai) si c est une lettre ou un chiffre et la valeur 0 (faux)
dans le cas contraire.
isalpha int isalpha (char c)
Fournit la valeur 1 (vrai) si c est une lettre et la valeur 0 (faux) dans le cas
contraire.
isdigit int isdigit (char c)
Fournit la valeur 1 (vrai) si c est un chiffre et la valeur 0 (faux) dans le cas
contraire.
islower int islower (char c)
Fournit la valeur 1 (vrai) si c est une lettre minuscule et la valeur 0 (faux)
dans le cas contraire.
isspace int isspace (char c)
Fournit la valeur 1 (vrai) si c est un "séparateur" (espace, saut de page, fin
de ligne, retour chariot, tabulation horizontale ou verticale) et la valeur 0
(faux) dans le cas contraire.
isupper int isupper (char c)
Fournit la valeur 1 (vrai) si c est une lettre majuscule et la valeur 0 (faux)
dans le cas contraire.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
3 - MANIPULATION DE CHAINES (STRING.H )
strcpy char * strcpy (char * but, const char * source)
Copie la chaîne source à l'adresse but (y compris le \0 de fin) et fournit en
retour l'adresse de but.

strncpy char * strncpy (char * but, const char * source, int lgmax)
Copie au maximum lgmax caractères de la chaîne source à l'adresse but
en complétant éventuellement par des caractères \0 si cette longueur
maximale n'est pas atteinte. Fournit en retour l'adresse de but.

strcat char * strcat (char * but, const char * source)


Recopie la chaîne source à la fin de la chaîne but et fournit en retour
l'adresse de but.

strncat char * strncat (char * but, const char * source, size_t


lgmax)
Recopie au maximum lgmax caractères de la chaîne source à la fin de la
chaîne but et fournit en retour l'adresse de but.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
3 - MANIPULATION DE CHAINES (STRING.H )
strcmp int strcmp (const char * chaine1, const char * chaine2)
Compare chaine1 et chaine2 et fournit :
- une valeur négative si chaine1 < chaine2,
- une valeur positive si chaine1 > chaine2,
-zéro si chaine1 = chaine2.

strncmp int strncmp (const char * chaine1, const char *


chaine2, size_t lgmax)
Travaille comme strcmp, en limitant la comparaison à un maximum de
lgmax caractères.

strchr char * strchr (const char * chaine, char c)


Fournit un pointeur sur la première occurrence du caractère c dans la
chaîne chaine, ou un pointeur nul si ce caractère n'y figure pas.

strrchr char * strrchr (const char * chaine, char c)


Fournit un pointeur sur la dernière occurrence du caractère c dans la
chaîne chaine ou un pointeur nul si ce caractère n'y figure pas.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
3 - MANIPULATION DE CHAINES (STRING.H )
strcspn size_t strcspn (const char * chaine1, const char *
chaine2)
Fournit la longueur du "segment initial" de chaine1 formé entièrement de
caractères n'appartenant pas à chaine2.
strstr char * strstr (const char * chaine1, const char * chaine2)
Fournit un pointeur sur la première occurrence dans chaine1 de chaine2
ou un pointeur nul si chaine2 ne figure pas dans chaine1.
strlen size_t strlen (const char * chaine)
Fournit la longueur de chaine.
Memcpyvoid * memcpy (void * but, const void * source, size_t lg)
Copie lg octets depuis l'adresse source à l'adresse but qu'elle fournit
comme valeur de retour (il ne doit pas y avoir de recoupement entre
source et but).
Memmove void * memmove (void * but, const void * source, size_tlg)
Copie lg octets depuis l'adresse source à l'adresse but qu'elle fournit
comme valeur de retour (il peut y avoir recoupement entre source et but).
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
4 - FONCTIONS MATH ÉMATIQUES (MATH .H )
sin double sin (double x)
cos double cos (double x)
tan double tan (double x)
asin double asin (double x)
acos double acos (double x)
atan double atan (double x)
atan2 double atan2 (double y, double x)
Fournit la valeur de arctan(y/x)
sinh double sinh (double x)
cosh double cosh (double x)
tanh double tanh (double x)
exp double exp (double x)
log double log (double x)
Fournit la valeur du logarithme népérien de x : Ln(x) (ou Log(x))
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
4 - FONCTIONS MATH ÉMATIQUES (MATH .H )

log10 double log10 (double x)


Fournit la valeur du logarithme à base 10 de x : log(x)
pow double pow (double x, double y)
Fournit la valeur de xy
sqrt double sqrt (double x)
ceil double ceil (double x)
Fournit (sous forme d'un double) le plus petit entier qui ne soit pas
inférieur à x.
floor double floor (double x)
Fournit (sous forme d'un double) le plus grand entier qui ne soit
pas supérieur à x.
fabs double fabs (double x)
Fournit la valeur absolue de x
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
5 - UTILITAIRES (STDLIB.H )
atof double atof (const char * chaine)
Fournit le résultat de la conversion en double du contenu de chaine. Cette
fonction ignore les éventuels séparateurs de début et, à l'image de ce que
fait le code format %f, utilise les caractères suivants pour fabriquer une
valeur numérique. Le premier caractère invalide arrête l'exploration.

atoi int atoi (const char * chaine)


Fournit le résultat de la conversion en int du contenu de chaine. Cette
fonction ignore les éventuels séparateurs de début et, à l'image de ce que
fait le code format %d, utilise les caractères suivants pour fabriquer une
valeur numérique. Le premier caractère invalide arrête l'exploration.

atol long atol (const char * chaine)


Fournit le résultat de la conversion en long du contenu de chaine. Cette
fonction ignore les éventuels séparateurs de début et, à l'image de ce que
fait le code format %ld, utilise les caractères suivants pour fabriquer une
valeur numérique. Le premier caractère invalide arrête l'exploration.
10. Les principales fonctions
de la bibliothèque standard
-------------------------------------------------------------------
5 - UTILITAIRES (STDLIB.H )

rand int rand (void)


Fournit un nombre entier aléatoire (en fait "pseudo-aléatoire"), compris
dans l'intervalle [0, RAND_MAX]. La valeur prédéfinie RAND_MAX est au
moins égale à 32767.

srand void srand (unsigned int graine)


Modifie la "graine" utilisée par le "générateur de nombres pseudo-
aléatoires" de rand. Par défaut, cette graine a la valeur 1.