• Aucun résultat trouvé

[PDF] Cours informatique : C++ methodes et explications | Cours c++

N/A
N/A
Protected

Academic year: 2021

Partager "[PDF] Cours informatique : C++ methodes et explications | Cours c++"

Copied!
28
0
0

Texte intégral

(1)

10.

L’héritage multiple

class A { ... } ; class B { ... } ;

class C : public A, public B { ... } ;

F Figure 1

10.1 Conflit de noms

class A { public : affiche () ; ... } ; class B { public : affiche () ; ... } ; class HM : public A, public B { ... } ; int main()

{

HM hm;

hm.affiche() // erreur de compilation car ambigu.

}

Ecrire hm.A::affiche() ou hm.B::affiche() sinon redéfinir HM::affiche()

HM::affiche() {

A :: affiche() ; // et / ou B :: affiche() ; }

10.2 Héritage 2 fois de la même classe

Figure 2

class A { protected : int k ; ... } ; class B : public A { ... } ;

class C : public A { ... } ;

class HM : public B, public C { ... } ; // hérite 2 fois de k venant de A

void HM :: affiche() {

cout << k; // ambigu, quel k ? } A A C B HM

B

A

C

(2)

Pour éviter la duplication

class A { protected : int k ; ... } ;

class B : public A virtual { ... } ; // ou public virtual A ! class C : public A virtual { ... } ;

class HM : public virtual A, public B, public C { ... } ; // hérite 1 seule fois de k venant de A

void HM :: affiche() {

cout << k; // ok

}

Figure 3

A est déclaré classe de base virtuelle. Les éléments de la classe de base virtuelle ne sont insérés qu’une seule fois dans la classe dérivée.

10.3 Appels des constructeurs.

Les constructeurs sont appelés dans l’ordre où ils sont mentionnés dans la déclaration de la classe dérivée (Pas dans l’ordre où ils apparaissent dans le constructeur).

Et les constructeurs des classes de base virtuelles sont appelés avant les constructeurs des classes de bases non virtuelles, enfin le constructeur de la classe dérivée.

Ordre d’appel des constructeurs de la classe HM

HM :: HM( .... ) : B ( ... ) , C ( ... ), A ( ... ) { ... } ; // constructeur de HM constructeur de A constructeur de B constructeur de C constructeur de HM

10.4 Une utilisation :

Pour implémenter un type abstrait de données à partir d'une structure de données fondamentales. A C B HM Classe de base virtuelle

(3)

Type abstrait de données Structure de données fondamentales Pile abstraite File abstraite Ensemble abstrait ... Tableau Liste chaînée Arbre ... Pile File Ensemble Figure 4

Le type abstrait de données ne contient que des des fonctions membres virtuelles pures. Qui sont implémentées dans la classe dérivée à l'aide d'une structure de données

fondamentales.

Class EnsembleAbstrait { public :

virtual void ajouter( int ) = 0 ; virtual void enlever ( int ) = 0 ; virtual void contient ( int ) = 0 ; } ;

Class Tableau { ....

} ;

Class Ensemble : public EnsembleAbstrait, private Tableau { public :

virtual void ajouter( int ) { } virtual void enlever ( int ) { } virtual void contient ( int ) { } } ;

Par héritage multiple de EnsembleAbstrait et Tableau ou

ou par héritage multiple de EnsembleAbstrait et Liste chaînée on fabrique une nouvelle classe qui gère un ensemble d'entier

soit la fonction f :

void f (EnsembleAbstrait &e ) {

e.ajouter() ; e.enlever() ; ...

}

(4)

10.5 En conclusion

L’héritage multiple est plaisant d’un point de vue conceptuel, mais pose d’énormes problèmes de maintenance et de conflit.

(5)

11. Les conversions de type

11.1 Par les constructeurs : constructeur de conversion

Class Complex

{ ...

friend Complex operator+ (Complex, Complex ); public :

Complex( int a, int b = 0); ...

} ;

Complex x( 0, 0), y( -1, 2);

Complex z = 5 ; // z = Complex( 5, 0 );

x = y + 2 // x = operator+ ( y, Complex( 2, 0 ) )

Si on a un constructeur à un argument, il effectue automatiquement une conversion de type. Le constructeur à un argument est appelé un constructeur de conversion.

11.2 Par un opérateur : opérateur de conversion.

sous la forme X :: operator T () => conversion du type X vers le type T.

Class BigInt {

char text[ 50]; public :

BigInt (int i ) ; // constructeur (de conversion)

void operator= ( int i ); // affectation

operator int () ; // operateur de conversion

} ;

BigInt big = 123; // construction : big = BigInt( 123 ) big.text "123"

big = 5; // affectation : operator = big.text "5"

int i ;

i = big; // conv. de type : i = big.operator int( ) i (entier( big.text )

Autre exemple :

Point p( 1, 2 ); Complex z;

(6)

Class Point {

int abscisse, ordonnee ; public :

Point( int a, int o ) { abscisse = a; ordonnee = o; }

operator Complex () { return Complex (abscisse, ordonnee ) ; } } ;

Complex {

float re, im ; public :

Complex( float xx = 0, float yy = 0 ) ; Complex operator + ( Complex ) } } ;

Autre exemple : soit une classe String On peut y définir un opérator const char *

cet opérator sera utilisé chaque fois qu’une fonction a besoin d’un const char * en paramètre et qu’on lui passera un objet du type String

class String {

char *str; public :

String( const char * ) ;

operator const char * () { return str ; } }

String s( "chaîne de caractère" );

(7)
(8)

12. Les modèles (templates)

Un modèle est un canevas décrivant une famille de composants : famille de fonctions, famille de type (class) ...

Les modèles de classes sont abondamment utilisés dans les librairies de classes du compilateur ou dans les classes vendues dans le commerce.

12.1 Déclarations et définitions.

12.1.1 Modèles de fonctions

Définition d’une fonction générique paramètrée par une constante

template <int N> // définition d'un modèle de fonction void f ( )

{

float tab[ N ] ;

for ( int i = 0 ; i < N ; i++ ) cin >> tab[ i ] ; // ...

}

la fonction f est un modèle de fonction qui utilise un tableau de float. La taille du tableau sera défini plus tard par le "paramètre" N

Jusqu'ici le compilateur connaît la définition d'un modèle de fonction mais aucune fonction n'est implémentée ( générée ).

f< 10 >() ; // création et appel d'une fonction avec N = 10 f< 50 >() ; // création et appel d'une autre fonction avec N = 50

ici deux fonctions f sont implémentées (générées et exécutables).

Les créations des fonctions sont faites à la compilation en fonction des appels.

12.1.2 Modèles de classe

Définition d’une classe générique "paramètrée" par deux constantes

template <int col, int lig> class Ecran

{

int colonne, ligne ; char ecran[ col ][ lig ]; public :

Ecran(); void efface() ; ...

(9)

Ecran < 25, 80 > ecranStandard; // création du type Ecran<25,80> // et création d'une variable de ce type

Ecran < 4, 40 > ecranLCD; // création d'un autre type Ecran<4,40> // et création d'une variable de ce type

Les fonctions membres définies à l'extérieur de la classe doivent être précédées de la définition des paramètres

template <int col, int lig>

void Ecran < col, lig > :: efface( ) {

for( int c = 0; c < col; c ++ )

for( int l = 0; l < lig; l ++ ) ecran[ c ][ l ] = ' '; }

12.2 Paramètres de modèle.

12.2.1 Les paramètres constants.

Les paramètres sont des entiers, énumérations, pointeurs ou référence, mais pas des réels.

Template <int I > f( ) ; // ok

Template <float X> f( ) ; // erreur Template <float X> class C { } ; // erreur 12.2.2 les paramètres types.

template <class T> // pas une classe mais un type !

T min( T a, T b ) // définition d'un modèle de fonction

{ return a < b ? a : b ; } int main() { int i, j; char c, d; float x, y; ... i = min<int> ( j, 0 );

// création et appel de la fonction int min( int, int) c = min<char> ( d, ‘A’ );

// création et appel de la fonction char min( char, char) x = min<float> ( y, 3.14 );

// création et appel de la fonction float min ( float, float) return 0;

}

on trouve aussi le mot-clé typename à la place de class

template <typename T> class A { } ;

Les arguments du modèle doivent apparaître obligatoirement dans la liste des paramètres de l'appel de la fonction

(10)

template <class A, class B, class C>

C min ( A a, B b ) // erreur : C n’est pas un paramètre de min () {

C c = a < b ? a : b ; return c;

}

12.2.3 Déduction des paramètres types.

Le compilateur peut déduire parfois tout seul le type des "paramètres" du modèle au moment de l'instanciation. L'appel peut alors être simplifié.

// avec la fonction modèle précédente : template <class T> T min( T a, T b )

float x, y ;

x = min( x, y ); // le compilateur en déduit x = min <float> ( x, y )

mais

float x, y ;

x = min( y, 3 ); // erreur, pas de modèle pour ... min ( float, int )

Aucune correspondance ne convient, aucune conversion (cast) n’est appliquée et il y a erreur de compilation

12.2.4 Paramètres par défaut.

template <class T = int, int taille = 100> class Tableau

{

T tab[ taille ]; void erreur() ; public :

T & operator [ ] (int i ) { assert( i < taille ) ; return tab[ i ] ; }

const T & operator [ ] (int i ) const // pour un tableau constant { assert( i < taille ) ; return tab[ i ] ; }

} ;

Tableau < float, 20 > tabReel ;

Tableau < Complex > tabComplex; // Tableau < Complex, 100 > Tableau <> tabEntier; // Tableau < int, 100 >

12.3 Spécialisation partielle d'un modèle.

Il est possible (et parfois obligatoire) de redéfinir une fonction déjà définie par un modèle

template <class T> // modèle générique

T min( T a, T b ) {

return a < b ? a : b ; }

(11)

template<>

char *min( char *a, char *b ) {

return strcmp( a, b ) < 0 ? a : b ; }

12.4 Autres exemples.

Classe tableau de tout type

template <class Type> class Tableau

{

Type *tab; int taille ; public :

Tableau( int n ) : taille( n ), tab( new Type[ taille ] ) { } ~Tableau() { delete [] tab };

... } ;

Tableau <int> tabEntier( 5 );

Tableau <Complex> tabComplex( 10 ); Tableau <String> tabString( 100 );

Autre exemple : création d'un modèle de gestion de liste d’élements

Lors de la création de la classe liste, on ne connait pas le type des éléments

template <class Type> // Type sera défini à la demande

class Element {

Type info;

Element *suivant;

friend class Liste <Type> ; // un objet Liste doit connaitre Element public :

... } ;

(12)

template <class Type> class Liste

{

Element <Type> * premier; Element <Type> * courant ; Element <Type> * dernier; public :

Listee() ; ~Liste();

Type tete() { return premier->info ; } void ajoute( const Type& );

... }

Liste <int> listeEntier; Liste <Point> listePoint;

(13)

13. La gestion des exceptions.

13.1 Introduction.

La gestion d'erreur peut se faire de différentes manières.

 Méthode brutale: l'utilisation de assert( ) : interruption forcée du programme.

FILE * f = fopen( "fichier", "w" ) ; assert ( f != NULL ) ;

Utilisation d'une variable globale (exemple errno des bibliothèques standards du C) et gestion de cette variable globale par le programmeur.

 Code de retour pour chaque fonction et propagation de ce code de retour jusqu'à l'appelant qui voudra bien le traiter.

bool f( )

{ if( ... ) return true else return false ; }

Comment se mettre d'accord entre un concepteur de composant et son utilisateur pour traiter les erreurs ?

13.1.1 Principe :

Un mécanisme de gestion des erreurs a été introduit dans le langage lui-même par la notion d'exception.

On nomme exception une rupture de la séquence du programme.

Cette rupture est décidée en général à cause d'un problème grave : division par 0, indice de tableau trop grand ou négatif, mémoire insuffisante, pointeur nul, dépassement de calcul ... Lorsqu'une fonction veut signaler une erreur, elle lance une exception (en général un objet erreur).

L'utilisateur qui veut gérer l'erreur, attrape l'objet lancé et exécute le traitement adéquat. Si l'erreur n'est pas attrapée, un traitement par défaut termine le programme.

Structure de controle

throw / try / catch

13.2 exemple :

class Pile {

int *pile, sommet, taille ; public :

Pile( int taille ); void empile( int i ) ; int depile( ) ;

(14)

Pile :: Pile( int taille ) {

if( taille < 0 ) throw( taille ); this->taille = taille ;

pile = new int[ taille ] ; sommet = 0 ;

}

void Pile :: empile( int i ) {

if( sommet >= taille ) throw( "pile pleine" ); pile[ sommet++ ] = i ;

}

int Pile :: depile( ) {

if( sommet == 0 ) throw( "pile vide" ); return pile[ --sommet ];

} int main( ) { try { Pile pile( 5 ); pile.empile( 1 ) ; pile.empile( 2 ) ; cout << pile.depile() ; cout << pile.depile() ; cout << pile.depile() ; } catch( char *msg ) { cout << endl ; cout << msg ; exit( - 1 ) ; } catch( int i ) { cout << endl ;

cout << "erreur à la crétion de la pile, taille incorrecte: " << i ; exit( - 2 ) ;

}

return 0 ; }

13.3 l'instruction throw().

Dès qu'une erreur apparait, le programmeur peut lancer ou lever une exception par l'instruction throw() .

Le paramètre du throw est une variable.

(15)

Ce sera en général un objet d'une classe d'exception.

 On sort immédiatement de la fonction avec l'instruction throw et on ne revient plus dans la fonction. Il y a ensuite en général interruption du programme.

int Pile :: depile( ) {

if( sommet == 0 ) throw( "pile vide" ); return pile[ --sommet ];

}

13.4 Le bloc try.

Les instructions à surveiller sont mises dans un bloc précédé du mot clé try . Le bloc try contient les instructions susceptibles de lancer une exception.

try {

// appels de fonctions susceptibles de lancer des exceptions // directement ou indirectement

}

 Si une exception est lancée (directement ou indirectement) par une des instructions du bloc try , cette exception est attrapée par le bloc et aussitôt le programme se déroute du bloc try et rentre au début du bloc catch qui doit gérer l'exception.

13.5 Le bloc catch.

try { // instructions } catch ( TypeException_1 ex ) { // // instructions }

catch (TypeException_2 ex) { // instructions

}

Le bloc catch doit suivre immédiatement le bloc try. Le bloc catch contient les gestionnaires d'exceptions nécessaires.

Un bloc catch commence par le mot clé catch suivi entre parenthèses comme une fonction d'un paramètre du type d'une classe d'exception, puis du bloc d'instructions à exécuter.

 Le bloc catch exécute ses instructions et en général se termine par l'instruction exit() ou abort(). Mais il peut, avant d'interrompre le programme donner à l'utilisateur des

indications sur l'erreur, et faire effectuer des sauvegardes nécessaires.

 S'il n'y a pas d'arrêt du programme dans un bloc catch, le programme reprend après le bloc try / catch qui a saisi l'exception.

Sortie immédiate de la fonction

(16)

 Le bloc catch exécuté est le premier bloc rencontré avec le type d'exception correspondant à la variable d'exception lancée.

 Si aucune classe d'exception des blocs catch ne correspond à l'exception lancée par throw, la recherche se poursuit dans les blocs try / catch englobant.

 Si on ne trouve aucun gestionnaire de la même classe, le programme appelle la fonction

teminate().

13.5.1 Choix du bon gestionnaire d'exception.

catch( Truc t) // gestionnaire de l'exception truc ou d'une classe derivée { // }

catch( ... ) // gestionnaire de n'importe quelle exception { // }

catch( Chose * c )// gestionnaire de l'exception chose ou d'une classe dérivée

{ // }

ici le gestionnaire de chose ne pourra jamais être exécuté !

13.5.2 Prévision des exceptions possibles.

Une fonction (même la fonction main() ) peut prévoir (spécifier) les exceptions susceptibles de se produire.

int f () throws( TableauLimite, TableauCreation ) { ... }

les exceptions prévues (spécifiés) seront lancées (throw). Toute autre exception non prévue qui serait levée à l'intérieur de la fonction entraîne l'appel de la fonction particulière

(17)

Pile :: Pile( int taille ) {

if( taille < 0 ) throw( taille ); this->taille = taille ;

pile = new int[ taille ] ; sommet = 0 ;

}

void Pile :: empile( int i ) {

if( sommet >= taille ) throw( "pile pleine" ); pile[ sommet++ ] = i ;

}

int Pile :: depile( ) {

if( sommet == 0 ) throw( "pile vide" ); return pile[ --sommet ];

}

void initialisePile( Pile &p ) {

for( int i = 0; i < 10; i++ ) p.empile( 2*i ); } int main( ) { try { Pile pile( 5 ); initialisePile( pile ) ; pile.empile( 1 ) ; cout << pile.depile() ; } catch( char *msg ) { cout << endl ; cout << msg ; exit( - 1 ) ; } catch( int i ) { cout << endl ;

cout << "erreur à la création de la pile, taille incorrecte: " << i ; exit( - 2 ) ; } return 0 ; } 2 1 3 sans exit()

(18)

13.6 Autres exemples

13.6.1 Exemple 1

// déclaration des classes d'exception Class TableauCreation

{ public :

int indice;

TableauCreation( int n ) { indice = n ; } // constructeur };

Class TableauLimite {

public : int indice;

TableauLimite( int n ) { indice = n ; } // constructeur };

class Tableau // classe Tableau

{ int taille; int *tab ; public : Tableau( int ); ~Tableau();

int &operator [] (int ); // surdéfinition de l'opérateur [] } ;

Tableau :: Tableau (int i ) // constructeur {

if ( i <= 0 ) {

TableauCreation erreur( i ); // création d'un objet d'exception throw( erreur ); // lancement de l'exception }

tab = new int[ taille = i ] ; }

int &Tableau :: operator [] (int i ) // opérateur [] {

if ( i < 0 || i >= taille ) {

TableauLimite erreur( i ); // création d'un objet d'exception throw( erreur ); // lancement de l'exception }

return tab[ i ]; // ok

(19)

int main() // essai {

try {

Tableau t( -3 ) ; // provoque l'exception TableauCreation t[ 20 ] = 2; // provoque l'exception TableauLimite }

catch( TableauCreation e ) {

cout << "exception de création avec indice : " << e.indice << endl; exit( 1 );

}

catch( TableauLimite e ) {

cout << "exception d'indice avec indice : " << e.indice << endl; exit( 1 ); } } 13.6.2 Exemple 2 f1() { try{ doSomething f2() ; doSomething } catch( … ) { doSomething exit( 1 ); } catch( … ) { doSomething exit( 1 ); } } terminate() f2() { try{ doSomething f3() ; doSomething } catch( … ) { doSomething exit( 1 ); } } f3() { doSomething if( …) throw( …); doSomething } Figure 5 Ou Ou

(20)
(21)

14. Les entrées/sorties (Streams ou flots).

14.1 Rappels

Les streams sont déclarés dans le fichier entête iostream.h

14.2 La classe ostream : classe des flots de sortie.

Elle surdéfinit l’opérateur << (insertion) sous la forme d’une fonction membre pour écrire toute valeur de type prédéfini du langage :

cout << char, entier, long, réel, char *, adresse, …

 L’opérateur << renvoie une référence sur le flot, ce qui permet de cumuler les sorties.

int i = 3; char c = ‘a’;

char s[] = " bonjour ";

cout << "i =" << i << "c=" << c << "s=" << s << ‘\n’ ;

14.2.1 Redéfinition de l'opérateur <<

Pour écrire dans un flot un objet de type T avec l’opérateur <<, il suffit de définir une

fonction amie dans la classe T correspondant à l’une des formes suivantes : ostream & operator << ( ostream &, T )

ostream & operator << ( ostream &, T& )

ostream & operator << ( ostream &, const T& )

exemple :

ostream & operator << ( ostream &o, const Complex &c ) {

return o << c.x << ‘+’ << c.y << ‘i’ ; }

Complex z( 2, 3 );

cout << z ; // écrit 2+3i

14.2.2 Autres fonctions de la classe ostream :

ostream &write( char *texte, int n ) Ecrit le tableau jusqu'à la taille n.

cout.write( "maison" , 5 ) ; // écrit : maiso

(22)

cout.put( '\n' ) ; // effectue un saut de ligne

(23)

14.3

La classe istream : classe des flots d’entrée.

1. Elle surdéfinit l’opérateur >> (extraction) sous la forme d’une fonction membre pour lire toute valeur de type prédéfini du langage.

 L’opérateur >> renvoie une référence sur le flot, ce qui permet de cumuler les entrées.

int i ; char c ;

cin >> i >> c ;

 Pour lire un objet d’un nouveau type T dans un flot d’entrée avec l’opérateur >>, il suffit de définir une fonction amie :

istream & operator >> ( istream &, T& )

istream & operator >> ( istream &i, Complex &c ) {

char carac;

i >> c.x >> carac; assert( carac == ‘+’ ); i >> c.y >> carac; assert( carac == ‘i’ ); return i;

}

Complex z ;

cin >> z ; // il faut taper par exemple 2 + 3i

14.3.1 Fonctionnement de l'opérateur d'extraction >>  Saisie d'un tableau de char :

"saute" les blancs au début

arrête la saisie dès le premier séparateur trouvé,

les autres caractères restent dans le flux, dont le séparateur.

ATTENTION : n'arrête pas la saisie si le tableau de saisie est plein !

char texte [ 50 ] ; cin >> texte ;

// si on frappe " saisie de mot " ( = Entrée) // alors texte contient "saisie"

// et il reste " de mot " dans le flux d'entrée.

 saisie d'un entier :

"saute" les blancs au début

arrête la saisie dès le premier caractère différent d'un chiffre

(24)

int i ; cin >> i ;

// si on frappe " 123A" ou " 123 " // alors i contient 123

// et il reste "A" ou le caractère "" (Entrée seul)  saisie d'un réel :

"saute" les blancs au début

arrête la saisie dès le premier caractère différent d'un chiffre ou d'un point

double d ; cin >> d ;

// si on frappe " 3.14A" ou " 3.14 " // alors d contient 3.14

// et il reste "A" ou le caractère "" (Entrée seul)  En conclusion cin >>

ne permet pas de saisir des espaces

Le séparateur de fin de saisie reste dans le flux

Il est bon de vider le flux avant ou après une saisie (avec get() ou getline() ) Le fonctionnement est similaire avec scanf().

14.3.2 Autres fonctions de la classe istream :

 La fonction get() : plusieurs formes

int get();

rend le premier caractère du flux sous la forme d'un entier, les autres restent dans le flux.

istream& get(char*, int len, char terminal= '\n');

prend les caractères dans le flux s'arrête

quand la longueur len – 1 est atteinte et ajoute '\0' dans la saisie ou quand on rencontre le caractère terminal.

Le caractère terminal reste dans le flux et ajoute '\0' dans la saisie ne saute pas les "blancs" au début

la saisie contient toujours à la fin le caractère '\0' les autres caractères restent dans le flux

istream& get(char&);

rend le premier caractère du flux ctrl Z rend 0.

istream& get(streambuf&, char = '\n');

 La fonction getline()

istream& getline(char*, int len, char terminal= '\n');

même comportement que get( char *, int, int ) mais

(25)

Lit donc un caractère de plus que get( char *, int, int ).

 En conclusion : get( char *, int, int ) et getline( char *, int, int ) Saisissent les espaces (par opposition à cin >> )

Utiliser cin.get( char *, int, int ) puis cin.get() pour retirer le séparateur ou cin.getline(char *, int, int) qui lit aussi le séparateur.

getline( … ) est plus interessant que get( … )

Fonctionnement un peu similaire à gets() mais dans gets : pas de contrôle de la taille du buffer, le caractère terminal est remplacé par '\0' (comme getline() ).

 La fonction gcount()

int gcount ( );

Renvoie le nombre de caractères saisis par get et getline (et read)

(avec getline on lit un caractère de plus car le caractère terminal est retiré du flux)

char texte[ 50 ] ; int i ;

i = cin.get() ;

// si on frappe "56"

// alors i contient 0x35 et il reste "6"

cin.get( texte, 5) ; i = cin.gcount() // si on frappe "123"

// alors texte contient "123" i contient 3 et il reste "" cin.get( texte, 5) ; i = cin.gcount()

// si on frappe "12345678"

// alors texte contient "1234" i contient 4 et il reste "5678" cin.getline( texte, 5) ; i = cin.gcount()

// si on frappe "123"

// alors texte contient "123" i contient 3 et il ne reste rien cin.getline( texte, 5) ; i = cin.gcount()

// si on frappe "12345678"

// alors texte contient "1234" et i contient 4 et il reste "5678"  La fonction read()

istream& read(char*, int len);

même comportement que get( char *, int, int ) mais n'utilise pas de caractère terminal.

Peu intéressant.

 La fonction peek()

int peek( );

Rend le caractère dans le flux sans l'extraire. Les fonctions tellg() et seekg()

(26)

14.4

Le statut d’erreur d’un flot

Ensemble de bits d’un entier :

les bits d’erreur sont définis comme constante dans la classe ios. ios::eofbit

ios::failbit ios::badbit ios::goodbit.

Pour lire tout le statut : int rdstate().

pour modifier le statut : void clear( int = 0)

fl.clear( ios::badbit | fl.rdstate() ) ; // active le bit ‘bad’

fonctions d'état : bool good() ; bool fail() ; bool eof() ;

14.5 Formatage.

Le formatage est effectuée à l’aide de manipulateurs Il faut inclure le fichier entête <iomanip.h> Les manipulateurs sont inclus dans le flot.

Quelques exemples : (les manipulateurs sont très nombreux).

dec : conversion en décimale hex : conversion en hexadécimale oct :

setbase( int )

fixed , scientific : notation fixe ou scientifique endl : insère un saut de ligne et vide le tampon

setw( int ) définit le gabarit. A utiliser avant chaque opération !

setprecision( int ) définit la précision des nombres flottants.

setfill( int ) définit le caractère de remplissage. A utiliser avant chaque opération !

int i = 16;

float x = 12.3456;

cout << ‘*’ << hex << i << ‘*‘ << setw( 8 ) << setprecision( 2 ) << x << ‘*’; // affiche *10* 12.35*

14.6 Les flux fstream : les fichiers (ofstream, ifstream)

14.6.1 Mode d'ouverture

(27)

ios::out en sortie (écriture) (détruit le fichier existant) ios::app en ajout à la fin (conserve le fichier existant) ios::trunc efface le contenu à l'ouverture ????

ios::binary en mode binaire (utiliser read et write)

14.6.2 Constructeur

fstream( const char *name, int mode, int prot = …. ); ifstream( const char *name, int mode = ios::in );

ofstream( const char *name, int mode = ios::out | ios::trunc );

14.6.3 Autres membres

void ifstream::open( const char *name, int mode = ios::in );

void ofstream::open( const char *name, int mode = ios::in | ios::trunc ); bool fstream::is_open() ;

void fstream::close() ; void fstream::eof() ;

14.6.4 En écriture on peut utiliser

<< avec tout type de base put( char )

write( char *, int n) // écrit n caractères, ne s'arrête pas en '\n' ou '\0' ! flush()

14.6.5 En lecture on peut utiliser

>> avec tout type de base get ( )

get ( char *, int ) getline( char *, int ) long tellg()

seekg( pos )

count() pour connaître le nombre de caractères lu

14.6.6 exemple :

#include <fstream.h> char ligne[ 80 + 1] ;

char nomFichier[ ] = " …….." ;

ifstream fEntree;

fEntree.open( nomFichier, ios::in ); if( !fEntree.good() ) { cerr << "erreur ….. " ; return ; } while( … ) { fEntree.getline( ligne, 80 + 1, '\n' ); if( fEntree.eof() || fEntree.fail() ) break ; int taille = fEntree.gcount( ) – 1 ;

(28)

…… }

fEntree.close() ;

14.7 Les flux strstream : les chaînes de caractères

14.7.1 Mode d'ouverture

ios::in en entrée (lecture)

ios::out en sortie (écriture) (détruit la chaîne existante) ios::app en ajout à la fin (conserve la chaîne existante) ios::trunc efface le contenu à l'ouverture ????

ios::binary en mode binaire (utiliser read et write)

14.7.2 Constructeur

strstream( ) ; utilise un buffer alloué dynamiquement

strstream( signed char *buf, int sz, int mode ); utilise le buffer proposé

14.7.3 Autres membres

char *str() ; retourne le buffer et le gèle istrstream &getline( char *, int, int )

14.7.4 En écriture on peut utiliser

<< avec tout type de base put( char )

write( char *, int ) flush()

14.7.5 En lecture on peut utiliser

>> avec tout type de base get ( )

get ( char *, int ) getline( char *, int ) long tellg()

seekg( pos )

count() pour connaître le nombre de caractères lu

strstream chaîne ; int i = 5 ;

double d = 3.14 ;

chaine << " i = " << i << " d = " << d ; // équivalent à sprintf() chaine << " fin "

Figure

Tableau :: Tableau (int i )  // constructeur  {

Références

Documents relatifs

En effet, aucune des autorités administratives auxquelles s’est substitué le Défenseur des droits n’avait bénéficié de la part du législateur, du droit de demander un avis

UN BILAN DES RECHERCHES RECENTES Les éléments réunis dans ce dossier n'ont pas l'ambition de dresser un inventaire exhaustif des lieux reconnus pour les manifestations des

Non seulement les revendications des Gilets Jaunes sont légitimes mais il est nécessaire de les prendre au sérieux pour faire bifurquer l’économie vers du

Enfin, les ciné-transmissions altèrent également l’expérience d’une salle de théâtre pour des spectateurs habitués aux diffusions dans des salles de cinéma.. Dans un

Ces recherches sont centrales en ce qu’elles portent un regard critique sur la mise en place de ces pôles, mais peu de ces recherches offrent une réflexion

est mise en relation avec la Motivation de Service public (Kim, 2012 ; Wright &amp; Pandey,.. Toutefois, les modèles mobilisés dans ces recherches dissocient MSP et

Keywords : Intellectual security; identity ; educational contents ; Islamic education; Curriculum.. - 25 - 1 - ﺔﻣدﻘﻣ نﻣ ﻲﻓﺎﻘﺛﻟا

La prise en compte du rapport à l’écriture des élèves, dans leurs pratiques sco- laires et extrascolaires, s’avère être un enjeu d’autant plus important qu’il appa- rait