Cours-Gratuit
  • Accueil
  • Blog
  • Cours informatique
home icon Cours gratuits » Cours informatique » Cours programmation » Cours C++

Formation C++

Formation C++
Participez au vote ☆☆☆☆☆★★★★★

 Elaboré par : Mr Mustapha AITMAHJOUB

SOMMAIRE

                                                                                                                                             Page

INTRODUCTION AU LANGAGE C++

1.   ELEMENTS DU LANGAGE ………………………………… …………………. 2

1.1  Alphabet du langage………………………………… …………………………2

1.2  Mots réservés………………………………………… ………………………..2

1.3  Identificateurs………………………………………………………………..….2

1.4  Constantes……………………………………………………………………… 3

1.5  Commentaire…………………………………………………………………… 3

1.6  Les séparateurs……………………………………………………………………3

2.   STRUCTURE D’UN PROGRAMME C++………………………………………….4

2.1  Structure de base……………………………………………………………….5

3.   TYPES DE DONNEES FONDAMENTAUX………………………………………6

3.1  Données de type entier .6

3.2  Données de type réel…………………………………………………………..6

4.   VARIABLES ET CONSTANTES…………………………………………………..7

4.1  Variables ………………………………………………………………………7

4.2  Constantes……………………………………………………………………..7

5.   ENTREE/SORTIE DES DONNEES………………………………………………..8

5.1  Fonction printf ()……………………………………………………………….8

5.1.1  Sortie formatée……………………………………………………..…8

5.1.2  Largeur du champ…………………………………………………….9

5.1.3  Séquences d’échappement…………………………………………..10

5.2  Fonction scanf ()……………………………………………………………..10

6.   LES EXPRESSIONS………………………………………………………………11

6.1  Opérateurs arithmétiques…………………………………………………….12

6.2  Opérateurs de manipulation………………………………………………….12

6.3  Opérateurs d’incrémentation/decrémentation……………………………….12

6.4  Opérateurs sizeof ()………………………………………………………….12

7.   EXPRESSION BOOLEENNE…………………………………………………….13

7.1  Opérateurs de comparaison………………………………………………….13

7.2  Opérateurs logiques………………………………………………………….13

7.3  Opérateurs conditionnels ternaire……………………………………………14

8.   INSTRUCTIUONS D’AFFECTATION…………………………………………..14

9.   PRIORITE DES OPERATEURS…………………………………………………..17 INSTRUCTION DE CONTROLE

1.   STRUCTURE SEQUENTIELLE………………………………………………….17

2.   STRUCTURE SELECTIVE……………………………………………………….18

2.1  Structure if……………………………………………………………………19

2.2  Structure if,,else………………………………………………………………21

2.3  Structures if imbriquées………………………………………………………24

2.4  Structure switch………………………………………………………………25

STRUCTURE REPETITIVE………………………………………………………26

3.1  Structure while……………………………………………………………….28

3.2  Structure do..while………………………………………………………… 29

3.3  Structure for………………………………………………………………….30

INSTRUCTUION DE BRANHEMENT………………………………..…………30

4.1  Instruction break…………………………………………………………… 31

4.2  Instruction continue…………………………………………………………….31

4.3  Instruction goto…………………………………………………………………34

TYPES DE DONNEES COMPLEXES

1.   LES TABLEAUX…………………………………………………………………….34

1.1  Tableaux unidimensionnels ……………………………………………………34

1.1.1    Déclaration d’un tableau……………………………………………….34

1.1.2    Initialisation d’un tableau………………………………………………36

1.2  Tableaux multidimensionnels…………………………………………………..36

1.2.1    Déclaration d’un tableau……………………………………………… 36

1.2.2    Initialisation d’un tableau………………………………………………..38

LES CHAINES DE CARACTERES…………………………………………………38

2.1  Fonctions d’entrée/sortie des chaînes…………………………………………..39

2.2  Fonctions de traitement des chaînes…………………………………………….40

2.   LES STRUCTURES………………………………………………………………….41

3.1  Déclarations d’une structure……………………………………………………41

3.2  Déclaration de variables d’une structur…………………………………………41

3.3  Accès aux membres de la structure……………………………………………..42

3.   LES POINTUERS……………………………………………………………………43

4.1  Déclaration des pointeurs……………………………………………………….45

4.2  Tableaux et pointeurs……………………………………………………………47

4.3  Pointeurs et chaînes de caractères ………………………………………………47

4.3.1  Initialisation d’une chaîne………………………………………………47

4.3.2  Traitement des chaînes………………………………………………….49

4.4  Pointeurs et structures…………………………………………………………..50

4.5  Allocation dynamique de la mémoire…………………………………………..52

4.   ENUMERATION……………………………………………………………………..52

5.1 Utilisation des énumérations ……………………………………………………53

5.   DEFINITION DE NOUVEAUX TYPES……………………………………………..54 LES FONCTIONS

FONCTION NE RETOURNANT PAS DE VALEUR……………………………….57

1.1  Fonction ne prenant pas de paramètres………………………………………….57

1.2  Fonction prenant des paramètres……………………………………………… 59

FONCTION RETOURNANT UNE VALEUR……………………………………….61

PASSAGE DE PARAMETRES………………………………………………………63

3.1  Passage par valeur………………………………………………………………63

3.2  Passage par adresse……………………………………………………………..64

3.3  Passage par référence……………………………………………………………64 PASSAGE D’UN TABLEAU à UNE FONCTION ………………………………….66

PASSAGE D’UNE STRUCTURE à NE FONCTION………………………………..69

1.  CLASSE DE STOKAGE………………………………………………………………72

6.1 Durée de vie……………………………………………………………………..72

6.1.1 Variables automatiques…………………………………………………73

6.1.2  Variables statiques et externes…………………………………………73

6.2 Portée des variables……………………………………………………………..74

6.2.1 Portée bloc………………………………………………………………74

6.2.2 Portée fonction………………………………………………………….74

6.2.3 Portée fichier……………………………………………………………75

LES FICHIERS

1.   DEFINITION………………………………………………………………………77

2.   PRINCIPE D’ACCES AUX FICHIERS…………………..………………………77

3.   ENTREE/SORTIE STANDARD…………………………………………………..78

3.1  E/S des caractères……………………………………………………………79

3.1.1  Ouverture d’un fichier……………………………………………….80

3.1.2  Ecriture vers un fichier………………………………………………83

3.1.3  Fermer un fichier…………………………………………………….83

3.1.4  Lecture d’un fichier………………………………………………….83

3.1.5  Fin de fichier…………………………………………………………84

3.1.6  Erreur d’ouverture d’un fichier………………………………………84

3.1.7  Application : compter le nombre de caractères………………………86

3.2  E/S des chaînes………………………………………………………………..87

3.3  E/S formatées…………………………………………………………………90

3.4  Mode binaire et mode texte…………………………………………………..93

3.5  E/S des enregistrements………………………………………………………95

3.5.1  Ecriture des structures avec fwrite()…………………………………95

3.5.2  Lecture des structures avec fread()…………………………………..97

3.6  Accès aléatoire……………………………………………………………….98

4.   E/S SYSTEME……………………………………………………………………..101

4.1  Lecture des fichiers…………………………………………………………..102

4.1.1  Création d’un tampon………………………………………………..103

4.1.2  Ouverture d’un fichier……………………………………………….103

4.1.3  Identificateur de fichier…………………………………………… 104

4.1.4  Lecture du fichier dans le tampon………………………………… 104

4.1.5  Fermeture du fichier……………………………….………………..105

4.1.6  Message d’erreur……………………………………………………105

4.2  Opérations sur le tampon……………………………………………………105

4.3  Ecrire dans un fichier………………………………………………………..109



INTRODUCTION AU LANGAGE C

1.   ELEMENTS DU LANGAGE C

1.1 Alphabet du langage

Le langage C utilise les lettres A à Z (majuscule et minuscule), les chiffres 0..9 et certains symboles spéciaux comme éléments de construction pour former les éléments de base d’un programme.

Certains symboles spéciaux se composent de deux caractères consécutifs, par exemple  ++  >=  /* !

=

1.2 Mots réservés

Les mots réservés ou mots clés ont en langage C et pour le compilateur une signification standard prédéfini. Les mots clés ne peuvent pas être redéfinis par l’utilisateur.

Asm

_asm

__asm

auto

break

case

cdecl

_cdecl

__cdecl

char

class

const

continue

_cs

__cs

default

delet

do

double

_ds

__ds

else

enum

_es

__es

_export

__export

extern

far

_far

__far

_fastcall

__fastcall

float

for

friend

goto

huge

__huge

if

inline

int

interrupt

_interupt

__interupt

_loadds

__loadds

long

near

_near

__near

new

operator

pascal

_pascal__pascal           private

               protected         public              register

return               _saveregs

__savaregs      _seg                __seg              short

signed              sizeof

_ss                   __ss                 static               struct

switch              template

this                  typedefunion              unsigned

virtual              void

volatilewhile

TABLEAU 1 : Mots réservés

1.3 Identificateurs

Un identificateur se définit comme un nom donné à un élément du programme tels que les variables, les types, fonctions et les labels.

L’identificateur est crée en le spécifiant dans la déclaration d’une variable, type ou d’une fonction. Dans l’exemple suivant, Valeur1, Valeur 2 et Somme sont des identificateurs de variables entières, et main() et printf() sont des identificateurs de fonctions.

#include<stdio.h> void main()

{ int Valeur 1 , Valeur 2, Somme ;

Valeur 1 = 10 Valeur 2 = 20

Somme = Valeur 1 + Valeur  2 ;

Printf (“ Somme = %d”, Somme) ; }

Une fois déclaré, on peut utiliser l’identificateur, plus tard, dans une instruction de programme pour se référer à la valeur associé à cet identificateur.

Les identificateurs se composent de lettres, de chiffres ou du caractère souligné dans n’importe quel ordre, pourvu que le premier caractère soit une lettre ou le caractère souligné. Le compilateur C fait une distinction entre les majuscules et les minuscules, par exemple valeur et Valeur sont deux identificateurs différents.

J, nombre_jour, ENTIER sont des identificateurs valides

Valeur 1 : invalide contient la caractère espace

7 somme : invalide car le premier caractère est un chiffre

1.4 Constantes

Il est souvent commode d’associer un élément de donnée simple, tel qu’une valeur numérique, un caractère ou une chaîne de caractère, à un identificateur, attribuant ainsi un nom à l’élément de donnée. On appelle l’identifcateur une constante si on lui attribue l’élément de donnée de manière définitive (la valeur reste inchangée tout au long du programme)

1.5 Le commentaire

Les commentaires sont des textes servant à annoter un programme. Ils ne présentent d’utilité que pour le programmeur, et ils sont supprimés logiquement du fichier source avant la compilation.

Il y’ a deux façons de délimiter les commentaires, soit par la paire ** lorsque le commentaire est écrit sur plusieurs lignes, soit // pour débuter une ligne de commentaire jusqu’à la fin de la ligne.

1.6 Les séparateurs

Crochets [] : les crochets ouvrants et fermants [ ] servant à spécifier un indice d’accès à un tableau mono ou multi-dimensios.

Char Ch, Str[]= “ Bonjour ” ;

Int Mat[3] [4] ; //matrice 3x4

                               Ch=Str[3] ;      //ch=’n’

Parenthèses () : Les parenthèses permettent de grouper des expressions, d’isoler des expressions conditionnelles et d’indiquer des appels de fonctions et des paramètres :

X = (a+b)/c ; // remplace la priorité normal

if (a= =0) ; // utilisation dans une instruction conditionnelle Fonc() ; // appel d’une fonction

Accolades {} : Le couple d’accolades permet d’indiquer le début et la fin d’un bloc d’instruction.

if (x !=5)

{ x++ ; fonct(x) ;

}

Virgule : La virgule sépare les éléments d’une liste d’arguments d’une fonction : Int somme (intx, int y) ;

Point-virgule ; Le point-virgule est le terminateur d’instruction. Toute expression légale en C (y compris l’expression vide) qui est suivie par le signe ; est interprétée en tant qu’instruction.

Deux-points : Le signe deux-points permet une instruction avec label :

Debut : x=0 ;

.

.

goto Debut ;

2.   STRUCTURE D’UN PROGRAMME C++

Les deux principales parties des programmes C++ sont les fichiers sources et les fichiers en-tête. Les fichiers sources contiennent les paries principales du programme. C’est dans les fichiers sources qu’on définit les routines, les données et les instructions.

Parfois, les fichiers sources empruntent les routines et fonctions d’autres fichiers sources ou de bibliothèque. Pour que ces routines soient reconnues par le compilateur, on doit déclarer dans le fichier principal des fichiers d’en-tête. Le fichier d’en-tête indique au compilateur les noms et caractéristiques des routines. Par exemple pour calculer 510 , on doit faire appel à la fonction pow qui est déclarée dans le fichier à inclure math.h

2.1 Structure de base des programmes C++

L’exemple suivant est un programme C++

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 1

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme affiche un message sur l’écran

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> void main()

{

// Affichage d’une chaîne

printf(’’Ce ci est un programme C++/n’’) ;

}

Regardons sa structure. Le texte entre /* et */ est un commentaire. Main() est une fonction. Tout programme C++ est un ensemble de fonctions dont une et une seule doit s’appeler main(). Le mot clé void indique au compilateur que la fonction main ne renvoie aucune valeur.

Si la programme doit renvoyer une valeur au système d’exploitation. Le programme précédent s’écrira :

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 2

 *Fichier :

 *Auteur :  Mustapha AIT MAHJOUB

 *Date : 10/09/1999

 *Description : Ce programme affiche un message sur l’écran et retourne une valeur au dos

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> int main()

{

// Affichage d’une chaîne

printf(’’Ce ci est un programme C++/n’’) ; return(0) ; }

En effet, il se peut que le système d’exploitation s’intéresse à la valeur renvoyée par main(). Par convention, 0 signifie succès, et toute valeur de retour non nulle désigne une erreur rencontrée durant l’execution du programme.

Les accolades { } marquent le début et la fin de la fonction main (). Les chaînes de caractères comme ’’Ce ci est un programme C++\n ’’ sont délimitées par des guillemets. \n est le caractère retour à la ligne. La fonction printf ( )affichera la chaîne de caractères sur l’écran. // débute une zone de commentaire qui s’étendra jusqu’à la fin de la ligne. En fin, #include <stdio.h> donnera au préprocesseur l’ordre d’inclure les lignes présentes dans le fichier d’en-tête stdio.h à l’intention du compilateur. Ce fichier contient, entre beaucoup d’autre, la déclaration de la fonction printf ().

3.  TYPES DE DONNEES FONDAMENTAUX

Le type de données caractérisent des variables et des constantes en définissant leurs plages de valeurs et les opérations que l’on peut faire dessus. Le type indique en plus le nombre d’octets consécutifs sur les quelle s’étale la valeur. Une variable de type int (entier), par exemple occupe un mot de 2 octets sous DOS.  

Les types de données se décomposent en deux catégories : les types prédéfinis et les types personnalisés. Les principaux types de C++ sont :

-      type entier

-      type réel

-      type structuré

-      type énumératifs

3.1 Données de type entier

Les données de type entier sont des objets avec un nombre complet (entier).Ces catégories incluent les constantes de type entier, les variables, les fonctions et expression.

Le tableau suivant donne les types entiers prédéfinis de C++, avec leurs tailles et leurs plages de valeurs relatives à l’environnement 16 bits.

Type

Plage de valeurs

Taille

char

-128 à127

1 octet

unsigned char

0 à 255

1 octet

short

-215 à +215-1

2 octets

unsigned short

0 à216

2octets

int

-215 à215 –1

2 octets

unsigned int

0 à 216 –1

2 octets

long

-231 à +231

4 octets

TABLEAU 2 : Types entiers C++ permet de spécifier des valeurs octales ou hexadécimales.

-      Constante octale : elle commence par ‘0’’ (Zéro)

-      Constante Hexadécimale : elle commence par ‘0x’’

I = 20              // 20 en décimal

I = 024            // 20 en octal

I = 0x14          // 20 en hexadécimal

3.2 Données de type réel

Les données de type réel se rapportent aux éléments de données qui représentent des objets numériques réels. Ceci inclut les constantes de type réel. Les variables, fonctions et expressions. Les types réels standards de C++ sont les suivants :

Type

Taille

Float

Double

Long double

4 octets

8 octets

10 octets

TABLEAU 3 : Types réels

Les nombres réels peuvent s’écrire soit sous la forme classique (par exemple 3.14), soit sous la forme scientifique (par exemple 2.45 E-5).

4.   VARIABLES et CONSTANTES

4.1 Variables

Une variable est un identificateur qui permet de représenter une valeur modifiable. Une variable possède un nom qui doit être unique dans un certain domaine (portée). Outre le nom, une variable doit posséder un type de donnée précisant au compilateur, le nombre d’octets à allouer à la variable.

Une variable doit être déclarée, n’importe où dans le code, avant son utilisation dans le programme.

Int Somme ;                      //déclaration d’une variable qui a pour nom somme et

                                        //comme type, le type entier float x, Delta;               // déclaration de deux variables de type réel.

                Char c ; // déclaration d’une variable de type caractère

L’écriture des noms de variable doit respecter les règles d’écriture des identificateurs. Lorsqqu’on définit une variable, on peut lui fournir en même temps une valeur initiale. C’est cette valeur que la variable aura lors de sa première utilisation.

Int Somme =0 ;                      // déclaration et initialisation des variables

Float x=10, Delta=12.3 ;

Char c=’’0’’ ;

4.2 Constantes

Il est souvent commode d’associer un élément de donnée simple, tel qu’une valeur numérique, à un identificateur, attribuant ainsi un nom à l’élément de donnée. On appelle l’identificateur une constante si on lui attribue un élément de donnée de manière définitive (la valeur reste inchangée tout au long du programme).

On pourrait considérer une constante comme une variable qui, une fois, initialisée, peut être lue mais non modifiée.

Les déclarations des variables et des constantes se ressemblent. La seule différence consiste en la présence du mot clé const.


Const int NombreMax= 100 ; Const float SalaireMin= 1500.00 ;

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 3

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme calcule et  affiche la surface d’un cercle

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> void main() {

const Pi = 3.14 ; //Pi est une constante float Rayon = 10.0 ; //Rayon est une variable initialisée à 10 printf (‘’surface = %.2f’’, Pi*Rayon) ; //affiche la surface du cercle }

5.   ENTREE / SORTIE DES DONNEES

5.1 Fonction printf ()

On utilise la fonction printf() pour afficher des données sur l’écran. Les éléments de données de sortie peuvent être des chaînes de caractères, des constantes numériques ou les valeurs de variables et d’expressions.

5.1.1 Sortie formatée

Le spécificateur de format ou formateur (comme %d ou %c) sont utilisés pour contrôler le format qui sera utilisé par printf() pour afficher une variable particulière. En général, le formateur doit correspondre au type de la variable à afficher. Nous utilisons, par exemple, le formateur %d pour afficher un entier et %c pour afficher un caractère. La liste suivante fournit les formateurs pour printf() et scanf() ;

Formateur

Description

Printf()

Scan()

%c

Un seul caractère

X

X

%s

Chaîne de caractères

X

X

%d

Entier signé

X

X

%f

Réel (notation décimale)

X

X

%e

Réel (notation exponentielle)

X

%g

Réel (notation décimale)

X

%u

Entier non signé (décimal)

X

%x

Entier non signé (hexadécimal)

X

%o

Entier non signé (octal)

X

1

Préfixe utilisé avec %d, %u, %x, %o pour spécifier un entier long

X

TABLEAU 4 : Caractères formateurs

Le programme suivant affiche l’entier i et le réel x avec les différents formats

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 4

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme affiche un entier et un réel sous différents formats

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> void main()

{

int i = 255 ; float x = 10.0 ; printf (‘’%d %u   %x %o\n’’,i,i,i,i) ; //affichage d’un entier sous différents formats  printf (‘’%f  %e   %g \n’’,x,x,x) ;   //affichage d’un réel sous différents formats }

5.1.2 Largeur du champ

Considérons le programme suivant :

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 5

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme affiche un réel sous différents longueur de champs

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> void main()

{

float x = 10.56 ;

printf (‘’x = %f\n’’ ,x) ;          //affiche 10.560000  printf (‘’x = %5.2f\n’’,x) ;           //affiche 10.56 printf (‘’x = %8.3f\n’’ ,x) ;      //affiche 10.560

}

Nous remarquons que la variable x est affichée, avec la première fonction printf (), avec 6 chiffres après la virgule alors que deux seulement de ces chiffres sont significatifs. Pour supprimer les zéros insignifiants, nous avons inséré la chaîne 5.2 entre le caractère % et f (seconde fonction printf()). Le nombre après le point décimal précise le nombre de caractères qui seront affichés après le point décimal. Le nombre qui précède la point spécifie l’espace à utiliser pour contenir le nombre lorsqu’il sera affiché. 5.1.3 Séquences d’échappement

Dans les exemples précédents, nous avons utilisé le caractère “/n” dans la chaîne de format pour insérer un retour à la ligne suivante. Le caractère nouvelle ligne /n est un exemple de séquence d’échappement. La liste suivante montre les principales séquences d’échapppement :

Séquence

Description

\n

Nouvelle ligne

\t

Tabulation

\b

Retour en arrière avec effacement

\r

Retour chariot

\’

Caractère apostrophe

\’’

Caractère guillemet

\\

Caractère anti-slash

\xdd

Code ASCII Hexadécimal

\ddd

Code ASCII décimal

TABLEAU 5 : Séquences d’échappement

5.2 Fonction scanf()

On utilise cette fonction pour lire des données, de différents types, à partir du clavier. Voici un exemple utilisant la fonction scanf() :

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 6

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme lit une valeur et calcule une expression

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{

clrscr() ;

const int JoursAn = 365 ; float Annees, NombreJours ; printff(‘’Entrez votre age :’’) ;

scanf(‘’%f’’ ,&Annees) ; NombreJours = Annees*JoursAn ;

printf(‘’Votre age en nombre de jours = %.1f jours\n’’ ,Nombre Jours) ;

getch() ; //attend que l’utilisateur appuie sur une touche

}

Nous remarquons que le format de scanf () ressemble beaucoup à celui de la fonction printf () (voir tableau 4). Comme pour printf () l’argument à gauche est une chaîne qui contient le formateur ‘’%f’’ et à droite le nom de la variable &-annee. La fonction scanf () reçoit comme paramètre l’adresse de la variable annees d’où la présence de l’opérateur d’adresse &.

6.   LES EXPRESSIONS

Une expression est un groupe d’opérandes liés par certains opérateurs pour former un terme algébrique qui représente une valeur. Il y’ a deux sortes d’expression : numérique et logique. Une expression numérique donne comme résultat une valeur numérique, alors qu’une expression logique représente une condition qu’est vraie ou fausse.

6.1 Opérateurs arithmétiques

Ils sont utilisés pour effectuer des opérations de type numérique. Le tableau suivant décrit cinq opérateurs très courants qu’on peut utiliser pour créer des expressions numériques

Opérateurs

Signification

+

-

*

/

%

Addition

Soustraction

Multiplication

Division

Reste de la division

TABLEAU 6 : Opérateurs arithmétiques

L’opérateur de division/ appliqué à des entiers donne un résultat entre de sorte que plusieurs divisions différentes peuvent donner le même résultat.

int resultat ; resultat=3/3 ; //resultat = 1 resultat = 4/3 ; //resultat = 1

Si l’on ne désire pas perdre le reste, on peut employer l’opérateur %. Ce dernier, dont l’utilisation est réservée aux entiers, calcule le reste de la division de deux nombres.

int reste ; reste = 3 % 3 ; // reste = 0 reste = 4 % 3 ; // reste = 1

Le programme 7 calcule le polynôme ax2 + bx + c

/*----------------------------------------------------------------------------------------------------------------------

 *PROGRAMME 7

*Fichier : polyncpp

*Auteur :  Mustapha AIT MAHJOUB

*Date : 10/09/1999

*Description : Ce programme calcule l’expression ax2 + bx + c

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h>

#include<conio.h> //pour clrscr() et getch() void main()

{

clrscr() ; float a,b,c,x,y ;

scanf(’’%f %f    %f %f’’ , &a, &b, &c, &x) ;

y = a* x* x + b* x + c ;

printf (‘’ax*x + bx + c = %g\n’’,y) ; getch() ; }

6.2 Opérateurs de manipulation

Les opérateurs de bits agissent au niveau du bit. Les opérandes de ces opérateurs ne sont plus des entiers ou des caractères, mains tous simplement une suite de bits. Un opérateur de bits permet de manipuler les bits individuellement en les positionnant soit à 1 soit à 0. Les opérandes doivent être de type entier. Les opérateurs du tableau 7 suivant permettent d’agir sur des bits particulièrement à l’intérieur d’une variable.

Opérateur

Signification

Exemple

x = 15 ou x = 1111 ou x = 0xF

~

Non(complément)

y = x

y = 0xfff0

<< 

Décalage à gauche

Y = x <<2

y = 0x3c

>> 

Décalage à droite

y = x >> 2

y = 3

&

ET binaire

y = x & 0xa

y =0xa

|

OU binaire

y = x |  0xa

y = 0xf

^

OU-Exclusif

y = x ^ 0xa

y = 5

TABLEAU 7 : Opérateurs de manipulation

6.3 Opérateurs d’incrémentation / decrémentation

L’expression n++ utilise l’opérateur d’incrémentation ++ qui a pour effet d’ajouter 1 à n. Ces opérateurs regroupent deux fonctionnalités : l’effet de bords qui est l’incrémentation ou la decrémentation, et la valeur qu’ils renvoient lorsqu’ils sont utilisés dans des expressions. Cette dernière dépend de la position relative du ++ ou du – par rapport à son opérande, par exemple si a = 5

b = 2*a++

// b =10, a = 6

b = 2*++a

// a =7, b =14

b = ++a-2

// a = 8, b = 6

b = 10 –(- -a)

// a = 7, b =3

6.4 Opérateur sizeof () Cet opérateur renvoie la taille , en nombre d’octets, de l’expression au du type syntaxe : seizeof< expression>     Ou    Sizeof( <type>)

Exemple :  Sizeof (int) renvoie le nombre d’octet qu’occupe un entier

7.   EXPRESSION BOOLEEENNE

Les expressions booléennes prennent des valeurs de vérité vraies ou fausses. Bien que nous parlions de valeurs logiques « vraie » et   « fausse »  n’oubliant pas qu’en fait ce ne sont que des valeurs numériques entières. Si le résultat de l’expression booléenne est 0, l’expression est fausse. Si le résultat est différent de zéro, l’expression est vrai.

7.1 Opérateurs de comparaison

Les opérateurs de comparaison sont tous des opérateurs binaires : ils relient deux opérandes. Le résultat de comparaison  soit vrai(non nul), soit faux( nul).

Le tableau suivant décrit les opérateurs de comparaison.

Opérateur

Signification

< 

Inférieur

> 

Supérieur

<=

Inférieur ou égal

>=

Supérieur ou égal

=  =

Egal

!=

Différent

TABLEAU 8 : Opérateur de comparaison

7.2 Opérateurs logiques

Le langage C  contient trois opérateurs logiques. A l’instar des opérateurs des comparaisons , de résultat d’une expression utilisant les opérateurs logiques soit vrai (non nul), soit faux (nul). Le type de résultat est toujours int. Les opérateurs logiques sont toujours évalués de la gauche vers la droite.

Le tableau suivant décrit les opérateurs logiques.

Opérateur

Signification

Exemple

a = 10, b =3


TABLEAU 9 : Opérateurs logiques

7.3 Opérateur conditionnel ternaire

Jusqu'à présent nous avons rencontré des opérateurs unaires ((NON binaire, incrémentation, etc.) qui manipulent un seul opérande et des opérateurs binaires (addition, division, etc.) qui manipulent deux opérandes. Il existe un opérateur ternaire qui manipule trois opérandes : l’opérateur arithmétique conditionnel. Voici sa syntaxe :

EXPRESSION 1 ;EXPRESSION 2 ; EXPRESSION 3 ;

On commence par évaluer Expression 1. Si elle est vrai (non nulle), alors on évalue Expression 2, si non on évalue Expression 3

Par exemple, pour calculer le maximum de deux nombres, on écrit,

Opérateur

Signification

Exemple

Equivalent

=

Affectation simple

x = 2

*=

Affectation avec multiplication

x * = 2

x = x *2

& &

ET logique

(a>0) && (b<10) est vraie

||

OU logique

(a = = 4) || (b= = 3) est vraie

!

NON logique

! (b = =3) est fausse

Int a, b ; max ; a = 5 ; b = 10 ;

Max = (a>b) ; a :b ; // max = 10 car a n’est pas supérieur à b

8.  INSTRUCTIONS D ‘AFFECTATION

Nous avons déjà vu, dans les exemples précédents, que l’instruction d’assignation (ou affectation) sert à assigner un élément de données à une variable. Considérons l’expression

X= 10 ;

Une fois l’affectation effectuée, la variable x vaut 10. Mais l’expression entière x = 10 possède aussi la valeur 10 de sorte qu’on peut écrire en C ++ l’expression Y = x = 10 ;

Après traitement de l’instruction, x et y valent 10 tous les deux.

En C++, outre l’opérateur =, il existe plusieurs opérateurs d’affectation combinés comme le montre le tableau suivant :

/=

Affectation avec division

x /= 2

x = x /2

%=

Affectation avec modulo

x %= 2

x = x %2

+=

Affectation avec addition

x += 2

x = x +2

-=

Affectation avec soustraction

x - = 2

x = x -2

<<=

Affectation avec décalage à gauche

x<< = 2

x = x <<2

>>=

Affectation avec décalage à droite

x >>= 2

x = x>> 2

&=

Affectation avec ET binaire

x &= 2

x = x &2

|=

Affectation avec OU binaire

x |= 2

x = x |2

^=

Affectation avec OU exclusif binaire

x ^= 2

x = x ^2

TABLEAU 10 : Opérateurs d’affectation

9.  PRIORITE DES OPERATEURS ET ORDRE D’EVALUATION.

Le tableau suivant résume à priorité de tous les opérateurs C++, incluant ceux non encore vus. Les opérateurs apparaissent dans un ordre de priorité décroisante

Les opérateurs sur une même ligne ont la même priorité et leurs opérandes sont évalués dans l’ordre indiqué dans la colonne ordre.

Opérateur

Description

Ordre

( )

Expression

gauche

Sizeof ~ !

Opérateurs unaire

droite

* / %

Opérateurs multiplicatifs

gauche

+ -

Opérateur additif

gauche

<< >>

Décalage binaire

gauche

< >   <=   >=

Opérateurs rationnels

gauche

= =    ! =

Opérateurs d’égalité

gauche

&

ET binaire

gauche

^

OU binaire exclusif

gauche

|

OU binaire

gauche

&&

ET logique

gauche

||

OU logique

gauche

?=

Opérateur ternaire

droite

= * = / = % + =

-= <<= >>= & =

^= |=

Affectations combinées

droite

TABLEAU 11 : Priorité des opérateurs

Quant on ‘est pas certain de la priorité d’un opérateur, on doit utiliser des parenthèses pour assurer le bon ordre d’évaluation des opérateurs. Les parenthèses facilitent la compréhension des expressions.



STRUCTURES DE CONTRÔLE

Le programme doit être conçu de telle sorte que les commandes s’exécutent dans un ordre logique et progressif. C’est ce qu’on appelle le déroulement d’un programme. Toutefois, si on veut que le programme répète plusieurs fois les mêmes instructions ou bien qu’il exécute une instruction que sous certaines conditions, l’approche séquentielle n’est pas pratique.

On utilise des mécanismes de contrôle permettant au programme de se brancher à des sousprogrammes qui prendront en charge des tâches répétitives, répéteront une série d’instructions tant q’ une condition reste vraie ou déclencher une action en fonction d’une condition. Ces trois types de mécanismes de contrôle sont connus respectivement comme branchement, boucles et condition (sélection). Les branchements, boucles et sélection sont tous des déviations temporaire du déroulement linéaire du programme. Ils vous permettent de créer des programmes avec souplesse et puissance.

1.   STRUCTURE SEQUENTIELLE

Dans une structure séquentielle, chaque instruction est  exécutée une fois et seulement une fois, dans le même ordre qu’elle apparaît dans le programme. Les instructions sont exécutées séquentiellement. Les programmes vus aux chapitres précédents sont de type séquentiel.

Figure 1 : Ordinogramme d’une structure séquentielle

2.   STRUCTURE SELECTIVE (ALTERNATIVE)

Une structure de décision est une structure de contrôle conditionnelle qui autorise une action seulement si une condition donnée à une valeur non nulle (Vrai).

2.1 Structure if

If  <condition/expression>

Instruction

Figure 2 : Ordinogramme et syntaxe de la structure if.

Quand le programme atteint la condition ou l’expression, il l’évalue. Si le résultat est vrai (non nul), le programme exécute Instruction, sinon (résultat nul) Instruction est pas exécutée.

Figure 3 : Exemple d’ordinogramme pour if /*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 1

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : Calcule de la remise avec un seul taux

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> void main()

{

const float Taux=0.1 ; float Remise, Montant Remise=0.0 ;

printf(‘’Enter montant ;’’) ; scanf(‘’%f’’, &Montant) ; if (Montant>=1000.0)

Remise = Montant*Taux ; Montant =Montant-Remise ;

printf(‘’Montant..=%.2f\n’’, Montant) ; }

L’exemple du programme 1 montre comment calculer le montant à payer par un client en lui accordant une remise. L’utilisateur saisit le montant. Si ce montant est supérieur à 1000, une remise avec un taux de 10% est faite (Remise Montant*taux), sinon pas de remise (Remise = 0). Après, le montant est calculé (Montant = Montant – Remise) puis afficher.

2.2 Structure

L’ordinogramme et la forme de cette structure sont

If ( <Condition/expression> )

Instruction 1

Else

Instruction 2

Figure 4 : Ordinogramme et syntaxe de la structure

Quand le programme atteint la condition, il l’évalue. Si la condition est vraie (expression non nulle), instruction 1 est exécutée, sinon Instruction 2 est exécutée. L’une des instructions s’exécute toujours (mais jamais les deux).

Figure 5: Exemple d’ordinogramme pour

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 2

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : Calcule de la remise avec deux taux

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include <conio.h> void main()

{ const float Taux 1=0.1, Taux 2=0,05 ; float Remise, Montant printf(‘’Enter montant ;’’) ; scan(‘’%f’’ ,&Montant :’’) ;

if (Montant>=1000.0)

Remise = Montant*Taux 1; else

Remise = Montant*Taux 2; Montant =Montant-Remise ; printf(‘’Montant..=%.2f\n’’, Montant) ; getch() ; }

L’exemple du programme 2 montre comment calculer le montant à payer par un client en lui accordant une remise. L’utilisateur saisit le montant. Si ce montant est supérieur à 1000, une remise avec un taux de 10% (Taux 1) est faite. Sinon on accorde une remise avec un taux de 5% (Taux2). Après, on calcule le montant (Montant = Montant – Remise) puis on l’affiche.

2.3 Structures if imbriquées

Les structures if peuvent s’imbriquer l’une dans l’autre, tout comme n’importe quelle autre structure de contrôle. L’imbrication des structures if doit être manipuler avec beaucoup d’attention afin d’éviter toute ambiguïté possible.

L’exemple suivant montre la forme générale d’imbrication à deux niveaux que peuvent prendre les structures if imbriquées.

Figure 6 : Organigramme et syntaxe de la forme générale de structures if imbriquées

Dans cette forme d’imbrication à deux niveaux, Condition 1, Condition 2 et Condition 3 représentent des expressions, et Bloc 1, Bloc 2, Bloc 3 et Bloc 4 représentent des blocs d’instructions. Dans ce cas, une structure complète sera exécutée si Condition 1 est vrai, et une autre si condition 1


est fausse. IL est évidemment possible que Bloc 1, Bloc 2, Bloc 3 et Bloc 4 contiennent d’autres structures . Nous aurions alors une imbrication à plusieurs niveaux.

Programme 3 : Ecrivons un programme C qui résout une équation du deuxième degré Ax2 + Bx + C =  0

La résolution de l’équation se déroule de la manière suivante :

1.  Lecture des coefficients A, B et C

2.  Si la valeur attribuée à A est nulle (A = 0), il s’agit d’une équation de premier degré2.1 Si la valeur de B et zéro, deux cas se présentent :

2.1.1 Si C = 0 :

L’équation Ax2 + Bx + C = 0 quelle que soit la valeur de x  Dans ce cas la solution est l’ensemble des valeurs réelles.

2.1.2  Sinon (C <> 0) : exemple C = 2

L’équation Ax2 + Bx + C = 0 => 2 = 0 ce qui est impossible. Donc l’équation n’a pas de solution.

2.2 Sinon (B <> 0) : Exemple B = 5 ; C = 10

L’équation à une seule solution qui est X = -C/B = -2

Figure 7 : Ordinogramme de résolution d’une équation de deuxième ordre

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 3

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : résolution d’une équation de deuxième degré

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h>

#include<math.h> //prototype de sqrt

#include<conio.h> void main()

{ float A,B,C,Delta,X1,X2 ; clrscr() ; scan(‘’%f’’ ,&A) ; scan(‘’%f’’ ,&B) ; scan(‘’%f’’ ,&C) ;

IF ( !A)

{

if ( !B)

{

if ( !C) printf(‘’Infinité de solutions’’) ;

else printf(‘’Pas de solutions’’) ;

}

else

{

X1 = -C/B ;

Printf(‘’X = %g’’ ,X1) ;

}

}

else

{

Delta = B*B – 4*A*C ; if (Delta < 0)

  Printf(‘’Pas de solutions relles’’) ;

else   if ( !Delta)

Printf(‘’Solution double X1 = X2 = %g’’ ,-B/(2*A)) ;

  else

   {

X1 =(-B –sqrt(Delta))/(2*A) ;

X2 =(-B +sqrt(Delta))/(2*A) ;

Printf(‘’X1 = %g\nX2 = %g’’ ,X1,X2) ;

   }

}

}

2.4 Structure switch

La structure se définit comme une structure conditionnelle de contrôle qui permet de sélectionner un groupe particulier d’instructions parmi plusieurs groupes possible. La sélection s’effectue sur la base d’une expression, appelé sélecteur.

Voici la forme générale de la structure swich

Switch <expression>

{

case <const-exp-1> :

<bloc1>

case <const-exp-2> :

<bloc2>

case <const-exp-3> :

<bloc3>

case <const-exp-N> :

<blocN>

default

<bloc>

}

Forme de la structure switch

Le sélecteur <expression> peut appartenir à n’importe quel type entier. Il prend souvent la forme d’une seule variable de type entier.

Chacune des références de cas (cas <const-exp-1,case const-exp-2 ,…) représente une des valeurs constante autorisées du sélecteur. Donc si l’expression du sélecteur est de type entier, les références de cas représentent des valeurs entières se situant dans la gamme des possibilités. Les références de cas n’ont pas besoin de figurer dans un ordre particulier, mais chacune d’entre elles demeure cependant unique.

En cas de non-correspondance, et il existe un label default, le contrôle passe au bloc d’instruction <Bloc>.

Dans le programme suivant, le sélecteur Choix est une variable de type char. Suivant la valeur fournie par l’utilisateur à cette variable, le traitement sera aiguillé à l’instruction dans l’étiquette correspond à celle fournie. Si par exemple, l’utilisateur a tapé le caractère + l’instruction Resultat = Valeur 1 + Valeur 2 sera exécuté puis le contrôle passe à l’instruction qui suie le bloc le switch.

L’instruction break permet de sortir du blos de l’instruction switch. *-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 4

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :04/02/99

*Description : Calcul la somme, la différence , le produit ou le quotion de deux nombres

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{ char Choix ;

float Valeur 1 , Valeur 2, Resultat ; clrscr() ;

printf(‘’Addition…………………(+)/n’’) ; printf(‘’Soustraction…………………(-)/n’’) ; printf(‘’Multiplication …………………(*)/n’’) ;

printf(‘’Division…………………(/)/n’’) ;

printf(‘’Entrer votre choix : ‘’) ; Choix = getche() ; printf(‘’\nValeur 1 = ‘’) ; scanf(‘’%f’’,&Valeur 1) ; printf(‘’\nValeur 2 = ‘’) ; scanf(‘’%f’’,&Valeur 2) ;

switch(Choix)

{

case’+’ :{Resultat = Valeur 1 +Valeur 2 ; break ;} case’-’ :{Resultat = Valeur 1 -Valeur 2 ; break ;} case’*’ :{Resultat = Valeur 1 *Valeur 2 ; break ;} case’/’ : if (Valeur 2 = = 0) printf(‘’\nDivision par zéro’’) ; else

Resultat = Valeur 1/Valeur 2 ; Break ; Default : printf(‘’\n Opérateur incorrect’’) ;

}

printf(‘’\n Resultat = %g’’, Resultat) ; getch() ;

}

3.   STRUCTURES ET REPETITIVE S (BOUCLES)

Vous pouvez désirer que votre programme exécute les mêmes instructions de façon répétitive tant qu’une certaine condition reste vraie.

En programmation, ceci s’appelle une boucle. Le programme répète les mêmes instructions dans une boucle jusqu’au moment où la condition n’est plus vraie (ou n’est plus fausse). C possède plusieurs formes de boucles qui seront présentés dans la suite.

3.1 Structure while

La structure while correspond à une instruction de contrôle répétitive utilisée pour la réalisation de boucles conditionnelles. Voici l’organigramme et le forme générale de cette structure :

Figure 8 :Organigramme est formé de la structure while

Instruction s’exécute continuellement aussi longtems que l’expression booléenne <Condition/Expression demeure vraie (non nulle). Dès que <condition/Expression> devienne fausse, on sort de la boucle.

Servons nous de la structure while pour obtenir la moyenne d’une liste de N nombres. Nous utilisons une variable Somme initialement mise à zéro et mise à jour à chaque lecture d’un nombre nouveau dans la mémoire.

Supposons que l’utilisateur a donné la valeur 3 à la variable N. En entrant dans la boucle la variable Compte a pour valeur 1 donc inférieur à N. La condition « Compte = N » est vraie et les instructions continuent dans le bloc de while seront exécutées. On lit un nombre(Nombre = 10) puis on l’ajoute à l’ancienne somme (Compte = 0 + Nombre = 10) ensuite, la variable compte est incrémentée de 1 (Compte = Compte + 1 = 1 + 1 = 2). La variable compte est comparé à une deuxième fois avec la variable N. Le résultat de la comparaison est vrai(Compte<= N ou 2 <= 3) donc la boucle est exécutée une deuxième fois en lisant un nouveau nombre(Nombre = 1) suivi du calcul de la somme (Somme = Somme + Nombre = 10 + 20 = 30) et l’incrémentation de compte (Compte = Compte + 1= 2 + 1 = 3). La condition est toujours vraie. La boucle sera exécutée une troisième fois. Un nombre est lu(Nombre = 60) puis ajouté à l’ancienne somme (Somme =30 + 60 = 90)suivi de l’incrémentation de compte (Compte = Compte + 1 = 3 + 1 = 4). La variable compte est comparée avec N (4<= 3). Le résultat de la comparaison est faux . On sort de la boucle pour calculer la moyenne et afficher la somme et la moyenne.

Figure 9 : Organigramme de calcul de la moyenne des nombres

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 5

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : calcul de la moyenne en utilisant la boucle while

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{ float Somme = 0.0, Nombre, Moyenne ;

int Compte = 1,N ;

printf(‘’Nombre d’éléments :’’) ;

scanf(‘’%d’’,&N) ; while (Compte <= N) { printf(‘’Un nombre :’’) ; scanf(‘’%f’’,&Nombre) ;

Somme +=Nombre ;

Compte++ ; }

Moyenne = Somme /N ; printf(‘’Somme =%g\n’’ ,Somme) ; printf(‘’Moyenne = %g’’ ,Moyenne) ; getch() ;

}

3.1 Structure do..while

L’organigramme et la forme générale de cette structure sont

do

instruction

While (<Condition/Expression)

Figure 10 : Organigramme est forme de la structure do..while

Instruction est exécuté continuellement jusqu’à ce que la condition <Condition/Expression> soit égale à zéro (fausse). La différence avec while est que <Condition/Express> est testée après, et non avant, chaque exécution de la boucle. Le système suppose qu’il y a au moins une exécution du bloc d’instructions.

Le programme suivant utilise la structure do..while pour calculer la moyenne des notes.

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 6

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : calcul de la remise en  utilisant la boucle do

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{ float Somme = 0.0, Nombre, Moyenne ; in Compte = 1,N ;

printf(‘’Nombre d’éléments :’’) ;

scanf(‘’%d’’,&N) ;

do

{ printf(‘’Un nombre :’’) ; scanf(‘’%f’’,&Nombre) ;

Somme +=Nombre ;

Compte++ ;

} while (Compte <= N) ; Moyenne = Somme /N ; printf(‘’Somme =%g\n’’ ,Somme) ; printf(‘’Moyenne = %g’’ ,Moyenne) ; getch() ;

}

3.2 Structure for

La format de cette structure est

for(<Init/Exp> ; <Test/Exp> ;<Incr/Exp>)

<Bloc d’instruction>

La séquence d’événement est la suivante :

1.   L’expression d’initialisation <Init/exp> est exécutée. Comme son non l’indique, il s’agit d’une instruction qui initialise un ou plusieurs compteurs de boucle mais la Syntaxe permet une expression d’un quelconque degré de complexité(y compris des déclarations). D’où l’affirmation que tout programme C peut être écrit sous la forme d’une seule boucle for.

2.   L’expression <Test/Exp est évaluée suivant les règles de la boucle while. Si <Test/Exp> ets différente de zéro (vraie), la boucle est exécutée. Une expression vide est prise ici comme while (1 ou vrai) . Si <Test/Exp> est égal à zéro (fausse).L a boucle prend fin.

<Incr/Exp>incrémente les compteurs

Le Bloc d’instruction est exécuté et le contrôle revient à 2.

Le programme suivant utilise la structure for pour calculer la moyenne des notes.

*---------------------------------------------------------------------------------------------------------------------

*PROGRAMME 7

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : calcul de la moyenne en  utilisant la boucle for

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> #include<conio.h> void main()

{ float Somme = 0.0, Nombre, Moyenne ; in Compte = 1,N ; clrscr() ;

printf(‘’Nombre d’éléments :’’) ;

scanf(‘’%d’’,&N) ;

for(Compte = 1 ; Compte <= N ; Compte ++)

{ printf(‘’Un nombre :’’) ; scanf(‘’%f’’,&Nombre) ;

Somme +=Nombre ;

}

Moyenne = Somme /N ;

Printf(‘’Somme =%g\n’’ ,Somme) ; Printf(‘’Moyenne = %g’’ ,Moyenne) ; getch() ; }

Si dans cet exemple, l’utilisateur a donné la valeur 3 à la variable N. Compteur prendra successivement les valeurs 1,2 et 3, ce qui cause trois exécutions de la boucle à chaque fois, un nombre est lu puis ajouter à Somme. La sortie de la boucle for est faite lorsque la variable compte aura atteint la valeur de N.

4.  INSTRUCTIONS DE BRANCHEMENT

Une instruction de branchement, lorsqu’elle est exécutée, passe le contrôle à la suivante. Il existe quatre instructions de branchement :break, continue, goto et return.

4.1 Instruction break

Une instruction break ne peut s’utiliser que dans itération (while, do..while et for) ou un switch. Elle marque la fin d’une instruction d’itération ou de switch.

Le programme suivant determine la valeur de N pour laquelle la somme 0 + 1+ 2 +………+ N est supérieur ou égale à une valeur donnée.

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 8

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/02/99

*Description : utilisation de break dans un boucle while

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main()

{ int Valeur, Somme, N ; Somme = N = 0 ;

clrscr() ;

scanf(‘’%d’’,&Valeur ;

while(1) //condition est toujours vraie

{

if (Somme >= Valeur) break ;//sortie forcée de la boucle

Somme +=N++ ;

}

printf(‘’%d\n ‘’,N-1) ; getch() ;

}

 4.2 Instruction continue

La syntaxe de cette instruction est

Continue ;

Elle n’est utilisable que dans une instruction d’itération.. Elle passe le contrôle à la condition de test pour les boucles while et do, et à l’expression d’incrémentation dans une boucle for.

Dans le cas de boucles d’itération imbriquées, une instruction continue est considérée comme appartenant à l’itération la plus proche la contenant.

*----------------------------------------------------------------------------------------------------------------------*PROGRAMME 9

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/02/99

*Description : utilisation de mot clé continue dans un boucle while

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{ int Valeur, Somme, i, Nombre ; ;

Somme = i = 0 ;

Clrscr() ;

While (i+ + <5)

{

Scanf(‘’%d’’,&Nombre;

If (Nombre< 0) continue ;

Somme +=Nombre;

}

printf(‘’%d\n ‘’,Somme) ; Getch() ;

}

4.3 Instruction goto

La syntaxe est

Goto label ;

L’instruction goto passe le contrôle à l’instruction label qui doit être dans la même fonction.

Il est illégal de sauter une instruction de déclaration ayant une valeur d’initialisation implicite ou explicite à moins que cette déclaration ne soit dans un bloc interne déjà ignoré.


TYPE DE DONNEES COMPLEXES

1.   LES TABLEAUX

1.1 Tableaux unidimensionnels

Un tableau unidimensionnel est une liste de données de même type auxquels on se refaire collectivement par le même le nom. On peut accéder à chaque élément individuel en spécifiant le nom du tableau, suivi par un indexe (ou indice) cerné par des crochets. Donc si une liste de note d’un tableau unidimensionnel contient N éléments, les éléments individuels du tableau sont Note [0], Note[1]……Note

[N-1]

1.1.1    Déclaration d’un tableau

La déclaration d’un tableau comprend trois parties : -      L’indication de type - Le nom du tableau.

                        -    Le nombre d’éléments (entre crochet) du tableau (ou taille).

<type> <non> [ <nombre d’élément> ] ;

L’exemple suivant est une déclaration d’un tableau de 25 notes :

Float Note [24] ;

Ou

Const int N = 24 ; Float Note [N] ;

La taille du tableau doit être une expression constante (connu au moment de la compilation).

1.1.2    Initialisation des tableaux

On peut initialiser un tableau lors de sa déclaration. Il suffit de fournir la liste des valeurs des divers éléments placées entre accolades et séparées entre elles par des virgules.

Int JoursMois [11] = {31,30,31,30,31,30,31,31,30,31,30,31} ;

Quand on initialise un tableau dans sa déclaration, on peut omettre la taille. Celle ci est déterminée par le compilateur par le nombre de valeurs d’initialisation. Le tableau JoursMois peut être déclaré par Int JoursMois [] = {31,30,31,30,31,30,31,31,30,31,30,31} ;

Les points suivants doivent être respecter lors de l’utilisation des tableaux :

-    On ne peut pas initialiser un tableau à partir d’un autre tableau.

-    Les affectations entre tableaux dont interdites

Float Vec1[10], Vec2[10] ;

Vec 1 = Vec 2 ; // erreur

-    Toute expression donnant un résultat entier peut être utilisée comme indice

Int i,j ;

Float x = 1.0 ;

Float Vect[10] ;

Vec[5] = Vec[i + j] ; //correct i + j est un entier

Vec[4] = Vec[x] ; //correct x n’est pas un entier

-    Le compilateur ne vérifie pas si l’indice d notes et en calculer la moyenne et l’écart de chacune de ces notes par rapport à la moyenne à l’aide de la formule.

Ecart[i] = Note[i] – Moyenne.

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 1

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : utilisation des tableaux pour calculer les écarts simples

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{ float Somme,Moyenne ; float Note[MAX_ELEMENT] ;

Ecart[MAX_ELEMENT] ;

Int i,N ;

// Lecture des notes

clrscr() ;

printf(‘’Nombre d’éléments :’’) ;

scanf(‘’%d’’,&N) ;

for (i=0 ;i<N ; i++)

{ printf(‘’Note[%d]’’ i) ;

scan(‘’%f’’,&Note[i]) ;

}

//calcul de la somme des notes for (i=0, Somme =0 ; i<N i++) Somme +=Note[i] ; //calcul de la moyenne

Moyenne = Somme /N ;

//calcul des écarts simples for (i=0 ; i<N ; ++)

Ecart[i] = Note[i] – Moyenne ;

//Affichage des résultats clrscr() ;

printf(‘’Moyenne =%2f\n’’, Moyenne) ;

printf(‘’Note\t\tEcart\n’’) ; for (i=0 ; i<N ; i++) printf(‘’%.2f\t\t%.2f n’’,Note[i],Ecart[i]) ; getch() ;

}

1.2 Tableaux multidimensionnels

Nous avons déjà envisager un tableau unidimensionnel sous la forme d’une liste (sur une seule colonne) de données de même type . Les tableaux multidimensionnels constituent une extension de ce concept. On peut ainsi imaginer un tableau à deux dimensions comme un tableau de données composé de lignes et de colonnes. Supposons, par exemple, que Matrice est tableau à deux dimensions contenant M lignes et N colonnes. Les éléments individuels du tableau sont Matrice [0] [0],..,Matrice[0] [N-1], …,Matrice[M-1] [0],…,Matrice[M-1] [N-1].

Le tableau se visualise de la manière suivante :

Matrice[0] [0]……………………………………………….Matrice[0] [N-1]

                                                               .                                                                                              .

.            . Matrice =      .           . .         .

                                                               .                                                                                              .

                                               Matrice [M-1][0]                                                                   Matrice [M-1][N-1]

1.2.1    Déclaration d’un tableau multidimensionnel

Quelle que soit sa dimension, un tableau comprend toujours une collection de données de même type.

On peut définir un tableau multidimensionnel dans une déclaration de variable, de la même façon que pour chacune des dimensions du tableau

<type> <nom> [nombre de ligne>][<nombre de colonne>] ;

Par exemple,

Float Matrice[3][3] ;

Matrice est tableau à deux dimensions. Il peut stocker 3x3=9 éléments de type float.

L’accès aux différents éléments se fait comme avec les tableaux à une dimension, à ceci près que l’on a besoin de deux indices. Par exemple, pour calculer la somme des éléments de la première ligne Somme  = Matrice[0][0] + Matrice[0][1] + Matrice[0][2] ;

1.2.2    Initialisation d’un tableau multidimensionnel

On peut initialiser un tableau multidimensionnel dès sa déclaration. Par exemple, pour initialiser Matrice à zéro

float Matrice [][] = {

{0,0,0},

{0,0,0},

{0,0,0}

}

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 2

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : calcul la somme et le produit de deux matrices

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#definie MAX_LIGNE 10

#definie MAX_COLONNE 10

// Définnition d’un nouveau type MATRICE

type de f float MATRICE[MAX_LIGNE][MAX_COLONNE] ; void main ()

{

int ligne,colonne ;

MATRICE Mat1,Mat2,MS,MP ;

Clrscr() ;

printf(‘’Matrice1\n ’’) ;

For (inti=o ;i<ligne ;i++) // boucle de lignes

For (intj=o ;j<colonne ;i++) // boucle de colonnes

{ printf(‘’Mat1 ![%d],[%d]=’’,i,j) ;

scanff(‘’%f’,&Mat1[i][j] ;

}

//lecture de la deuxième matrice printf(‘’Matrice2\n’’) ; for(i=0 ;i<ligne ;i++)

for (int j=0 ;j<colonne ;j++)

{ printf(‘’Mat2[%d],[%d]=’’,i,j) ;

scanf(‘’%f’’,&Mat2[i][j] ;

}

//somme de deux matrices for(i = 0 ;i<ligne ;i++) for (int j=0 ;j<colonne ;j++)

MS[i][j] = Mat 1[i][j] + Mat2[i][j] ;

//Produit de deux matrices for (i=0 ; i<ligne ; i++)

for (int j=0 ; j<colonne ; j++)

{

MP [i][j] = 0.0 ;

//produit d’une ligne par colonne for (int k=0 ; k<ligne ; k++)

{

MP[i][j] =MP[i][j] + Mat1[i][k]*Mat2[k][j] ; }

}

//affichage matrice somme printf(‘’Matrice Somme\n’’) ; for (i=0 ; i<ligne ; i++)

for (int j=0 ; j<colonne ; j++)

{ printf(‘’MS[%d][%d]=%g\n’’,i,j,ms[i][j] ; }

//affiche matrice produit printf(‘’Matrice Produit\n’’) ; for(i=0 ; i<ligne ;i++)

for(int j=0 ; j<colonne ; j++)

{ printf (‘’MP[%d][%d]=%g\n’’,i,j,MP[i][j]) ;

} getch() ;

}

2.   LES CHAINES DE CARACTERES

Les chaînes de caractères sont des formes de données utilisées pour stocker et manipuler le texte. En C++, il n’existe pas de type de données spécifique aux chaînes de caractères. Pour gérer des chaînes de caractères, il faut donc passer par des tableaux de chair. L’exemple suivant définit une chaîne de caractères.

Char Nom[] = ‘’Nacer’’ ;

Ou

Char Nom[6] = ‘’Nacer’’ ;

On reserve ici, de l’espace mémoire pour stocker 6caractères. Les 5 premiers sont initialisés avec les caractères ‘N’, ‘a’, ‘c’, ‘e’, ‘r’. Le dernier est initialisé avec le caractère terminateur nul ‘\o’ marquant la fin de la chaîne.

On peut, aussi, initialiser une chaîne avec une liste de caractères

Char Nom[] = { ‘N’, ‘a’, ’c’ , ‘e’, ‘r’, ‘-0’} ;

2.1 Fonction d’ E / S des chaînes de caractères

La fonction, de la librairie C++, gets() permet de saisir une chaîne à partir du clavier . Elle n’est pas universelle comme scanf() ; elle est écrite seulement pour lire une chaîne. Le caractère retour chariot indique la fin de la lecture d’une chaîne. On peut ainsi inclure des espaces et des tabulations comme caractères de la chaîne.

La fonction puts(), qui va en pair avec gets(), permet d’afficher une chaîne sur l’écran. L’exemple suivant lit une chaîne puis l’affiche sur l’écran : Char Nom[81] ;

gets(Nom) ;// le nombre de caractère inférieur à 81 puts(Nom) ;

2.2 Fonctions de traitement des chaînes

La bibliothèque C++ fournit un ensemble de fonctions de traitement des chaînes. Pour les utiliser, il suffit d’inclure le fichier d’en tête string h dans votre programme, voici quelques unes de ces fonctions (pour plus de détailles consulter l’aide) :

strlen(chaîne) :calcul la longueur d’une chaîne strcpy(destination,source) :copie une chaîne dans une autre strcpy(destination,source,N) :copie N caractères de la chaîne source dans la chaîne destination.

Sttrcat(destination,source) :concatène destination et source.

Strncat(destination,source,N) :concatène Ncaractère de la source avec destination Strcmp(destination,source) :compare destination et source.

Les programmes 3 et 4 suivants montrent l’utilisation de quelques fonctions de manipulation des chaînes.

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 3

*Fichier : chaî

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : manipulation des chaînes

----------------------------------------------------------------------------------------------------------------------*/ #include<conio.h>

#include<stdio.h>

#include<string.h>

void main ()

{ char ch1[20]=’’Bon’’,ch2[20]=’’Jour’’ ; int i ;

printf(‘’Longueur de chaîne 1 :%d’’,strlen(ch1)) ; strcpy(ch1,che) ; puts(ch1) ; //affiche ‘’Jour’’ strcpy(ch1,’’Bon’’) ;

strncpy(ch1,ch2,2) ;//les 2 caractères ‘’JO’’ de ch2 remplace ‘’BO’’ puts(ch1) ; strcpy(ch1,’’Bon’’) ; strcat(ch1,ch2) ;

puts(ch1) ;//affiche ‘’BonJour’’ strcpy(ch1,’’Bon’’) ; strncat(ch1,ch2,1) ; puts(ch1) ;//affiche ‘’BonJ’’ strcpy(ch1,’’Jour’’) ; i= strcmp(ch1,ch2) ;

printf(‘’%d\n’’,i) ;//affiche 0 puisque ch 1 = ch 2 getch() }

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 4

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : inverse une chaîne, par exemple NACER devient RECNA

----------------------------------------------------------------------------------------------------------------------*/ #include<conio.h>

#include<stdio.h> #include<string.h>

void main ()

{ char ch1[20],ch2[20] ;

int L ; clrscr() printf(‘’Enter une chaîne ;’’) ; gets(Ch1) ;//saisir abonjour

L = strlen(Ch1) ;//L = 7

Strcpy(Ch2,Ch1) ;//Ch2 = ‘’BONJOUR’’

For (int i=0 ; i<L ; i++)

Ch2i = Ch1{L-i-1] ;

puts(Ch2) ;//affiche « RUOJNOB »

Getch()

}

3.   LES STRUCTURES

Nous avons déjà vu comment une variable simple peut contenir une seule information d’un type donné et comment un tableau peut contenir une collection d’information de même type . Ces deux mécanismes de stockage des données peuvent résoudre une grande variété de problèmes. Mais, il arrive souvent qu’on désire utiliser des ensembles d’éléments de données de différents types comme une seule entêtée dans ce cas, l’utilisation des variables et des tableaux est inadéquate.

Supposons qu’on désire stocker le nom d’un employer, son salaire et le nombre de ses enfants. On peut stocker ces informations dans trois variables séparées : une pour le nom, une autre pour le salaire et une autre pour le nombre d’enfants. Cette façon de faire n’est pas pratique : dans la vie, il est naturel, de regrouper les éléments (Nom, Salaire et Nombre Enfants) en une seule entité appelée structure.

Les structures sont une caractéristiques très puissante de C++, et facilite l’organisation et le traitement des informations.

3.2 Déclaration d’une structure

Pour déclarer une structure, on utilise le mot clé struct, puis le nom de la structure. En suite, entre accolades, les variables qui constituent la structure, par exemple :

Struct employe] ;]

{ char Nom[81]

float Slaire ; int Nombre Enfants ;

} ;

Cette instruction définit un nouveau type de données appelé struct employer. Caque variable de ce type est constituée de 3 éléments (ou membres) : une variable chaîne de caractères appelée Nom, une variable de type réel Salaire, et une variable de type entier Nombre Enfants.

Il faut noter que cette instruction ne déclare aucune variable donc il n’y a pas de réservation mémoire. Il indique, simplement au compilateur les différents éléments de la structure.

3.3 déclaration de variables d’une structure

Une fois, on a définit la structure, on peut déclarer une ou plusieurs variables qui ont pour type structure on tapant le nom de la structure, puis le nom de la variable.

Pour définir une variable de la structure employée , on écrit

employe Salaire ;

Cette instruction réserve de l’espace mémoire, pour la variable Salaire pour contenir tous les éléments de la structure : 81 octets pour Nom, 4 octets pour Salaire, et 2 octets pour Nombre Enfants.

3.3 Accès aux membres de la structure

Après avoir créé une structure, puis une variable de cette structure, on accède aux membres en tapant le nom de la variable, puis un point, puis le nom du membre.

Par exemple, pour affecter des valeurs aux différents membres de la variable Salaire, on écrit :

[] = ‘’Hassan’’ ;

Salaire.Salaire = 3000.0 ;

Salaire.NombreEnfants = 2 ;

L’opération point, connecte le nom de la variable structure avec les membres de cette structure. Le programme suivant utilise la structure employe

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 5

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : manipulation des structures

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{ const float Allocation = 150.00 ; struct employe//declaration de la structure

                                                               {          char Nom[30]

float Salaire Base ;

int Nombre Enfants ;

} ;

float Salaire ;

employe Agent ;//déclaration d’une variable de la structure clrscr() ; printf(‘’Enter le nom’’) ;

gest() ;

printf(‘’Enter salaire de base :’’) ; scanf(‘’%f’,&Agent.Salaire Base) ; printf(‘’Enter Nombre d’enfants : )

Slaire = Agent.Salaire Base + Agent.Nombre Enfants*Allocation.

printf(‘’Salaire : %.2f’, Salaire); getch();

4    LES POINTEURS

Le pointeur fournit un autre moyen pour accéder à une variable sans se réferer directement à celle ci. Plus les données deviennent complexes, pour gérer à l’aide des variables des informations dont la taille varie.

La différence entre une variable et un pointeur est que la variable pointe toujours sur le même emplacement mémore, alors que le pointeur peut être modifier de façon qu’il pointe sur un autre emplacement en mémore.

4.1 Déclaration des pointeurs

Pour créer un pointeur vers un type de données, créer une variable de ce type de données mais placer un astérisque devant son nom. La déclaration suivante:

                                                               Int       *p;

Alloue une variable p pouvant contenir l’adresse d’un entier. Maintenant, *p est l’entier dont l’adresse est contenue dans p, par exemple:

                                                               Int n= 5;

P = &n;//stocke l’adresse de n dans p

*p + = 2;//incrémente n de 2

Dans l’instruction p = &n, & est l’opérateur d’adresse renvoyant de la variable n. Considérons le programme suivant :

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 6

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : manipulation des structures

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{ int x = 4 float y = 10.0 ;

int *px ;//pointeur sur un entier float *py ;//pointeur sur un réel clrscr() ;

printf(‘’x = %d\t,y = %g\n’’,x,y) ; px = &x ;//px contient l’adresse de x py = &y ;//py contient l’adresse de y

*px = *px + 10 ;//ajoute 10 … la valeur contenue dans x

*py = *py / 5 ;//divise par 5 le contenu de y printf(‘’x = %d\t,y = %g’’ ,x,y) ; getch() ; }

Après avoir afficher la valeur de x et de y, les adresses des variables x et y sont affectées aux pointeurs px et py.

Px = &x ;//px contient l’adresse de x

Py =&y ;//py contient l’adresse de y

En suite, l’opérateur d’instruction * est utilsé dans les instructions d’assignation

*px = *px +10 ; *py = *py / 5 ;

Dans l’instruction *px = *py + 10, nous prenons le contenu de la variable pointée par px (x = 4), lui ajoutons 10. Le résultat est retourné dans la variable pointée par px (x = x + 10 = 14). Le contenu de la variable y est divisé par 5 dans l’instruction *py = *py / 5.

 Remarques :

La déclaration suivante :

Int *p, q ;

ne déclare pas deux pointeurs p et q, mais un pointeur p et entier q. Pour déclarer p et q comme pointeur, il faut écrire

Int *p, *q ;

Ou

Int*p ;

Int *q ;

Le mot clé const interagit de façon étrange avec la déclaration des pointeurs :

Const  int*p ;

déclare un pointeur sur une constante entière, et non pas un pointeur constant sur un entier. Cela veut dire que l’on peut regarder la valeur de *p. mais que l’on ne peut pas la modifiée. Ecrire

*p = 0 ;//erreur modification d’une constante

générera une erreur alors que

p++ ;//p n’est pas constant don peut être modifié

est autorisée.

Pour déclarer un pointeur constant, il faut placer le mot clé const à côté du non du pointeur

Int*  const q = 10 ;

q ne peut pas être modifié, mais on peut modifier le contenu de la variable sur laquelle il pointe ;

*q = 10 ;// est correct q++ ; //erreur

4.2 Tableaux et pointeurs

Les tableaux et les pointeurs sont intimement liés en C++. Le compilateur translate la notation d’un tableau en notation pointeur, puisque l’architecture interne d’un microprocesseur comprend les pointeurs mais pas les tableaux. Lorsqu’ on déclare un tableau, comme par exemple :

int v[10] ;

Le nom du tableau v représente un pointeur constant pointant sur l’élément d’indice 0 du tableau. De même vecteur +1 représente l’adresse de l’élément suivant et *(v+1) l’entier stocké à cette adresse. Dans le cas général ou p, un pointeur et n, un entier on a :

p[n] = ù(p+n) ;

Si un pointeur pointe sur un tableau, on peut le faire se déplacer sur les éléments en lui ajoutant ou retranchant des valeurs entières. Ce pointeur sur un entier ajoute en fait sizeof(int) à l’adresse contenue dans le pointeur.

Pour voir la relation entre les tableaux et les pointeurs. Considérons le programme suivant . Le premier utilise la notation des tableaux et le second la notation des pointeurs.

*-----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 7

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : utilisation des tableaux

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{ int Nombre[] = {10,20,30,40,50} ; clrscr()

for (int i=0 ; i<5 ; ++)

{

Nombre[i] = Nombre[i]+5 ;

Printf(‘’Nombre[%d]=%d\n’’,i,Nombre[i] ;

}

getch()

}

L’expression Nombre [i] est utilisée pour accéder à chaque élément du tableau.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 8

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : utilisation des pointeurs sur des tableaux

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{ int Nombre[] = {10,20,30,40,50} ; clrscr() ;

for (int i=0 ; i<5 ; i++)

{

*(Nombre+i) = *(Nombre +i)+5 ;

printf(‘’Nombre[%d]=%d\n’’,i,*(Nombre+i)) ;

}

getch(),

}

Cette version de programme est identique au précédente, sauf pour l’expression *(Nombre +i)

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 9

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : Saisir des températures par jour, puis en calculer la moyenne. La saisie du nombre >=100

indique la fin de saisie

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{

float Tempr[40], float Somme = 0.0, Moyenne ; int Nombre Jours, Jour =0 ; float *p ;

clrscr() ;

p = Tempr ; //initialise le pointeur avec l’adresse du tableau do

{ printf(‘’Température[%d] :’’, Jour ++) ; scanf(‘’%f’,p) ;

}

while (*(p++) <100) ; //r,p,ter tant température<100 p= Tempr ; //initialise le pointeur avec l’adresse du tableau. Nombre Jours= Jour –1 ; //nombre de temp,ratures lues if (Nombre Jours >=1)

{ for(Jour = 0 ; Jour <Nombre Jours, Jour ++)

Somme += *(p++) ;//calcul de la somme cumule des temp,rature

Moyenne = Somme/Nombre Jours ;

Printf(‘’Moyenne des températures =%g’’.Moyenne) ;

} getch() ;

}

4.3 Pointeurs et chaînes de caractères

Les chaînes  de caractères sont des tableaux de caractères, terminées par le caractère nul ‘\0’. Les deux instructions suivantes déclarent une chaîne s, et un tampon buf capable de contenir une chaîne de 10 caractères.

Char s[ ] = ‘’Bonjour’’ ;

Char buf[10] ;

4.3.1    Initialisation d’une chaîne comme pointeur

L’instruction

Char *p = ‘’Bonjour’’ ;

déclare une variable de type pointeur, puis alloue 8 caractères contigus en mémoire, puis initialise p avec l’adresse de cette chaîne de caractères.

4.3.2    Traitement des chaînes de caractères

Le programme suivant calcul la longueur d’une chaîne, c’est à dire le nombre de caractères non nul.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 10

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : manipulation des structures

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{

char Texte[30] ; char *p ; int Longueur ; clrscr() ; p= Texte ; Longueur = 0 ;

Puts(‘’Enter un texte :’’) ;

Gets(texte) ; while (*p++ !=’\0’)

Longueur++ ;

Printf(‘’la chaîne contient %d caractères’’, Longueur) ; getch() ; }

Ce programme renvoie le nombre de caractères de la chaîne Texte saisie. Le pointeur p est initialisé avec p est initialisé avec l’adresse de début de la chaîne

P = Texte ;

Dans le texte de continuation de la boucle, l’expression *p++, l’opérateur est exécuté avant l’opérateur *. P++ est exécuté en premier, ayant pour effet d’incrémenter p  pour passer au caractère suivant de la chaîne. Ce pendant la valeur renvoyée par p++ est la valeur du caractère se trouvant à l’adresse p avant incrémentation.

Considérons la déclaration suivante

Char Source [ ] = ‘’Bonjour’’ ; Char Destination[ 10] ;

Peut-on écrire Destination = Source pour copier la chaîne ‘’Bonjour’’ dans Destination ?

Nous avons vu précédemment que Destination et Source qui sont écrites sans crochets, sont des pointeurs, pointant sur l’adresse de début du tableau. En particulier, Destination est une constante (le tableau est fixé en mémoire ) et ne peut être modifier donc l’écriture Destination = Source est interdite Le programme suivant utilise les pointeurs pour copier une chaîne dans une autre chaîne.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 11

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : copie une chaîne dans une autre

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void main ()

{

char Source [] =’’Chaîne source’’ ; char Destination[81] =’’’’ ; //chaîne vide

char *ps ; char *pd ; clrscr() ; ps= Source ; pd = Destination ;

printf(‘’Source=%s\nDestination avant =%s\n’’, Source,Destination) ; while ((*pd++ = *ps++) !=’\0’)

;//instruction vide

printf(‘’Destination après%s’’, Destination) ; getch() ; }

Les pointeurs pd et ps parcourent les tableaux de caractères. L’instruction

pd++ =ps++

incrémente pd et ps, mais * s’applique aux valeurs des pointeurs avant incrémentation, et le contenu de l’adresse pointée par l’ancien ps est copié à l’adresse de l’ancien pd.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 12

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : utilisation des tableaux de pointeurs vers des chaînes

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h> #define MAX 12

void main ()

{

int i, drapeau=0 ; char Nom[10] ;

static char * ListeNom[MAX]=

{

} ;

static int List Nombre[] =

‘’Janvier’’, ‘’Fevrier’’, ‘’Mars’’,

‘’Avril’’, ‘’Mai’’, ‘’Juin’’,

‘’Juillet’’,’’Aout’’,’’Septembre’’,

’’Octobre’’,’’Novembre’’,’’Decembre’’

{

31 30 31,

30,31,30,

31,31,30,

31,30,31

} ;

clrscr() ;

printf(‘’Enter le num,ro du mois :’’) ; scanf(‘’%d’’ ,&i) ; i -= 1 ;

if ( (i>=0) && (i<=11) )

 printf(‘’%s\t%d’’, ListeNom[i],ListeNombre[i]) ; getch() ;

}

4.4 Pointeurs et structures

Lorsqu’on dépose d’un pointeur sur une structure, on a la possibilité de modifier la valeur d’un membre de cette structure. Dans le programme suivant. ARTICLE est une structure et pArt est un pointeur sur cette structure. On peut utiliser *pArt à tout endroit où on peut employer la structure.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 13

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :03/02/99

*Description : utilisation des pointeurs vers structure

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h> #include <string.h> void main()

{

typedef struct

{ char Designation[81] ; unsigned int Code ;

float Prix ;

float Stock ;

}ARTICLE ;

clrscr() ;

ARTICLE Article ;  //variable structure

Strcpy(Aricle.Designation, ‘’Résistance 10K 1/2w’’) ; //initialisation des membres

= 1234 ;  //modification des membres

= 80 ;

Article.Stock = 200 ;

ARTICLE*pArt ;  //pointeur sur la structure

PArt = &Article ;  //fait pointer pArt sur la structure

(*pArt).Prix = 60 ;  //modification des membres

(*pArt).Stock = 400 ; printf(‘’Designation     ;%s\n’’, Article.Designation) ; printf(‘’Code   :%u\n’’ ,) ;  printf(‘’Prix        :%2f\n’’ ,) ;

printf(‘’Stock   :%2f\n’’ ,ARTICLE.Stock) ; getch() ; }

Comme l’emploi de la syntaxe

(*pointeur).membre

n’est pas pratique. C++ possède le raccourci équivalent

pointeur-> membre

Dans le programme précédent, on peut remplacer

(*pArt).Prix ;

par

pArt -> Prix ;

et

(*pArt).stock

par

Part -> Stock ;

 4.5 Allocation dynamique de la mémoire

Quand on définit une variable, ordinaire ou pointeur, on alloue une certaine quantité mémoire bien définie située à une adresse équivalente bien définie (connu du compilateur). En effet, un programme C++ compilé utilise quatre régions mémoires distinctes. Leur modèle d’organisation est présenté par la figure suivante :

Organisation mémoire d’un programme

Zone de code : Elle contient les instructions machine pour toutes les fonctions.

Zone de données statiques : L’allocation statique de la mémoire est faite dès le début du programme(si la variable est globale). Ou de la fonction (si la variable est locale). La mémoire allouée ne sera libérée qu’à la fin du programme ou de la fonction.

Zone pile : Elle contient toutes les données locales non statiques, y compris les paramètres des fonctions. Zone d’allocation dynamique : Il existe une autre technique appelée allocation dynamique de la mémoire qui consiste à utiliser la mémoire disponible, en fonction des besoins des programmes. Il faut,

Pour cela, passer par un pointeur qui pointe vers un bloc de mémoire alloué dynamiquement par l’opérateur new propre à C. Par exemple : int*pEntier=new int ;

L’opérateur new prend une partie (ici la taille d’un entier) de la mémoire libre allouée au programme (mémoire nommée Tas).

Un pointeur, qu’il soit initialisé statiquement ou dynamiquement, peut être ensuite déréférencé : *pEntier) 100 ;

Il faut explicitement libérer la mémoire allouée dynamiquement qu’on en ‘a plus besoin, pour cela, on fait appel à l’opérateur delete :

Delete pEntier ;

Pour une structure par exemple, l’allocation dynamique se fait de la façon suivante : Typedef struct

{

char Designation[81] ; unsigned int code ;

float Prix ;

float Stock ;

} ARTICLE ;

ARTICLE *pArt ; //pointeur sur structure

PArt = new ARTICLE ; // allocation dynamique

5    ENUMERATION

Un type de données d’énumération permet d’obtenir des identifications mnémoniques pour un ensemble de valeurs entières. Par exemple, la déclaration suivante :

enum categorie {ingénieur, technicien, ouvrier} Catégorie ;

Les identificateurs utilisés dans une liste d’énumération sont implicitement de type signed char, unsigned char ou int, selon la valeur de ces énumérations

5.1 Initialisation des constantes d’énumération

Les énumérateurs placés entre accolades sont appelés constantes d’énumération. Chacun reçoit une valeur fixe entière. En l’absence de valeurs d’initialisation explicites, le premier énumérateur (ingénieur) est égal à zéro. Et chaque énumération qui suit est incrémenté de un (technicien 1, ouvrier2).

Lorsqu’il existe des valeurs d’initialisation, on peut attribuer d’s valeurs spécifiques aux énumérateurs.  Ceux qui apparaîtront ensuite sans valeur d’initialisation seront incrémentés de un . Par exemple, dans la déclaration suivante 

enum categorie {ingénieur =100, technicien =ingénieur/2, ouvrier =technicien/2} Catégorie : La valeur d’initialisation est une expression ayant pour résultat une valeur entière

5.2 Utilisation des énumérations

Les variables de type énumération sont souvent utilisées pour clarifier les opérations du programme. Si on a besoin,  par exemple, d’utiliser les catégories d’un groupe d’employé dans un programme source si on utilise des valeurs telle que ingénieur, technicien ou lieu des valeurs entières. Voici un exemple d’utilisation des variables énumérations

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 14

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :02/02/99

*Description : utilisation des variables énumération ----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main() {

  enum categorie {ingenieur =0, technicien, ouvrier} ;   struct employe   {

char Nom[35] ; float Slaire ;

catégorie Grade ;

  } ;

  employe Slaire ;   float Prime ;

  clrscr() ;

  printf(‘’Nom……..’’) ;   scanf(‘’%s’’ ,) ;   printf(‘’Salaire…..) ;   scanf(‘’%f’’ ,&Salaire.Salaire) ; printf(‘’Grade.(0/1/2) :’’) ;   scanf(‘’%d’’,&Salaire.Grade) ; //Salaire.Grade = ingénieur ;

  switch(Salaire.Grade)

   {

  case 0 : Prime = 1000.0 ;break    case 1 : Prime = 600.0 ;break ;   case 2 : Prime = 300.0 ;break ;

  }

  Salaire.Salaire + + Prime ;

  Printf(‘’NOM……….. :%s\n’’ , ) ;

  Printf(‘’Salaire……….. :%g\n’’ , Salaire.Salaire) ;

  Printf(‘’Catégorie……….. :%u\n’’ , Salaire.Grade ) ;

  Return   }

6   DEFINITION DE NOUVEAUX TYPES

Le mot réservé typedef indique la définition d’un nouveau spécificateur de type de données. Comme exemple, considérons l’instruction suivante dans laquelle le type unsigned char est redéfini pour être de type OCTET :

Typedef unsigned char OCTET ;

Maintenant on peut déclarer des variables de type unsigned char en écrivant

OCTET var1, var2 ;

Ou lieu de

Unsigned var1, var2 ;

On peut, par exemple dans le programme 5, définir un nouveau type

Typedef struct categorie

{ char Nom[35] ; float Salaire ;

categorie Grade ;

}AGENT ;

Maintenant on peut déclarer des variables qui ont pour type AGENT

AGENT Salaire1, Salaire2 ;//variables de type AGENT

AGENT Salaire[50] ;//Tableau de structure de type AGENT

AGENT* Salaire ;//pointeur vers une structure


LES FONCTIONS

Les programmes sont souvent très complexes et très longs. Pour les créer, il est bon de les découper en sections facilement appréhendables.

Dans cette optique, C++  autorise la création de groupes d’instructions et l’attribution de nom à ces croupes. On appelle ces groupes des fonctions. Une fonction se présente comme une espèce d’opérateur personnalisé, identifiée par un nom et non par un symbole opératoire. Les opérandes d’une fonction, appelés arguments, sont spécifiés par les biais d’une liste dans laquelle les arguments sont séparés les uns des autres par les virgules.

Les déclarations des fonctions se présentent typiquement de la façon suivante.

<type> <nom de fonction> (<type> <arg1>, <type> arg2> ,…) ;

1.  FONCTION NE RETOURNANT PAS DE VALEUR

1.1 Fonction ne prenant pas des paramètres

Une fonction qui ne retourne pas de valeur, donc qui se contente d’exécuter une certaine action, a le type void. Le corps de la fonction, encadré d’accolades contient les instructions exécutées par la fonction. Voici un exemple simple de fonction de type void.

/* FONCTION  1*/ void cadre()

{ int X0 = 1, Y0 = 80, Y1 = 24 ; int i ;

gotoxy(X0, Y0) ;printf(‘’\xDA’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y0) ; printf(‘’\xC4’’) ;} gotoxy(X1, Y0) ;printf(‘’\xBF’’) ; for (i = X0+1 ; i<Y1, i++)

{gotoxy(X1,i);printf(‘’\xB3’’) ;} gotoxy(X1, Y1) ;printf(‘’\xD9’’) ;

for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y1) ; printf(‘’\xC4’’) ;} gotoxy(X0, Y1) ;printf(‘’\XC0’’) ; for (i = Y0+1 ; i<Y1, i++)

{gotoxy(X0,i);printf(‘’\xB3’’) ;} }

La première ligne constitue l’en-tête de la fonction, void indiquant ici que la fonction ne renvoie pas de valeur de retour.

Le type de la fonction est suivi du nom, cadre, de celle ci. Vient ensuite, la liste des arguments, encadrés de parenthèses. Ici, elle vide, ce qui signifie que la fonction n’attend pas de paramètres.

L’en-tête de la fonction et suivi du corps de celle ci, composé d’instructions spécifiant ce que doit faire la fonction, instructions encadrées par des accolades. Cette fonction affiche un cadre.

Une fois, la fonction définie, on peut l’appeler à partir d’une autre fonction. La fonction main(), de l’exemple suivant appelle la fonction cadre(), sans lui transmettre de paramètres, pour dessiner un cadre.

------------------------------------------------------------------------------------------------------------------------------------------------*

*PROGRAMME 1

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :04/02/99

*Description : utilisation des variables énumération

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void cadre() ;//prototype de la fonction cadre() ; void main()

{

clrscr() ;

cadre() ;//appelle la fonction pour dessiner uncadre getch() ; }

/*---------------------------------------------------------------------------------------------------------------------------------------------*

*FONCTION 1

*Description : Cette fonction dessine un cadre dont les coordonnées 1,1 :représente le coin haut …gauche et

80,24 : représentent le coin bas à droite.

*Entree :aucune *Sortie :aucune

----------------------------------------------------------------------------------------------------------------------*/ void cadre()//aucun paramètre reçu

{ int X0= 1, Y0= 1 , X1 =80, Y1 =24 ; int i ;

gotoxy(X0, Y0) ;printf(‘’\xDA’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y0) ; printf(‘’\xC4’’) ;} gotoxy(X1, Y0) ;printf(‘’\xBF’’) ; for (i = X0+1 ; i<Y1, i++)

{gotoxy(X1,i);printf(‘’\xB3’’) ;} gotoxy(X1, Y1) ;printf(‘’\xD9’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y1) ; printf(‘’\xC4’’) ;} gotoxy(X0, Y1) ;printf(‘’\XC0’’) ; for (i = Y0+1 ; i<Y1, i++) {gotoxy(X0,i);printf(‘’\xB3’’) ;}

}

Pour appeler une fonction ne prenant pas de paramètres impose de laisser les parenthèses après le nom de la fonction. Un nom de fonction sans parenthèses symbolise l’adresse de début de la fonction, qui peut alors être passée à d’autres fonctions.

L’emploi des fonctions présente plusieurs avantages :

-   On peut regrouper en une entité structurelle homogène des actions connexes, que l’on désignera par un simple identificateur. On améliore ainsi l’organisation et la lisibilité du code source. Lire cadre() est plus clair que de lire les instructions constituant la fonction.

-   Une fonction permet de répéter une certaine séquence d’action fréquemment exécutée, sans devoir recopier tout le code source.

-   Le découpage du code en fonction facilite la modularité du code source.

1.1.2 Fonction prenant des paramètres

Nous allons maintenant regarder la fonction cadre() qui reçoit des paramètres de la fonction appelante. Au lieu de dessiner un cadre fixe, la nouvelle version de la fonction cadre() à une liste d’arguments X0, Y0, X1,  et Y1 de type int. Les arguments X0 et Y0 représentent le coin supérieur gauche du cadre, alors que X1, Y1 représentent le coin bas à droite du cadre.

/*FONCTION 2*/

void cadre(int X0,int Y0,int X1, int Y1)

{

int i ;

gotoxy(X0, Y0) ;printf(‘’\xDA’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y0) ; printf(‘’\xC4’’) ;} gotoxy(X1, Y0) ;printf(‘’\xBF’’) ; for (i = X0+1 ; i<Y1, i++)

{gotoxy(X1,i);printf(‘’\xB3’’) ;} gotoxy(X1, Y1) ;printf(‘’\xD9’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y1) ; printf(‘’\xC4’’) ;} gotoxy(X0, Y1) ;printf(‘’\xC0’’) ; for (i = Y0+1 ; i<Y1, i++)

{gotoxy(X0,i);printf(‘’\xB3’’) ;} }

Le programme suivant dessine deux cadres en appelant deux fois la fonction cadre() avec des paramètres différents.

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*PROGRAMME 2

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :04/02/99

*Description : dessine deux cadres concentriques en faisant appel deux fois … la fonction cadre.

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void cadre(int X0,int Y0, int Y1) ;

void main()

{ int C0,L0,C1,L1 ; clrscr() ; C0= 1 ;

L0 = 1 ;

C1 = 80 ;

L1 = 24 ;

Cadre (C0, L0,C1,L1) ;//dessine le cadre extérieur

C0 +=5 ;

L0 +=5 ;

C1 - =5 ;

L1 - =5 ;

Cadre(C0,L0,C01,L1) ;//dessine le cadre inférieur getch() ; }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*FONCTION 2

*Description : Cette fonction dessine un cadre dont les coordonnées

X0, Y0 :représentent le coin haut …gauche et X1, Y1 :représentent le coin bas à droite. *Entree :Les coordonnéees X0, Y0, X1, Y1 de type entier *Sortie :aucune

----------------------------------------------------------------------------------------------------------------------*/ void cadre(int X0,int Y0,int X1, int Y1)

{

int i ;

gotoxy(X0, Y0) ;printf(‘’\xDA’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y0) ; printf(‘’\xC4’’) ;} gotoxy(X1, Y0) ;printf(‘’\xBF’’) ; for (i = X0+1 ; i<Y1, i++)

{gotoxy(X1,i);printf(‘’\xB3’’) ;} gotoxy(X1, Y1) ;printf(‘’\xD9’’) ; for (i = X0+1 ; i<X1, i++)

{gotoxy(i,Y1) ; printf(‘’\xC4’’) ;}

gotoxy(X0, Y1) ;printf(‘’\xC0’’) ; for (i = Y0+1 ; i<Y1, i++)

{gotoxy(X0,i);printf(‘’\xB3’’) ;}

}

2.  FONCTION RETOURNAT UNE VALEUR

Une fonction, qui retourne une valeur, restitue à la fonction appelante un résultat d’un type donné. Nous allons voir maintenant une fonction munie d’une liste d’arguments et d’une valeur de retour, à savoir une fonction qui calcul la puissance. Notre fonction puissance() aura deux arguments, l’un de type double et l’autre de type int et retourne une valeur de type double.

/* FONCTION 3 */

double puissance(double x, int n)

{ double r= 1 ; if (n= = 0) return 1 ; if (n< 0)

{ if (x= =0) return 0 ;//mathématiquement incorrect x = 1/x ;

n = -n ;

}

while (n-- >0) r*= x ;

return( r) ;

}

Le mot clé return termine l’exécution de la fonction et redonne le contrôle à la fonction appelante. L’exemple suivant montre l’appel de la fonction puissance() dans une instruction d’affectation.

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*PROGRAMME 3

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :04/02/99

*Description : calcul n2n à l’aide de la fonction puissance()

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

double puissance (double x, int n) ;

void main()

{

int n ;

double y, x = 2.0 ;

clrscr() ; n = 3 ; y = n* puissance (x,n) ; printf(‘’n2n = %g’’ ,y) ; getch() ; }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*FONCTION 3

*Description : calcul de la puissance par multiplication successive.

*Entrée :l’argument x de type double et l’argument n de type int *Sortie :x puissance n

----------------------------------------------------------------------------------------------------------------------*/ double puissance(double x, int n) double r= 1 ; if (n= = 0) return 1 ;

if (n< 0)

{ if (x= =0) return 0 ;//mathématiquement incorrect x = 1/x ;

n = -n ;

}

while (n-- >0) r*= x ;

return( r) ;

}

Le type de la valeur de retour peut être un type standaard (int, float, etc), un type dérivé (int*, float*,etc), un type personnalisé, ou bien void. Quand on ne précise pas le type de la fonction, c’est à un int qui est pris par défaut.

3.   PASSAGE DE PARAMETRES

3.1 Passage par valeur

Par défaut, les paramètres sont passés par valeur. La fonction alloue une variable locale sur la pile pour chaque paramètre. Cette variable est initialisée avec la valeur passée à la fonction lors de l’appel.

Une fois initialisée, la variable se comporte comme toute autre variable locale de la fonction. Les valeurs des variables allouées pour les paramètres peuvent être modifiées (comme n-dans la fonction puissance() ). Leur contenu est perdu lors de la sortie de la fonction, et elles ne sont en aucune façon recopiées dans l’environnement de la fonction appelante. Dans le programme 2.1, la fonction puissance est appelée avec comme paramètres x et n

Y = n*puissance(x,n) ;

Le n dans l’environnement d’appel n’est pas affecté, alors que le n local à la fonction est décrémentée jusqu’à 0.

3.2 Passage par adresse

Quand on veut qu’une fonction puisse modifier les paramètres, transmis, dans l’environnement appelant, il faut lui passer des pointeurs (passage par adresse) et non des variables ordinaires (passage par valeur).

/*FONCTION 4*/

void echange (int *x, int *y)

{ int temp ;//variable temporaire temp = *x ;

*x = *y ;

*y = temp ;

}

Cette fonction devrait appelée avec échange (&x, &y). Le mécanisme de gestion de référence s’occupe de placer les opérateurs * et & à votre place.

3.3 Passage par référence

Cette technique consiste à déclarer les arguments formels en tant que référence. Passer des références à une fonction revient à lui passer les adresses des arguments, et non pas des copies de leurs contenus. Pour cette raison on utilise souvent les références pour retourner des résultats : voici la fonction puissance avec un argument de style référence pour retourner le résultat.

/* FONCTION 5 */

void puissance(double x, int n, double&resultat)

{

resultat= 1 ; if (n= =0) return ; if (n <0)

{ if (x= =0) { resultat=0 ; ;//mathématiquement incorrect return

       } x = 1/x ;

n = -n ;

}

while (n- - > 0)

resultat *= x ;

}

Quand on accède à la fonction puissance qui contient un paramètre de style référence (variable resultat), on substitue un paramètre réel dans la référence de la fonction au paramètre formel à l’intérieur de la fonction elle-même. C’est donc le paramètre réel lui-même qui sera utilisé pendant l’exécution  de la procédure.

Les paramètres réels qui remplacent les paramètres de style référence doivent être eux-mêmes des variables ; ils ne peuvent pas prendre la fforme de constantes ou expressions comme pour le style de passage par valeur.

L’appel de la fonction puissance, instruction puissance(x,n,y), dans le programme suivant entraîne la substitution du paramètre réel y à l’argument formel resultat de la fonction puissance. Si la valeur de resultat change à l’intérieur de la fonction, ce qui est le cas, un changement correspondant dans la valeur de y se produira dans la fonction main()

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*PROGRAMME 4

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :04/02/99

*Description : calcul la puissance

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h>

void puissance(double x, int n, double&resultat) ;

void main()

{ double y, x = 2.0 ;

clrscr() ;

// les variables x et n sont passées par valeur // alors que y est passées par référence puissance(x, 3, y) ; printf(‘’%g’’ , y ) ; getch() ; }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*FONCTION 5

*Description : calcul de la puissance par multiplication successive.

*Entrée :l’argument x de type double et l’argument n de type int sont passés par valeur et l’argument resultat est passé par référence. *Sortie :x puissance n dans resultat

----------------------------------------------------------------------------------------------------------------------*/ void puissance(double x, int n, double& resultat)

{

resultat =1 ; if (n=0) return ; if (n < 0)

{ if  (x= =0){ resultat=0 ; ;//mathématiquement incorrect return } x= 1/x ;

n = -n ;

}

while (n--> 0)

resultat *= x ;

}

Au niveau de la transmission des arguments, les références combinent les avantages des pointeurs (possibilité de modifier les arguments) et ceux des variables ordinaires (simplicité de la syntaxe d’appel). Autre avantage des références (et aussi des pointeurs) : quand les arguments sont gros (structure par exemple), le passage par valeur est pénalisant car il fait recopier les arguments dans la pile (prend du temps).

4.  PASSAGE D’UN TABLEAU A UNE FONCTION

Les paramètres par valeur ne peuvent jamais être modifiés par une fonction, cependant les tableaux passés enparamètres peuvent être modifiés.

La fonction suivante, par exemple, lit un vecteur

/* FONCTION 6 */

void Lire Tab(float t[],int n)

{

for (int i=o ; i<n ; i++)

{

printf(‘’t[%d] :’’,i)

scanf(‘’%f’’,&t[i] ;//le vecteur t est modifié par la fonction }

}

La fonction Lire Tab() peut lire des tableaux de n’importe quelle longueur. Le nombre d’éléments à Lire est passé explicitement dans le second paramètre.

Le tableau n’est pas copié dans la fonction avant d’être recopié lors du retour de la fonction, comme pour les variables simples, mais la fonction alloue un pointeur local initialisé avec l’adresse de début du tableau. Du fait que c’est l’adresse du tableau qui est passé, et non pas le contenu, les éléments du tableau peuvent être modifiés.

Si l’on veut protéger un tableau passé en paramètre de toute modification , par la fonction appelée, il doit être déclaré const, par exemple

/* FONCTION 7 */

float Produit Slaire (const t[],int n)

{

float r= 1.0 ; for (int i=0 ; i<n ; i++) r* t[i] ;

return r ;

}

La fonction ProduitSalaire ne pourra pas modifier t puisqu’il est déclaré constant.

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*PROGRAMME 5

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :08/02/99

*Description : utilisation des vecteurs.

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void Lire Tab(float[],int) ; void Efface Tab(float[],int) ; void Affiche Tab(float[] , int) ; float Produit Scalaire(const float[] ,int) ;

void main()

{

float Produit, Vecteur[40] ;

int n ; clrscr() ;

printf(‘’Dimension des tableaux :’’) ;

scanf(‘’%d’’ ,&n) ; Lire Tab(Vecteur,n) ;

Produit =ProduitScalaire(Vecteur,n) ;

Affiche Tab(Vecteur,n) ;

Printf(‘’Produit scalaire =%g\n’’ ,Produit) ; Getch() ; }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*FONCTION 6

*Description : lecture des éléments d’un tableau

*Entrée :le tableau t et sa dimension n

*Sortie :valeur des élément du tableau

----------------------------------------------------------------------------------------------------------------------*/ void Lire Tab(float t[],int n)

{

for (int i=o ; i<n ; i++)

{

printf(‘’t[%d] :’’,i)

scanf(‘’%f’’,&t[i] ;

}

}

void Efface Tab(float t[],int n)

{

int i=0 ; while(i<n)

t[i++] =0 ;

}

void Affiche Tab(float t[],int n)

{

int i=0 while (i<n) printf(‘’t[%d]=%g\n’’ ,i,t[i++] ;

}

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*FONCTION 7

*Description : calcul du produit scalaire par la formule  p = t[0]*t[1}* …t[n-1]

*Entrée : tableau t et sa dimension, le tableau t n’est pas modifié

*Retour :produit scalaire de  type float

----------------------------------------------------------------------------------------------------------------------*/ float Produit scalaire( const float t[],int n)

{

float r= 1.0 ; for (int i=0 ; i<n ; i++) r *= t[i] ; return ;

}

5.  PASSAGE D’UNE STRUCTURE A UNE FONCTION

Les structures peuvent être passées en paramètres à des fonctions, ainsi que renvoées par des fonctions, par exemple, si on définit la structure

Struct Article

{ unsigned int Code ; char Designation[81] ;

float PrixUnitaire ; float Stock ; } ;

on peut écrire des fonctions telles que

Article LireFiche() ; //renvoie une structure de type Article

Void AfficheFiche(Article x) ;// accepte comme paramètre une structure

Lorsque l’on passe une structure à une fonction, le paramètre est une variable locale de la fonction, initialisée par une copie membre à membre de la variable passée. Lorsqu’une fonction renvoie une structure par une instruction return (ou r) est une variable de type structure locale à la fonction, une copie membre à membre de r est effectuée. Ces copies membre à membre prennent du temps si la structure est importante. Il est donc préférable de passer une référence constante, par exemple float Calcul|Montant(const Article& x, float Quantite)

du fait de const, la fonction CalculMontant () ne peut modifier la structure x. Elle reçoit un pointeur vers cette structure et non la valeur elle- même. La copie membre à membre des paramètres de la fonction ets évitée.

On peut aussi écrire une fonction pour qu’elle reçoive explicitement l’adresse de la structure : Void ModifieStock(Article* x)

On doit l’appeler ainsi :

ModifieStock(&Comp) ;//reçoit l’adresse de la structure

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*PROGRAMME 6

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :08/02/99

*Description : utilisation des structures.

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> struct Article //définition de la structure

unsigned int Code ; char Designation[81] ; float Prix Unitaire ; float Stock ;

} ;

//prototype des fonctions

Article Lire Fiche() ;

Void Afficher Fiche(Article x) ;

Float CalculMontant(const Article& x,float Quantite ) ;

Void ModifieStock(Article* x) ;

//programme principale void main()

{

Article Comp ;

Float M,Q ;

Comp = LireFiche() ;

Printf(‘’\Enter quantité :’’) ; Scanf(‘’%f’’ ,&Q) ;

M= CalaculMontant(Comp, Q) ;

AfficheFiche(Comp) ;

Printf(‘’\ n ---------------> Montant =%.2f’’ ,M) ;

ModifieStock(&Comp) ;

AfficheFiche(Comp) ;

Getch() ; }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*Cette fonction reçoit comme paramètre l’adresse de l ‘article pour modifier le membre Stock. *Aucune valeur n’est retournée

----------------------------------------------------------------------------------------------------------------------*/ .void ModifieStock(Article* x)

{ printf(‘’\nEntrer le nouveau stock :’’) ;

scanf(‘’%f’’ ,&x->Stock).

}

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*Cette fonction ne reçoit aucun paramètre et renvoie une structure Article

----------------------------------------------------------------------------------------------------------------------*/ Article Lire Fiche() {

Article x ;

Clrscr() ;

Printf(‘’Lecture d’une fiche\n’’) ;

Printf(‘’Code……..’’) ;

Scanf(‘’%d’’ ,&x.Code) ;

Printf(‘’Désignation…..’’) ;

Scanf(‘’%s’’ ,x.Designation) ; Printf(‘’Prix unitaire…’’) ;

Scanf(‘’%f’’ ,&x.PrixUnitaire) ;

Printf(‘’Stock……………….’’) ;

Scanf(‘’%f’’ ,&x.Stock) ;

Return x ;

}

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*Cette fonction  reçoit comme paramètre une structure Article puis affiche ses membres

----------------------------------------------------------------------------------------------------------------------*/ void AfficheFiche(Article x)

{

clrscr() ;

printf(‘’Affichage d’une fiche\n’’ ) ; printf(‘’Code……………..%u\n’’ , x.Code) ; printf(‘’Designation…..%s\n’’ ,x.Designation) ; printf(‘’Prix unitaire…..%2f\n’’,x.PrixUnitaire) ; printf(‘’Stock……………%.4f’’ ,x.Stock) : }

/*-----------------------------------------------------------------------------------------------------------------------------------------------

*Cette fonction  reçoit la référence d’une structure et un réel puis renvoie le montant

----------------------------------------------------------------------------------------------------------------------*/ float CalculMontant(const Article& x,float Quantité)

{ float m ;

m = x.PrixUnitaire *Quantité ; return m ;

}

6. CLASSE DE STOCKAGE

L’association des identificateurs avec des objets nécessite que chaque identificateur possède au moins deux attributs : une classe de stockage et un type.

La classe de stockage détermine l’emplacement d’un objet (segment de données, registre, pile) et sa durée de vie

6.1 Durée de vie

La durée de vie, en relation étroite avec la classe de stockage, définit la période pendant la quelle les identificateurs déclarés ont des objets physiques réels affectés en mémoire.

6.1.1  Durée de vie des variables automatiques

Le spécificateur de classe de stockage auto n’est utilisé que dans des déclarations de variables à portée locale, pour une durée du vie locale (automatique). Auto est rarement employé puisque la valeur par défaut de ces déclarations est justement auto .

Le mot clé register est similaire au mot clé auto. Il demande au compilateur de maintenir l4objet dans un registre de microprocesseur s’il ‘y’ a un de disponible. Si aucun registre n’est disponible, le compilateur traite l’objet comme un objet automatique.

Les variables auto et register sont crées (allocation mémoire ) lorsque la fonction auquel elles appartiennent est appelée, et détruites (désallocation de la mémoire lorsque la fonction est terminée. Dans la fonction suivante :

Void fonction1 ()

{ int a ; //automatique par défaut auto int b ; //automatique register int c ;

}

Les variables a, b et c sont crées à l’appel de fonction 1 () et d étruites lorsque le contrôle est redu à la fonction appelante.

6.1.2 Durée de vie des variables statiques et externes

Le spécificateur de classe de stockage static est utilisable avec les déclarations de fonctions et de variables à portée locale et à portée fichier. Static signale aussi que la variable a une durée de vie statique. Dans la fonction suivante :

Void fonction 2()

{ static float delta ;

}

La variable static delta est connue seulement dans la fonction ou’ elle est définie, fonction2 (), mais, contrairement aux variables automatiques, elle ne disparaît pas lorsque la fonction est terminée.

Le spécificateur externe est utilisable avec les déclarations de fonctions et de variables à portée locale et à portée fichier, pour indiquer un lien externe. Avec les variables à portée fichier, le spécificateur par défaut est externe. Utilisé avec des variables, externe indique que la variable a une durée de vie static

6.2 Portée des variables (visibilité)

Chaque variable possède une certaine portée bien définie, domaine de validité au sein duquel on peut accéder à la variable. Si on essaye d’accéder à une variable hors de sa portée, le compilateur ne l’accepte pas.

6.2.1 Portée Bloc

La portée bloc, ou portée local, d’un identificateur commence au point de déclaration et se termine à la fin du bloc contenant la déclaration. Voici un exemple de bloc à l’intérieur d’une fonction :

Void main()

{//bloc 1 int x= 10 ;

{//bloc 2 int y= 20 ; printf(‘’ %d  %d\n’’ , x, y) ;//coorect

}

y = y+ 10 ; //erreur

}

L’instruction y = y+ 10 générera un message d’erreur puisque la variable y est définie dans le bloc 2, donc ne peut pas être utilisée dans le bloc 1.

6.2.2 Portée fonction

Les seuls identicateurs qui ont une portée de fonction sont les labels d’instructions.

Void fonction()


{

int x ;

while(1) { scan(‘’ %d’’ ,&x) ;

if (x <0)

goto fin ;

} fin : printf(‘’le label fin est accesssible dans toute la fonction’’) ;

}

6.2.3 Portée fichier

Les identificateurs ayant une portée fichier, appel és identificateurs globaux, sont déclarés en dehors des blocs. Leur portée part du point de leur déclaration et se termine à la fin du fichier source. Voici un exemple :

Princip-cp

int X ;

Void main()

{ x = x+ 20 ;//correct, x est déjà définie y = y +30 ;//errreur, y n’est pas encore définie

}

int y ; void fonct()

{ x = x+20 ;//correct y = y+ 30 ;//correct

}

La variable x est visible aux fonctions main() et fonct(), alors que y n’est visible qu’à la fonction fonct().

              Créer un projet

OFPPT

LES FICHIERS

1.   DEFINITION

Un fichier est une structure de donnée. Tout comme un tableau, un fichier est constitué d’une collection de données de même type. A la différence d’un tableau, il est possible d’emmagasiner un fichier sur un disque pour conserver l’information d’une façon permanente.

2.  PRINCIPE D’ACCES AUX FICHIERS SUR DISQUE

L’accès au disque est une procédure complexes et relativement long puisque le lecteur du disque contient une parie méxanique. L’envoie des données caractère par caractère est impraticables. Le système d’exploitation qui s’occupe des transferts utilise une mémoire tampon où les données a enregistré sur le disque seront stockées temporairement en attendant que le tampon soit plein ou lorsqu’on ferme un fichier.

Figure 1 : mécanisme de transfert

La gestion de la mémoire tampon implique plusieurs taches :

-      Resever l’espace mémoire dans la RAM

-      Gérer cette mémoire à l’aide d’un pointeur sur celle ci

-      Libérer cette mémoire lorsque l’on n’a pas besoin d’elle.

Le langage C  nous fournit deus alternatives : soit gérer le tampon nous même en utilisant la méthode d’entrée/sortie de bas niveau (ou système) soit confier la tache au système d’exploitation en utilisant la méthode d’entrée sortie standard.

Chacune des deux méthodes est plus au moins complète pour effectuer des E/S sur disque. Ils ont toutes les deux des fonctions pour lire et écrire un fichier ou réaliser d’autres taches. Mais il y’a des différences importantes entre les deux méthodes.

La méthode d’ E/S standard comme son nom l’indique, et la méthode la plus simple et utilisée pour effectuer des E/S dans un programme C. Il possède une large gamme de commande assez facile à utiliser et évite au programmeur les détails des opérations élémentaires d’ E/S tel que la gestion du tampon et la conversion automatique des données.

La méthode d’E/S de bas niveau fournit moins de choix que la méthode standard, il peut être considérer comme un système primitif. Les techniques utilisés sont proches de celle du système d’exploitation. Le programmmeur doit créer et gérer le tampon utilisé pour le transfert des données. La méthode d’E/S système et plus difficile à utiliser que la méthode standard mais plus efficace en terme de vitesse et d’occupation mémoire.

3.   ENTREE/SORTIE STANDARD

La méthode d’E/S standard est utilisée de quatre façons  pour lire et écrire des données. Trois parmi ses quatres façons pour transférer les données correspondent aux méthodes, déjà vues, pour lire les données à partir du clavier et leur affichage sur l’écran.

Premièrement, les données peuvent être lues ou écrites un caractère à la fois. Ceci est analogue au travail réalisé par la fonction getche() pour lire un caractère à partir du clavier et à putchar() pour afficher un caractère

Deuxièmement, les données peuvent être lues ou écrites sous forme d’une chaîne, comme pour les fonctions gets() et puts().

Troisièmement, des données peuvent être lues et écrites dans un format donné analogue à celui généré par les fonctions printf() et scan() : comme une collection de valeurs mixtes de type caractère, chaîne, réel ou entier.

Quatrièmement, les données peuvent être lues et écrites dans un nouveau format appelé enregistrement ou bloc. L’enregistrement est un groupe de données de longueur fixe et généralement utilisé, par exemple, poue stocker les tableaux et las structures.

Le tableau suivant montre les fonctions utilisées pour lire et écrire des données dans un fichier pour la méthode d’E/S système et la méthode standard avec ses quatre possibilités.

Caractère

Chaîne

Formaté

Enregistrement

E/S standard

getc() putc()

fgets() fputs()

fscan() fprint()

fread() fwrite()

E/S système

read() write()

3.1 E/S des caractères

Notre premier exemple prend les caractères tapés au clavier, et un à la fois, sont envoyés sur le disque (tampon). Le programme est le suivant et essayant de voir ce qu’il fait.

/*---------------------------------------------------------------------------------------------------------------------*PROGRAMME 1

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :11/02/99

*Description : écrit des caractères tapés au clavier, vers un fichier

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h> #include<conio.h> void main()

{

FILE *fptr ;//pointeur vers fichier char car ; char fichier[81] ; puts(‘’Nom du fichier :’’) ;

gets(fichier) ; fptr =fopen(fichier, ‘’w’’) ;//ouvrir fichier en écriture while ( (car=getche()) != ‘\r’)//saisie des caractères

Putc(car,fptr) ;//ecrire caractère vers fichier fclose(fptr) ; //fermer fichier

}

Lors de l’exécution du programme, celui ci demande à l’utilisateur de taper le chemin et le nom du fichier (par exemple C: \) puis attend qu’une ligne de texte soit saisie (par exemple, ENTREE SORTIE DES CARACTERS C’EST FACILE.). Le programme s’arrête lorsque la touche [ENTREE] est appuyée.

On peut utiliser la commande TYPE du DOS pour voir le contenu du fichier .

C:\> TYPE

ENTREE SORTIE DES CARACTERES C’EST FACILE

3.1.1    Ouverture d’un fichier

Avant d’écrire un fichier vers un disque, ou le lire, on doit l’ouvrir. L’ouverture d’un fichier établit une communication entre le programme et le système d’exploitation pour préciser le fichier auquel on veut accéder et comment on va l’utiliser. On doit fournir, au système d’exploitation, le nom du fichier et d’autres informations (lire, écrire, tec…). La communication entre le système d ‘exploitation et le programme se fait à travers une structure C qui contient les informations concernant le fichier .

Cette structure, qui est définie par struct FILE dans le fichier stdio.h. est le point de contact . Lorsque on demande d’ouvrir un fichier, on reçoit au retour, c’est la demande est satisfaite, un pointeur vers une structure d type File. Chaque fichier ouvert doit avoir sa propre structure FILE, avec un pointeur vers elle. La figure 2 montre ce processus


Figure 2 : Ouverture d’un fichier

La structure FILE contient les informations sur le fichier qui vient d’être ouvert, comme exemple sa taille courante et l’adresse de son tampon. Cette structure est définie dans stdio.h de la façon  suivante :

Typedef struct {

                                                               Short               level ;

                                                               Unsigned                     flags ;

                                                               Char                fd ;

Unsigned char  hold ;

                                                               Short               bsize ;

Unsigned char *buffer, *curp ;

                                                               Unsigned         istemp ;

Short  token ;

} FILE ;

En examinant le détail de cette structure, on remarque l’existence de deux pointeurs : buffer et curp. Le rôle de buffer est de contenir l’adresse de la première case de la mémoire tampon. Celui de curp est de se déplacer dans la mémoire tampon pour lire ou écrire les caractères un par un. Un autre membre de cette structure est bsize qui contient la taille du tampon qui est de 512 octets.

Dans le programme 1, nous avons déclaré, en premier, une variable de type pointeur vers FILE, dans l’instruction :

FILE *fptr ;

Puis, on a ouvert le fichier avec l’instruction

Fptr =fopen(fichier, ‘’w’’) ;

Cette instruction demande au système d’exploitation d’ouvrir un fichier dont le nom est saisi par l’instruction gets(fichier) ;

Le caractère ‘’w’’ indique qu’on désire écrire vers le fichier. La fonction fopen() retourne un pointeur vers la structure FILE, pour le fichier, et qu’on stocke dans la variable fptr.

Le prototype de la fonction fopen() est déclaré dans stdio.h comme suit :

FILE *fopen(const char *filename, const char *mode) ;

La chaîne de mode prend l’une des valeurs ci-dessous :

Chaîne de mode

Desvription

‘’r’’

Ouverture en lecture seule

‘’w’’

Création pour écriture

‘’a’’

Ajout :ouvert en écriture en fin de fichier ou création pour écriture si inexistant

‘’r+’’

Ouverture de fichier préexistant pour mise à jour (lecture/écriture).

‘’w+’’

Création pour mise à jour (lecture/écriture). Si un tel fichier préexiste, le contenu est perdu

‘’a+’’

Ouverture pour ajout ; ouverture pour mise à jour en fin de fichier ou création si inexistant.

Pour indiquer qu’un fichier doit être ouvert ou crée en mode texte, on ajoute t à la chaîne de mode (par exemple, ‘’rt , ‘’w + t’’ ).

Pour le mode binaire, on ajoute b (par exemple, ‘’wb’’ , ‘’a +b’’ ).

3.1.2    Ecriture vers un fichier

Une fois, on a établit une ligne de communication avec le fichier en l’ouvrant, on peut écrire dans ce fichier. Dans le programme 1 nous écrivons les caractères, un à la fois, en utilisant l’instruction :

Putc(car, fptr) ;

Cette instruction écrit le caractère car dans le fichier pointé par la variable fptr.

Le processus d’écriture, vers le fichier, continue dans la boucle while jusqu’à ce que l’utilisateur tape la touche ENTREE.

3.1.3    Fermer un fichier

Lorsqu’on a terminé l’écriture vers le fichier, on doit fermer celui ci. La fermeture du fichier se fait par l’instruction fclose(fptr) ;

Normalement, les caractères envoyés par putc() sont stockés temporairement dans le tampon. Lorsque le tampon est plein (512 octets), sont contenu est alors envoyé automatiquement au disque. La fermeture du fichier par la fonction fclose() fait en sorte que les caractères du tampon sont envoyés vers le disque même si celui ci n’est pas plein.

Une autre raison pour fermer le fichier est de libérer l’espace de communication utilisé par un fichier pour être utiliser par d’autres fichiers. Cet espace contient la structure FILE et le tampon lui-même.

3.1.4    Lecture d’un fichier

Si on peut écrire un fichier, on doit être capable de le lire. Voici un programme qui lit un fichier en utilisant la fonction getc() :

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 2

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :11/02/99

*Description : lit des caractères d’un fichier puis les affiche

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h> #include<conio.h> void main()

{

FILE* fptr ;//pointeur vers fichier int car ; char fichier[81] ; puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’r’’) ;//ouvrir fichier en lecture

while ( (car=getc(fptr)) !=EOF)//lecture des caract7res du fichier printf(‘’%c’’ ,car)://affichage du caractère lu fclose(fptr) ; //fermer fichier

}

Ce programme est similaire au programme 1. Le pointeur vers FILE est déclaré de la même façon, et la fichier est ouvert et fermé de la même façon. La fonction getc() lit un caractère à partir du fichier (par exemple , ) ; cette fonction est complémentaire à la fonction putc().

3.1.5    Fin de fichier

La différence majeur entre ce programme et PROGRAMME 1 est que PROGRAMME 2 doit savoir la consultation de l’indicateur de fin de fichier EOF qui est envoyé par le système d’exploitation. L’indicateur EOF n’est pas un caractère mais un entier de valeur 1.

3.1.6    Erreur d’ouverture d’un fichier

Dans le programme 1 ou 2 si le fichier spécifié dans la fonction fopen() n’a pas pu être ouvert , le programme ne pourra pas être exécuté. En effet, la fonction fopen() renvoie une valeur nulle si par exemple :

-    Le disque est plein pour écriture

-    Fichier inexistant

-    Disque ou fichier protégé contre l’écriture.

Le programme suivant est une version améliorée du programme2.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 3

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :11/02/99

*Description : lit des caractères d’un fichier puis les affiche s’il n’pas d’erreurs d’ouverture de fichier. ----------------------------------------------------------------------------------------------------------------------*/ void AfficheErreur (FILE*fptr, char* ptr) ;

#include<stdio.h>

#include<conio.h> #include<stdib.h> void main()

{

FILE* fptr ;//pointeur vers fichier int car ; char fichier[81] ; puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’r’’) ;//ouvrir fichier en lecture if (fptr = = NULL)

{ printf(‘’Impossible d’ouvrir le fichier %s en lecture\n’’ , fichier) ; exit(1) ; //sortie du programme

}

while ( (car =getc(fptr)) ! = EOF)//lecture des caractères du fichier {

if (ferror(fptr))

{

AfficheErreur(fptr,fichier) ;

Fclose(fptr) ;

Exit(1) ;

}

printf(‘’%c’’ ,car) ;//affichage du caractère lu

}

fclose(fptr) ; //fermer fichier

}

void AfficheErreur(FILE* fptr, char* ptr)

{

perror(ptr) ;

clearerr(fptr) ;

}

Même si le fichier a été ouvert correctement, il se peut que d’autres erreurs de lecture ou d’écriture surviennent lors d’un accès au disque. Un secteur pourrait être défectueux, par exemple. La fonction ferror() détecte ce genre d’erreurs, perror() affiche un message correspondant à cette erreur et clearer() remet à zéro un indicateur d’erreur pour permettre de continuer les opérations sur le fichier.

3.1.7   Application : Compter le nombre de caractères dans un fichier

La possibilité de lire et d’écrire ves un fichier caractère par caractère peut avoir beaucoup d’applications. Comme exemple, voici un programme qui compte le nombre de caractères dans un fichier :

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 4

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :12/02/99

*Description : compte le nombre de caract7res dans un fichier

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h>

#include<conio.h>

#include<stdib.h> #include<dos.h>

void main(int_argc,char*_argv[]))

{

FILE* fptr ;//pointeur vers fichier

int car ; char fichier[81] ;

int compte=0 ; clrsc() ;

if (_argc != 2)

{ printf(‘’Format : >comptec NomFichier’’) ; exit(0) ;

}

fptr =fopen(_argv[1],’’r’’) ;//ouvrir fichier en lecture if (fptr = = NULL)

{ printf(‘’Fichier %s ne peut pas être ouvert\n’’_argv[1] ; exit(0) ;//fin du programme

}

while ( (getc(fptr) ) != EOF)//lire caractère du fichier compte++ ; fclose(fptr) ; //ferme fichier

printf(‘’le fichier %s contient %d caractères.’’,_argv[1],compte) ;

getch() }

Dans de programme nous avons utilisés une ligne de commande avec arguments pour obtenir le nom du fichier. On commence par chaercher le nombre d’arguments ; s’il y’en a deux, alors le deuxième, arg[1], est le nom du fichier.

Le programme ouvre le fichier en lecture tout en s’assurant de son existence, puis entre dans une boucle de lecture, pour lire les caractères un à la fois. A chaque lecture d’un caractère la variable compte est incrémentée de 1.

Le programme compte peut être exécuté à partir du DOS, par exemple : C :>compte

3.2 E/S des chaînes

Lire et écrire des chaînes de caractères à partir ou vers un fichier est aussi facile que lire et écrire des caractères individuels. Voici un programme qui écrit des chaînes vers un fichier en utilisant la fonction d’E/S de chaîne fputs().

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 5

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/03/99

*Description : écrit des chaînes de caractères, tapées au clavier vers un fichier ----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h> void main()

{

FILE* fptr ;//pointeur vers fichier char car ; char fichier[81] ; char chaîne[81] ; puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’w’’) ;//ouvrir fichier en ecriture if (fptr = = NULL)

{ printf(‘’Fichier %s ne peut pas être ouvert\n’’ , fichier) ; exit(0) ;//fin du programme

}

while ( strlen(gets(chaîne)) > 0)

{ fputs(chaine,fptr) ;

fputs(‘’\n’’ ,fptr) ;

}

fclose(fptr) ; //ferme fichier

}

L’utilisateur tape une série de chaînes en   terminant chacune d’elles par[ ENTREE]. Pour terminer le programme, l’utilisateur tape la touche [ENTREE] au début d4une ligne pour créer une chaîne de longueur nulle (condition de sortie de la boucle).

Nous avons déclaré un tableau de caractères pour stocker une chaîne fputs() écrit le contenu de ce tableau vers le disque, mais elle n’ajoute pas automatiquement le caractère nouvelle ligne \n à la fin de la chaîne, on doit le faire explicitement (fputs(‘\n’ ,fptr) pour rendre facile la lecture des chaînes à partir du fichier.

Voici le programme qui lit des chaînes à partir d’un fichier :

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 6

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/03/99

*Description : lit des chaînes de caractères, … partir d’un fichier puis les affiche ----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h> void main()

{

FILE* fptr ;//pointeur vers fichier char car ; char fichier[81] ; char chaîne[81] ; puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’w’’) ;//ouvrir fichier en ecriture if (fptr = = NULL)

{ printf(‘’Fichier %s ne peut pas être ouvert\n’’ , fichier) ; exit(0) ;//fin du programme

}

while (fgets(chaine,80,fptr) != NULL) printf(‘’%s’’,chaine) ; fclose(fptr) ; //ferme fichier

}

La fonction fgets() est déclarée dans le stdio.h par :

Char *fgets(char *s, int n, FILE *stream)

Nous remarquons que cette fonction prends trois paramètres. Le premier est l’adresse où la chaîne est stockée, le second est la longueur maximale de la chaîne. La fonction cesse la lecture soit lorsque n-1 caractères ont été lus soit suite à la lecture de saut de ligne (‘\n’) (ce caractère est copié dans s). la fin de la chaîne de caractères est marquée par l’ajout d’un caractère nul (‘\0’). Le troisième est le pointeur sur la structure FILE pour ce fichier.

3.3 E/S Formatées

Les programmes précédents nous ont permet de lire et écrire des caractères et du texte. Nous allons voir maintenant comment manipuler les nombres. Le programme 7 lit les données à partir du clavier, puis les envoie vers un fichier.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 7

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/03/99

*Description : écrit des données formatées, tapées au clavier vers un fichier

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h> void main()

{

FILE* fptr ;//pointeur vers fichier char car ; char fichier[81] ; char Designation[41] ; int Code ; float Prix ; float Stock ; clrscr() ;

puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’w’’) ;//ouvrir fichier en ecriture if (fptr = = NULL)

{ printf(‘’Fichier %s ne peut pas être ouvert\n’’ , fichier) ; exit(0) ;//fin du programme

} do

{

printf (‘’Code :’’) ; scanf(‘’%d’’ ,&Code) ; if (Code < = 0) break ; printf(‘’Désignation :’’) ; scanf(‘’%s’’ ,Designation) ;

printf(‘’Prix Unitaire :’’) ; scanf(‘’%f’’ ,&Prix) ; printf(‘’Stock :’’) ; scanf(‘’%f’’ ,&Stock) ;

fprintf (fptr, ‘’%s %d %f %f’ , Designation, Code, Prix, Stock) ;

}

while ( 1) ;

fclose(fptr) ; //ferme fichier

}

La clé de ce programme est la fonction fprintf(), qui écrit les valeurs des quatre variables vers le fichier . Cette fonction est similaire à printf(), sauf que le pointeur FILE est inclus comme premier paramètre. Comme pour printf(), nous pouvons formater une donnée de plusieurs façon ; en d’autre terme, les conventions d’écriture avec printf() reste valable pour fprintf()

Dans la boucle do, l’utilisateur saisie les données Code, Désignation, Prix et Stock tant que code est supérieur à 0.

Le programme suivant permet de lire les données enregistrées  avec la programme 7.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 8

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/03/99

*Description : lecturedes données formatées, à partir du disque, et leurs affichage

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h> void main()

{

FILE* fptr ;//pointeur vers fichier char car ; char fichier[81] ; char Designation[41] ; int Code ; float Prix ; float Stock ;

clrscr() ;

puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’w’’) ;//ouvrir fichier en lecture if (fptr = = NULL)

{ printf(‘’Fichier %s ne peut pas être ouvert\n’’ , fichier) ; exit(0) ;//fin du programme

}

while (fscanf(fptr, ‘’%s %d  %f  %f’’ , Designation,&Code,&Prix,&Stock) !=EOF)

{ printf (‘’Code :%d\n’’,Code) ; printf(‘’Désignation : %s\n’’ ,Designation) ; printf(‘’Prix Unitaire : %.2f\n’’ Prix) ; printf(‘’Stock : %2f\n’’ ,Stock) ;) ;

}

fclose(fptr) ; //ferme fichier getch() ;

}

Le programme 8 utilise la fonction fscan() pour lire les données à partir d’un fichier. Cette fonction est similaire à scanf(), sauf que, comme pour fprintf() , le pointeur vers FILE est inclus comme premier paramètre.

Le texte et les caractères sont stockés un caractère par octet. Les entiers sont stockés, en mémoire, sous forme de deux octets et les réels sur quatre octets alors que sur le disque, ils sont enregistrés sous forme d’un texte. Ainsi, l’entier 999 est stocké en mémoire sur deux octets, mais il a besoin de trois octets pour être stocké sur disque sous la forme ‘’999’’. Le nombre réel 45.36 occupe 4 octets en mémoire et 5 octets sur disque ; un octet pour cahaque chiffre et un octet pour le point décimal.

3.4 Mode binaire et mode texte

Le langage C a été développé initialement pour le système d’exploitation UNIX , en utilisant évidemment les conventions de traitement de fichier correspondantes à UNIX. Lorsque le langage C a été transporté sur MSDOS , on a ddécidé que C suppoterait les conventions des deux systèmes d’exploitation. Ainsi le mode texte est conforme au système UNIX et le mode binaire, au système MSDOS.

La distinction entre les deux modes réside dans l’interprétation du caractère ‘\n’ de code x0A (ligne suivante) et du caractère ctrl-Z, de code x/A

La figure suivante décrit l’interaction entre un programme C et le DOS pour un fichier ouvert en mode texte.

Figure 3 : Interaction C et DOS en mode texte

Pour un fichier ouvert en mode texte et en écriture, le caractère ‘n’ est converti et sauvé par le DOS sous forme de deux octets : CR/LF (x0D/x0A). lors d’une opération de lecture, le DOS transmet au programme C le code x0A lorsqu’il rencontre la séquence x0D et x0A

Normalement, la fin du fichier est reconnue lorsque tous les octets lus. Le dos connaît le nombre d’octets de chaque fichier.

Si le caractère ctrl-Z se trouve dans le fichier ouvert en mode texte, le DOS l’interprète comme fin de fichier. Le reste du fichier sera ignoré.

Figure 5 : Interaction Cet DOS en mode binaire

Pour un fichier ouvert en mode binaire :

-    Les caractères  ‘\n’ et ‘\r’ sont enregistrés et relus tels quels par le DOS -    La fin du fichier est reconnue lorsque tous les octets ont été lus.

-    Le code ctrl-Z est un code binaire comme les autres. Il n’est donc pas interprété par le DOS comme fin de fichier.

3.5 E/S des enregistrements

Nous avons vu, précédemment, comment les nombres peuvent être stockés en utilisant les fonctions d’E/S formatées fscan() et fprintf(). Nous avons aussi vu que la sauvegarde des nombres occupe beaucoup d’espace disque, car chaque chiffre est stocké comme caractère. L’E/S des données formatées présente un autre problème : il n’y a pas de moyen direct pour stocker des données de type complexe tels que les tableaux et les structures. La solution à ces problèmes est l’es des enregistrements (ou block). L’E/S des enregistrements écrit, vers le disque, les nombres dans un format binaire ce que réduit l’espace occupé sur le disque.

3.5.1    Ecriture des structures avec fwrite()

Nous allons récrire l’exemple du programme 7 en utilisant la structure ARTICLE. Le programme suivant accepte les entrées concernant, le nombre de la structure ARTICLE, Désignation, Code, Prix et stock puis écrit ces données vers le fichier disque.

Le fichier est ouvert en mode binaire et les informations obtenues de l’utilisateur sont placées dans la structureart. Puis, l’instruction suivante écrit la structure vers le fichier :

Fwrite(&art, sizof(art), 1, fptr ;

Le premier argument de cette fonction est l’adresse de la structure qui va être écrite. Le second argument est la taille de la structure en nombre d’octets. Le troisième argument est le nombre de structure à écrire en même temps. Le dernier argument est le pointeur vers le fichier dans lequel en va écrire.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 9

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :09/03/99

*Description : écrit des structures vers un fichier

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h>

typedef struct

{ char Designation[41] ; int Code ; float Prix ;

float Stock ;

}ARTICLE ;

void main()

{

FILE * fptr ;//pointeur vers fichier

Char  car ;

Char fichier[81] ; ARTICLE art ;

clrscr() ;

puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’wb’’) ;//ouvrir fichier en écriture,mode binaire if (fptr = = NULL)

{ printf(‘Impossible d’ouvrir le fichier %s en écriture\n’’ ,fichier) ;) ; exit(1) ;//fin du programme

} do

{

printf (‘’Code :’’) ; scanf(‘’%d’’ ,&) ; if ( <0) break ; printf(‘’Désignation : ’’) ; scanf(‘’%s’’,art.Designation) ; printf(‘’Prix Unitaire :’’) ; scanf(‘’%f’’ ,&) ; printf(‘’Stock : ’’) ; scanf(‘’%f’’ ,&art.Stock) ;

fwrite (&art,sizeof(art),1,fptr) ;

}

while(1) ;

fclose(fptr) ; //ferme fichier

}

3.5.2    Lecture des structures avec fread()

Le programme suivant permet de lire la structure écrite avec la programme 9 :

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 10

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :09/03/99

*Description : lit des enregistrements à partir d’un fichier

----------------------------------------------------------------------------------------------------------------------*/

#include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h>

typedef struct

{ char Designation[41] ; int Code ; float Prix ;

float Stock ;

}ARTICLE ;

void main()

{

FILE * fptr ;//pointeur vers fichier char  car ; char fichier[81] ; ARTICLE art ;

clrscr() ;

puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’rb’’) ;//ouvrir fichier en lecture,mode binaire

if (fptr = = NULL)

{


printf(‘Impossible d’ouvrir le fichier %s en lecture\n’’,fichier) ;) ; exit(0) ;//fin du programme

}

while (fread(&art,sizeof(art),fptr) = =1=

{ printf (‘’Code :%d\n’’ ,) ; printf(‘’Désignation : %s\n’’ ,art.Designatio) ; printf(‘’Prix Unitaire :%.2f\n’’ ,) ; printf(‘’Stock : %.2f\n’’ ,art.Stock) ;

}

fclose(fptr) ; //ferme fichier getch() ;

}

La principale instruction du programme 10 est l’expression

Fread(&art, sizeof(art), 1, fptr) ;

Celle ci lit la donnée à partir du disque pour la placer dans la structure art : le format est similaire à fwrite(). La fonction fread() retourne le nombre d’éléments lu qui correspond normalement au troisième argument de la fonction. La lecture des enregistrements continue jusqu’à que fread() retourne une valeur inférieure 1.

3.6   Accès aléatoire

Tous les fichiers peuvent être organisés d’une ou de deux manières différentes, séquentielle ou aléatoire (on appelle aussi cette dernière fichier à accès direct). Dans un fichier séquentiel, toutes les composantes d’un fichier sont stockées de façon séquentielle, l’une après l’autre. Pour accéder à une composante particulière, il faut commencer au début du fichier et chercher à travers le fichier entier pour trouver la composante qui nous intéresse. Ce type d’accès peut prendre beaucoup de temps, particulièrement si on travaille avec des fichiers volumineux. Cependant, les fichiers séquentiels sont relativement faciles à créer.

Dans un fichier aléatoire, on accède directement à n’importe quelle composante, sans traiter le fichier en entier à partir du début. Ce type d’accès est plus rapide mais difficile à créer et à maintenir. L’accès aux données, dans les programmes précédents, se faisait d’une manière séquentielle. Le programme suivant autorise l’accès aléatoire aux données du fichier crée par le programme 9.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 11

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :05/03/99

*Description : lit l’enregistrement d’un article, sélectionné par l’utilisateur

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<string.h> #include<process.h>

typedef struct

{ char Designation[41] ; int Code ;

float Prix ; float Stock ;

}ARTICLE ;

void main()

{

FILE * fptr ;//pointeur vers fichier char fichier[81] ; int NumeroEnreg ; long int Deplacement ; ARTICLE art ;

clrscr() ;

puts(‘’Nom du fichier :’’) ;

gets(fichier) ;

fptr =fopen(fichier,’’rb’’) ;//ouvrir fichier en lecture,mode binaire if (fptr = = NULL)

{

printf(‘Impossible d’ouvrir le fichier %s en lecture\n’’,fichier) ;) ; exit(0) ;//fin du programme

}

printf(‘’Enregistrement actuel :%d\n’’, ftell(fptr)/sizeof(art)) ; printf(‘’Enter le numéro d’enregistrement :’’) ;

scanf(‘’%d ,&NumeroEnreg) ;//lit le numéro d’enregistrement Deplacement = NumeroEnrg * sizeof(art) ;//calcul son déplacement if (fseek(fptr,Deplacement,0) !=0) //par rapport au début du fichier

{

printf(‘’Le pointeur du fichier ne peut être déplacé :’’) ; exit(0) ;

}

fread(&art,sizeof(art), 1 ,fptr) ;

printf (‘’Code : %d’’ ,&) ; printf(‘’Désignation : %s\n’’ ,art.Designation) ; printf(‘’Prix Unitaire : %.2f\n’’ ,) ; printf(‘’Stock : %.2f\n’’ ,art.Stock) ;

fclose(fptr) ; //ferme fichier getch() ;

}

Le pointeur de lecture du fichier est un pointeur vers des octets particuliers du fichier. Les programmes qu’on a vus font usage du pointeur. Chaque fois qu’on écrit des données vers un fichier, le pointeur est déplacé vers la fin. Lorsqu’on ouvre un fichier en lecture, le pointeur est positionné au début du fichier. Si le fichier est ouvert pour ajout, en utilisant l’option ‘’a’’, le pointeur est placé à la fin du fichier.

La fonction ftell() permet de connaître la position courante du pointeur :

Long ftell(FILE *fptr) ;

La fonction fseek() permet de déplacer le pointeur sur une donnée particulière en lui fournissant un déplacement par rapport à l’emplacement spécifié. Cette fonction est déclarée par

nt fssek(FILE *fptr, long Deplacement , int origine)

Fptr : fichier pointé,

Deplacement : Différence en octets entre origine (position pointeur fichier) et la nouvelle position. En mode texte, offset doit être 0 ou une valeur envoyée par ftell. Origine : Une des trois origines de pointeurs fichier (0, 1, ou 2)

0        : début du fichier

1        : position courante du pointeur

2        : fin de fichier

Valeur Renvoyée par fseek()

Si succès, (pointeur  repositionné), 0.

Si échec, non-zéro. fseek renvoie un code erreur uniquement sur un fichier non ouvert ou un périphérique.

4      ENTRE/SORTIE SYSTEME

L’E/S système (ou E/S de bas niveau) est semblable à celle utilisée par MS DOS pour lire et écrire un fichier. Avec l’E/S système, les données ne peuvent pas être écrites comme des caractères individuels ou comme chaînes de caractères ou encore comme données formatées comme pour les E//S standards. Il y a un seul moyen pour écrire les données : comme un tampon plein de caractères.

Ecrire un tampon de caractères ressemble aux E/S des enregistrements avec les E/S standards. Contrairement aux E/S standards, le programmeur doit créer le tampon pour ces données, le remplir avec des valeurs appropriées avant l’écriture. La figure suivante montre que le tampon pour une E/S système Figure3 : E/S système

L’E/S de bas niveau a plusieurs avantages :

-    Le code utilisé par les routines de la bibliothèque est plus court que celui de l’E/S standard

-    Plus rapide, car il utilise moins de routines.

4.1 Lecture des fichiers

Le programme suivant lit un fichier disque et affiche son contenu sur l’écran.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 12

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :16/03/99

*Description : lit un fichier avec la méthode d’E/S système

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<fcntl.h> //constantes symboliques pour open

#include<process.h>

#include<io.h>

#define Long Tampon 512 //taille du tampon en nombre d’octets char Tampon[Long Tampon] ; // déclaration tampon

void main(int argc,char *argv[])

{

int Handle, Octets, i ;

if(argc !=2)

{

printf(‘’Format : c:\>liresys ’’) ;


exit(0) ;

}

if ( (Handle =open(argv[1], O_RDONLY | O_BINARY)) < 0)

{

printf(‘’Impossible d’ouvrir le fichier %s’’ ,argv[1]) ; exit(0) ;

}

while( (Octets = read(Handle, Tampon, Long Tampon)) >0) for( j=0 ; j < octets ; j++) putch(Tampon[j]) ;

close (Handle) ;

}

4.1.1    Création d’un tampon

La première étape consiste en la création d’un tampon avec les instructions :

#define Long Tampon 512 char Tampon[Long Tampon] ;

Le tampon est la zone mémoire où les données lues à partir du disque seront placées. La taille du tampon est importante pour des opérations efficaces. Suivant le système d’exploitation, les tampons avec une certaine taille seront gérés plus efficacement que d’autres. Avec MSDOS, la valeur optimale est de 512 octets. Dans d’autre cas un tampon plus grand peut être utilisé en choisissant des multiples de 512 octets.

4.1.2    Ouverture d’un fichier

Comme pour les E/S standards, on doit ouvrir un fichier avant accéder. Ceci est réalisé par l’instruction

Handle = open(argv[1], O_RDONLY | O_BINARY)

L’ouverture d’un fichier consiste à établir une communication avec le système d’exploitation . On fournit au système à travers la fonction open()

-   le nom du fichier qu’on veut ouvrir.

-   accès en lecture ou en écriture.

-   le fichier est ouvert en mode binaire ou en mode texte.

La méthode utilisée pour indiquer ces caractéristiques est différente de celle utilisée par la méthode d’E/S standard. Chaque caractéristique est indiquée par une constante. La liste de ces constantes symboliques est fournie dans le tableau suivant :

Constantes

Signification

O_APPEND

Place le pointeur à la fin du fichier

O_CREAT

Crée un nouveau fichier pou écriture (n’a pas d’effet si le fichier existe déjà)

O_RDONLY

Ouvre le fichier en lecture seulement

O_RDWR

Ouvre le fichier en lecture et en écriture

O_TRUNC

Ouvre le fichier avec troncature. Si le fichier sa longueur est ramenée à zéro. les attributs restent identiques

O_WRONLY

Ouvre le fichier pour écriture seulement

O_BINARY

Ouvre le fichier en mode binaire

O_TEXT

Ouvre le fichier en mode texte

Dans l’exemple du programme 10, on a ouvert le fichier avec les constantes O_RDONLY et O_BINARY c’est à dire en lecture avec le mode binaire. Lorsque plusieurs constantes sont utilisées ensembles, elles sont combinées avec l’opérateur de bits OU (\).

4.1.3    Identification de fichier (Handle)

Au lieu de retourner un pointeur, comme pour la fonction fopen () le fait, la fonction open() retourne une valeur entière appelé identificateur (handle). Ce nombre qui est assigné à un fichier sera utilisé pour se référer à celui ci.

Si open() retourne la valeur – 1, elle signale une erreur d’ouverture

4.1.4    Lecture du fichier dans le tampon

L’instruction suivante lit le contenu du fichier :

Octets = read(Handle, Tampon, Long Tampon) ;

La fonction read() prend trois paramètres. Le premier est l’indicateur du fichier. Le second est l’adresse du tampon. Le troisième est le nombre maximum d’octets qu’on veut lire(dans l’exemple, la totalité du tampon).

La fonction read() retourne le nombre d’octets mis dans le tampon. Si ce nombre égale zéro, elle indique la fin de fichier.

4.1.5    Fermeture du fichier

Un fichier doit fermé après utilisation. On utilise la fonction close() pour fermer un fichier. La fonction close() prend comme paramètre l’identificateur du fichier à fermer.

Close(Handle) ;

4.1.6    Messages d’erreur

Comme pour l’E/S standard, pour déterminer l’origine d’une erreur lorsqu’on ouvre un fichier ou lorsqu’on lui accède, on peut utiliser la fonction perror(). Cette fonction prend comme paramètre une chaîne de caractères. Par exemple, on peut remplacer les instructions suivantes dans le programme 12 :

Printf(‘’Impossible d’ouvrir le fichier %s’’ ,argv[1] ; Exit(0) ;

par l’instruction perror(‘’Impossible d’ouvrir le fichier :’’) ;

4.2   Opération sur le tampon

Mettre le contenu d’un fichier dans un tampon a beaucoup d’avantage ; on peut faire différentes opérations sur le contenu du tampon sans le besoin d’accéder à nouveau au fichier. Le programme suivant cherche, dans le fichier, un texte ou une phrase saisie par l’utilisateur.

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 13

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :5/03/99

*Description : cherche une phrase dans un fichier

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<fcntl.h>

#include<process.h>

#include<io.h>

#include<string.h>

#define Long Tampon 1024

void cherche(char* phrase, int Ltampon) ;

char Tampon[Long Tampon] ;

void main(int argc,char *argv[])

{ int Handle, Octets, j; if(argc !=3)

{ printf(‘’Format : c:\>liresys phrase’’) ; exit(0) ;

}

if ( (Handle =open(argv[1], O_RDONLY | O_BINARY)) < 0)


{ printf(‘’Impossible d’ouvrir le fichier %s’’,argv[1]) ; exit(0) ;

}

while( (Octets = read(Handle, Tampon, Long Tampon)) >0) cherche(argv[2], Octets) ; close (Handle) ;

}

void cherche(char* phrase,int Ltampon)

{

char* ptr, *p ; ptr = Tampon ;

while ( (ptr =(char*) memchr(ptr, phrase[0], Ltampon )) != NULL) if (memcmp(ptr,phrase, strlen(phrase)) = = 0)

{ printf(‘’Première occurrencede la phrase:\n’’) ; for (p =ptr – 10; p<ptr + 10;p++) putchar(*p) ;

exit(0) ;

}

else ptr++ ; }

Le programme suggère de l’utilisateur de taper deux arguments dans la ligne de commande : la nom du fichier et la phrase à chercher, par exemple

C:\>fcherche main

La fonction cherche(), appelée par le programme principale, utilise plusieurs fonctions de manipulation du tampon, la première est la fonction memchr(). Cette fonction cherche, dans le tampon, un caractère spécifique. Dans le programme 13, l’expression

Ptr = (char*) memchr(ptr, phrase[0], Ltampon)

montre trois arguments nécessaires pour memchr(). Le premier est l’adresse du tampon. Le second est le caractère à chercher (le premier caractère de la phrase à chercher). Le troisième est la plage de recherche (taille du tampon). La fonction memchr() renvoie NULL si le caractère n’est pas trouvé dans le tampon. Sinon, elle retourne un pointeur vers le caractère trouvé. La fonction cherche() entre dans une instruction if pour vérifier si la phrase débutant par le caractère trouv é est identique à la phrase recherchée. Cette comparaison est faite avec la fonction memcmp() dans l’expression

if (memcmp(ptr,phrase, strlen(phrase)) = = 0)

La fonction memcmp() prend trois paramètres : un pointeur vers un emplacement du tampon où la comparaison doit débuter, l’adresse de la phrase à chercher et la longueur de la phrase. Si la phrase existe, la fonction memcmp() retourne la valeur zéro.

4.3   Ecrire dans un fichier

Comme exemple, essayons de voir le programme suivant qui copie un fichier vers un autre ; il limite le commande COPY du DOS.

Pour utiliser cette fonction, l’utilisateur tape le nom du fichier source (qui existe déjà) et le fichier de destination (qui va être crée) dans la ligne de commande.

C:\>fcopie

/*----------------------------------------------------------------------------------------------------------------------

*PROGRAMME 14

*Fichier :

*Auteur :  Mustapha AIT MAHJOUB

*Date :5/03/99

*Description : Copie un fichier

----------------------------------------------------------------------------------------------------------------------*/ #include<stdio.h>

#include<conio.h>

#include<fcntl.h>

#include ‘’c : \borlandc\include\sys\stat.h’’

#include<process.h>

#include<io.h>

#include<string.h> #define Long Tampon 4096 char Tampon[Long Tampon] ;

void main(int argc,char *argv[])

{ int E_ Handle, S_Handle , Octets;

if(argc !=3)

{ printf(‘’Format : c:\>fcopie ’’) ; exit(0) ;

}

if ( (E_Handle =open(argv[1], O_RDWR | O_BINARY)) < 0)

{ printf(‘’Impossible d’ouvrir le fichier %s’’,argv[1]) ; exit(0) ;

}

if ((S_Handle =open(argv[2], O_CREAT | O_WRONLY|

O_BINARY, S_IWRITE )) < 0) { printf(‘’Impossible d’ouvrir le fichier %s’’ ,argv[2]) ; exit(0) ;

}

while( (Octets = read(E_Handle, Tampon, Long Tampon)) >0) write   (S_Handle, Tampon,Octets) ;

close (E_Handle) ;

close (S_Handle) ; }

Les deux fichiers sont ouverts. L’un est la source à qui on assigne l’identificateur E_Handle. L’autre est le fichier de destination dont l’identificateur est S_Handle. L’expression qui ouvre le fichier de destination est

If ( (S_Handle =open(argv[2], O_CREAT | O_WRONLY|

O_BINARY, S_IWRITE  )) < 0 )

Pour créer un nouveau fichier, on utilise la constante symbolique O_CREAT. Nous voulons écrire ce fichier et ne pas le lire, pour le faire, nous utilisons la constante O_WRONLY . La constante O_BINARY indique que le fichier est ouvert en mode binaire.

Lorsque la constante O_CREATest utilisée, une autre variable doit être ajouter à la fonction open() pour indiquer l’état de la lecture/Ecriture du fichier qui va être crée. Ces options sont appelées arguments de permission (droit d’accès). Il existe trois possibilités :

                S_IWRITE                             : Ecriture permise

S_IREAD       : Lecture permise S_IREAD | S_IWRITE     : Lecture et écriture permises

Pour utiliser ces possibilités, il faut inclure le fichier ‘’sys-stat.h dans le fichier source du programme.

La fonction write() est similaire à read(). Elle prend trois arguments : l’identificateur du fichier, l’adresse du tampon et le nombre d’octets à écrire.

Decouvrir ces documents

  • Formation avancé de Windev

    Formation avancé de Windev

  • Formation Visual Studio

    Formation Visual Studio

  • Formation C++

    Formation C++

  • Document de formation sur le case management

    Document de formation sur le case management

  • Formation sur les bases de l’economie circulaire

    Formation sur les bases de l’economie circulaire

  • Formation approfondie en croissance economique

    Formation approfondie en croissance economique

  • Management participatif formation avance

    Management participatif formation avance

  • Formation : les grands modeles macroeconomiques

    Formation : les grands modeles macroeconomiques

Articles connexes

  • Formation en acupuncture : les critères de sélection
  • Quels sont les meilleurs logiciels de gestion de planning de formation ?
  • Comment établir un plan de formation efficace pour votre entreprise ?
  • Comment faire une convocation pour une formation ?
  • Formation de conducteur de bus : les bonnes adresses
  • Comment devenir développeur Web 3?
  • Kinésithérapeute en belgique: Cursus et formation
  • Gestionnaire immobilier : Ce qu’il faut savoir…
  • Contactez-nous
  • A propos de nous
  • On recrute
  • Rechercher dans le site
  • Politique de confidentialité
  • Droit d'auteur/Copyright
  • Conditions générales d'utilisation
  • Plan du site
  • Accueil
  • Blog
  • Finance et compta.
  • Formations Pro.
  • Logiciels & Apps
  • Organisation
  • Cours informatique
  • Aide à la rédaction
  • Etudes et Metiers
  • Science et Tech
  • Titans de la Tech
id 11354 02