Vous êtes sur la page 1sur 68

M1103—Cours de C++ 1

 Alain Casali
 Marc Laporte
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
A. Le type string
A.1 Initialisation de string lors de la déclaration

Construction par remplissage (fill) :


string VarIdent (Size, VarChar);

Exemple :
string Str1 (10,’A’);
Str1 est une string contenant 10 fois le caractère ‘A’

Construction par copie :


string VarIdent (AnotherString);

Exemple :
string Str2 (Str1);
Construction par copie partielle :
string VarIdent (AnotherString, APos);
string VarIdent (AnotherString, APos, NbOfChars);

Charge au développeur de vérifier l’assertion :


AnotherString.size () <= APos [+NbOfChars]

Exemple :
string Str3 (Str1, 3);
//Str3 est une string qui contient 7 fois le caractère ‘A’.
string Str4 (Str1, 3, 2);
//Str4 est une string qui contient 2 fois le caractère ‘A’.
A.2 Extraction d’une sous chaine

Pour extraire une sous-chaine d’une string, on appelle une des


méthodes substr() sur l’objet (la variable) de type string.

Profil des fonctions appelables :


1. string substr ();
renvoie toute la chaine de caractère
2. string substr (unsigned Pos);
renvoie la sous-chaine entre [Pos; .size () [
3. string substr (unsigned Pos, unsigned Len);
renvoie la sous-chaine entre [Pos; Pos + Len [

Charge au développeur de vérifier l’assertion :


.size () < Pos [+Len]

Exemple :
string Str ("Ma jolie chaine");
cout << Str.substr (4) << endl; //olie chaine
cout << Str.substr (4, 8) << endl; //olie cha
A.3 Recherche d’une chaine de caractères

Pour rechercher une sous-chaine dans une string, on appelle une des
méthodes find () sur l’objet (la variable) de type string.

Profil des fonctions appelables :


1. unsigned find (string AString);
renvoie la première position de AString dans la string courante,
sinon renvoie la constante string::npos;
2. unsigned find (string AString, unsigned Pos);
renvoie la première position de AString dans la string courante à
partir de la position Pos, sinon renvoie la constante string::npos.

Exemple :
string Str ("abracadrabrantesque");
cout << Str.find ("bra") << endl; //1
cout << Str.find ("bra", 8) << endl; //9
cout << Str.find ("bilou") << endl; //18446744073709551615
A.4 Lecture d’une ligne au clavier
Problème :
string Str;
cin >> Str; //ma jolie chaine
cout << Str; //ma
cin >> Str;
cout << Str; //jolie

Puisque le buffer de lecture n’est pas vide, l’extracteur extrait le prochain


mot (compris entre la position courante et le prochain caractère
d’espacement).

Solution : utiliser la procédure getline () de profil :


void getline (istream& is, string& AString);

Flux d’entrée Modification de l’état du flux puisqu’on


Exemple : fait une lecture
getline (cin, Str); //ma jolie chaine
cout << Str; //ma jolie chaine
cin >> Str; //en attente d’une string
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
bibliothèque = ensemble de types
sous-programmes
classes, objets, ...

bibliothèque graphique 2D bibliothèque graphique 3D

Fill() Shadow()

Paint() Project()

...
Draw() Draw()
...
conflit

utilisateur
Fill (something);

Project (quelque_chose);
Draw (autre_chose); quel Draw() ?
Draw (...); quel Draw() ?
bibliothèque standard du C++ = tous les types, classes, fonctions, objets, etc.
"prédéfinis" du C++ qui  au langage C

exemples int unsigned char  au langage C


cout endl <<  au langage C
décrits dans
flux standard injecteur le fichier iostream
de sortie (input output stream)
(écran)
regroupés dans
manipulateur l'espace de noms std

string + ...
décrits dans
le fichier string
opérateur de
concaténation
utilisation

#include <string> // contient la "description" de string

#include <iostream> // " cin, cout, endl, ...

opérateur de
résolution de
int main () portée
{
std::string
string Message;
Message;
extracteur
cin >> Message;
std::cin >> Message;
cout << Message
std::cout << endl;
<< Message << std::endl;

return 0;

} // main()
ou
utilisation

#include <string> // contient la "description" de string

#include <iostream> // " cin, cout, endl, ...


using namespace std;

int main ()
{
string Message;

cin >> Message;


cout << Message << endl;
return 0;

} // main()
bibliothèque graphique 2D bibliothèque graphique 3D

nsGraph2D nsGraph3D

Fill() Shadow()
Paint() Project()
décrites dans
Draw() fichiers Draw()

Graph2D Graph3D
#include <Graph2D>
#include <Graph3D>

ou

nsGraph2D::Fill (something);

nsGraph3D::Project (quelque_chose);
nsGraph3D::Draw (autre_chose);
aucune ambiguïté
nsGraph2D::Draw (...);
bibliothèque graphique 2D bibliothèque graphique 3D

nsGraph2D nsGraph3D

Fill() Shadow()
Paint() Project()
décrites dans
Draw() fichiers Draw()

Graph2D Graph3D
#include <Graph2D>
#include <Graph3D>
using namespace nsGraph2D;
using namespace nsGraph3D;
Fill (something);

Project (quelque_chose);
nsGraph3D:: Draw (autre_chose);
non ambigu
nsGraph2D:: Draw (...);
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
Exemple sans espace de noms

/**
Entete void DisAuRevoir (void)
**/ déclarations {
cout << "Au revoir"
#include <iostream> << endl;

using namespace std; } // DisAuRevoir ()

void DisBonjour (void); définitions


void DisAuRevoir (void); appels
int main ()
void DisBonjour (void) {
{ DisBonjour ();
cout << "Bonjour" DisAuRevoir();
<< endl;
return 0;
} // DisBonjour ()
} // main()
Exemple avec espace de noms nommé

/** void DisAuRevoir (void)


Entete {
**/ cout << "Au revoir"
<< endl;
#include <iostream>
} // DisAuRevoir ()
using namespace std;
} // namespace nsMyNamespace
namespace nsMyNamespace
{
void DisBonjour (void); int main ()
void DisAuRevoir (void); {
nsMyNamespace::
void DisBonjour (void) DisBonjour ();
nsMyNamespace::
{
cout << "Bonjour" DisAuRevoir();
<< endl;
return 0;
} // DisBonjour ()
} // main()
Exemple avec espace de noms nommé

/** void DisAuRevoir (void)


Entete {
**/ cout << "Au revoir"
<< endl;
#include <iostream>
} // DisAuRevoir ()
using namespace std;
} // namespace nsMyNamespace
namespace nsMyNamespace
{ using namespace nsMyNamespace;
void DisBonjour (void);
void DisAuRevoir (void); int main ()
{
void DisBonjour (void) DisBonjour ();
{ DisAuRevoir();
cout << "Bonjour"
<< endl; return 0;

} // DisBonjour () } // main()
Exemple avec espace de noms anonyme

/** void DisAuRevoir (void)


Entete {
**/ cout << "Au revoir"
<< endl;
#include <iostream> pas de nom
} // DisAuRevoir ()
using namespace std;
} // anonymous namespace
namespace
{
void DisBonjour (void);
void DisAuRevoir (void); int main ()
{
void DisBonjour (void) DisBonjour ();
{ DisAuRevoir();
cout << "Bonjour"
<< endl; return 0;

} // DisBonjour () } // main()
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
D. Valeur par défaut
D.1 Dans les fonctions « normales »

Déclaration/définition

string & ExpandTab (string & Chaine,


unsigned Tab = 8)
{
...
Utilisation

string LigneLue, L4, L8;


getline (cin, LigneLue);
L4 = L8 = LigneLue; affectation multiple

cout << ExpandTab (L4, 4) << '\n'


<< ExpandTab (L8) << '\n';

utilisation de la valeur par défaut : 8


D.2 Utilité des valeurs par défaut

unsigned FindDicho (const CVInt & V, int Val)


{

} // FindDicho ()

Utilisation
unsigned Pos = FindDicho (V, 10);
D.2 Utilité des valeurs par défaut extensibilité

unsigned FindDicho (const CVInt & V,int Val


unsigned MinPos,
unsigned MaxPos)
{

il n'y a plus qu'une seule fonction


C'est une seconde fonction
} // FindDicho () (une surcharge)

Utilisation
unsigned Pos = FindDicho (V, 10);

unsigned Pos = FindDicho (V, 10, 0, V.size ());


D.2 Utilité des valeurs par défaut extensibilité

unsigned FindDicho (const vector <int> & V,int Val


unsigned MinPos = 0,
unisgned MaxPos = V.size ())
{

il n'y a plus qu'une seule fonction


C'est une seconde fonction
} // FindDicho () (une surcharge)

Utilisation
unsigned Pos = FindDicho (V, 10);

unsigned Pos = FindDicho (V, 10, 0, V.size ());

unsigned Pos = FindDicho (V, 10, 1);


Règles pour les paramètres par défaut :
Soit f () une fonction comprenant m paramètres dont n
ayant des valeurs par défaut (n <= m).
• Dans le profil, si le ième paramètre a une valeur par
défaut, tous les paramètres suivants ont obligatoirement
des valeurs par défaut;
• Dans l’appel à la fonction, si on omet de fixer une valeur
au ième paramètre, on ne doit fixer aucune valeur pour ses
suivants.

Ada95 autorise une autre façon de passer des paramètres effectifs lors de l'appel
procedure UneFonction (Largeur : in Integer,
Hauteur : in Integer,
Utilisation Profondeur : in Integer) is

UneFonction (Largeur => 10,


Profondeur => 25,
Hauteur => 140);

C'est le passage des paramètres par nom


Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
E. Passage optimal des
paramètres
Soit le programme suivant :
unsigned Find (vector <int> V, int Val)
{

}

int main ()
{

vector <int> VInt (4);
for (int &x : Vect) x = Rand (1, 10);
cout << (Find (VInt, 5) == VInt.size ()?
"pas " : " ") << "trouvé" << endl;

}
Etat de la mémoire avant l’appel à Find ()

VInt [0] VInt [1]


VInt [2] VInt [3]

Etat de la mémoire pendant l’appel à Find ()

VInt [0] VInt [1]


VInt [2] VInt [3] V[0] = VInt[0] V[1] = VInt[1]
V[2] = VInt[2] V[3] = VInt[3] Val = 5

1. On crée un nouveau vecteur (V) de taille identique à celle de VInt


2. On copie, dans chaque case de la mémoire, le contenu de V [ind]
Etat de la mémoire avant l’appel à Find ()

VInt [0] VInt [1]


VInt [2] VInt [3] Var1
Var2 Var3
Var4 Var5

Etat de la mémoire pendant l’appel à Find ()

VInt [0] VInt [1]


VInt [2] VInt [3] V[0] = VInt[0] V[1] = VInt[1]
V[2] = VInt[2] V[3] = VInt[3] Val = 5 Var3
Var4 Var1 Var5 Var2

1. On a du déplacer certaines variables pour faire de la place à V


2. On crée un nouveau vecteur (V) de taille identique à celle de VInt
3. On copie, dans chaque case de la mémoire, le contenu de V [ind]
Etat de la mémoire avant l’appel à Find ()

Var1 VInt [0] VInt [1]


VInt [2] VInt [3] Var2 Var3
Var4 Var5 Var6 Var7
Var8 Var9

Etat de la mémoire pendant l’appel à Find ()

Var1 Var2 VInt [0] VInt [1]


VInt [2] VInt [3] V[0] = VInt[0] V[1] = VInt[1]
V[2] = VInt[2] V[3] = VInt[3] Val = 5 Var7
Var3 Var4 Var8 Var9

1. On a déplacé certaines variables pour faire de la place à V soit en


mémoire centrale, soit sur le disque (=> phénomène de swap)
2. On crée un nouveau vecteur (V) de taille identique à celle de VInt
3. On copie, dans chaque case de la mémoire, le contenu de V [ind]
Idée : combiner 2 notions du C++
1. Si un objet est déclaré const, on ne peut pas le modifier;
2. Si un objet est passé par référence (utilisation de ‘&’), seule son
adresse mémoire est donnée à la fonction, l’objet n’est pas copié (il
est utilisable en lecture –attention- et en écriture).

Lors d’une déclaration de fonction tous les objets doivent avoir ces 2
propriétés.

Type F (const Type & VarIdent1, const Type2 & VarIdent2, …)

Exemple :
unsigned Find (const CVint & V, int Val) {…}

Ce n’est pas une classe mais un POD


Paramètres in / out renvoyés

On souhaite transformer tous les caractères d’une string en leur minuscule

void ToLower (string & str)


{
for (char & c : Str) c = tolower (c);
}


string Chaine;
getline (cin, Chaine);
ToLower (Chaine);
cout << Chaine;

Est-ce qu’il n’y aurait pas moyen de combiner les deux dernières instructions?

cout << ToLower (Chaine);


=> Modification de la signature de ToLower ()

string ToLower (string & Str)


{

return str;
}


cout << ToLower (Chaine);

Retour par copie Passage par


: pas bien référence : TB
=> Modification de la signature de ToLower ()

string & ToLower (string & Str)


{

return str;
}


cout << ToLower (Chaine);

Passage par Passage par


référence : TB référence : TB

On a fait une unique allocation mémoire de chaine.


Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
F. Arguments de
commande
F.1 Utilisation

Modification de la signature du main ()

int main(int argc, char *argv[])

argc : nombre d’arguments de la commande (le nom de l’éxecutable compte);


argv : tableau des arguments
argv[0] : executable
argv[1] : 1er argument
argv[2] : 2nd argument
F.2 Manipulation

Il faut transformer (transtyper) les arguments de commande en leur type C++ correspondant.

Chaine de caractères
string (argv[i]);

Entier
stoi (argv[i]);

Entier naturel
stoul (argv[i]);
F.3 Fixer des arguments de commande dans Qt
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
G. Segmenter ses fichiers
Il existe 3 types de fichiers ayant pour extension :
• .h : regroupe toutes les signatures des fonctions;
• .cpp : regroupe touts les corps des fonctions déclarées dans le .h + d’autres fonctions
« locales »;
• .hpp : regroupe les signatures + corps des fonctions.

Règles :
1. Les fichiers de signature et de corps doivent posséder le même nom (à la casse près)!
2. Les paramètres par défaut ne sont présents que dans le fichier d’extension .h
3. On ne doit pas trouver deux fonction ayant la même signature dans le même espace de
nom, quelque soit le(s) fichier(s) où elles se trouvent
4. Le fichier XXX.h commence obligatoirement par
#ifndef __XXX_H
#define __XXX_H
5. Le fichier XXX.h se termine par
#endif
6. Le fichier XXX.cpp doit contenir
#include "XXX.h"
G.1 Exemple

nsUtil.h

#ifndef __NSUTIL_H
#define __NSUTIL_H


namespace nsUtil
{
std::string & ToLower (std::string & Str);

}
#endif

Résolution de portée obligatoire dans les


fichiers d’entête
nsUtil.cpp

#include "nsUtil.h"
using namespace std;

string & nsUtil::ToLower (string & str) {…}

La résolution de portée se fait ici

main.cpp

#include "nsUtil.h"
using namespace std;
using namespace nsUtil;

cout << ToLower (Chaine);


G.2 duplicate symbol for architecture x86_64

Cause : deux fonctions de même signature appartiennent au même


espace de nom.

Solution : mettre l’une des deux dans un espace de nom anoyme

Demo Qt
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
H. Bloc à unique instruction
H.1 Règle

Lorsqu’un bloc contient une unique instruction, les accolades {} l’entourant


sont superflues

Exemple (dans un bloc alternatif) :


int i; int i;
cin >> i; cin >> i;
if ((i % 2) == 0) if ((i % 2) == 0)
{ cout << "le chiffre est pair";
cout << "le chiffre" else
<< " est pair"; cout << "le chiffre est impair";
}
else
{
cout << "le chiffre"
<< " est impair";
}
Exemple (dans un bloc répétitif) :

for (unsigned i (0); i < Minusc.size (); i = i + 1)


cout << Minusc [i];

Exemple (bloc alternatif dans un bloc répétitif) :

for (unsigned i (0); i < 42; i = i + 1)


if (Rand (0, 2) == 0)
Vu comme une
cout << "le chiffre est pair";
unique instruction
else
par le schéma
cout << "le chiffre est impair";
alternatif

Vu comme une unique instruction par le schéma répétitif


Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
I. Opérateurs mathématique
i = i + (expression_entiere);

peut être écrite :

i += (expression_entiere);

ou plus simplement :

i += expression_entiere;

Exemple :

int i = 25;
int Incr;
cin >> Incr;
// ...
i += Incr * 2; // ou i = i + (Incr * 2);
existe aussi pour autres opérateurs binaires

arithmétiques
i = i - (expression_entiere);
peut être écrite :

i -= (expression_entiere);

i = i / (expression_entiere);
peut être écrite :

i /= (expression_entiere);

*=, %= existent aussi


Exemples :

i -= Incr;  i = i - Incr;

De même :

i /= Incr;  i = i / Incr;

i -= Incr - 1;  i = i - (Incr - 1);

 i = i - Incr + 1;
et :

i /= Incr * 2;  i = i / (Incr * 2);

 i = i / Incr / 2;
i *= Incr / 2;  i = i * (Incr / 2);

mais n'est pas du tout équivalent à


i = i * Incr / 2;

Exemple :

i = 10;
Incr = 5;
i *= Incr / 2;  i = i * (Incr / 2);
= 10 * (5 / 2);
= 10 * 2;
= 20;

 i = i * Incr / 2;
= 10 * 5 / 2;
= 50 / 2;
= 25;
L'opérateur += existe aussi pour les strings

avec la même sémantique :

Chaine1 += Chaine2;  Chaine1 = Chaine1 + (Chaine2);

surcharge de l'opérateur + : concaténation

surcharge de l'opérateur += arithmétique

string S1 ("Coucou");
string S2 ("moi");

S1 += " c'est " + S2;

S1 = S1 + (" c'est " + S2);


Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
J. Opérateurs ++ et --
J.1 Pré-incrémentation - Pré-décrémentation
i = i + 1; // incrémentation
peut être écrite :
i += 1; // incrémentation

ou même :

++i; // incrémentation

L'expression ++i a un double effet :

i est incrémenté de 1

l'expression a pour valeur la nouvelle valeur de i

++ est ici l'opérateur de pré-incrémentation

--i : opérateur de pré-décrémentation similaire


Exemple d'utilisation

string Str ("Bonjour");


unsigned i = 3; i vaut 3;
cout << Str [++i]; i vaut 4
affichage de Str [4] : 'o'
cout << Str [++i]; i vaut 5
affichage de Str [5] : 'u'
Effet de bord (side effect)

i = 3;
affichage de 'o'
cout << Str [++i];
affichage de 'u'
cout << Str [++i];
pas équivalent à :

i = 3;
cout << Str [++i] << Str [++i];

ordre d'évaluation des opérandes : de droite à gauche


2 1 

i = 5 i = 4 
ordre d'injection des opérandes : de gauche à droite
3 4 

cout << Str [5] << Str [4]; affichage de 'u' suivi de'o'
autre exemple : afficher un mot lu au clavier
caractère/caractère à l'envers

string MotLu;
cin >> MotLu;

unsigned i = MotLu.size ();

for ( ; ; )
{
if (0 == i) break;
i = i - 1;  cout << MotLu [--i];
cout << MotLu [i];

}
// suite du programme


string MotLu;
cin >> MotLu;
for (unsigned i = MotLu.size (); i > 0; )
{
cout << MotLu [--i];
}
// suite du programme

ou même :

string MotLu;
cin >> MotLu;

for (unsigned i = MotLu.size (); i > 0; )


cout << MotLu [--i];

// suite du programme
J.2 Pos-incrémentation - Post-décrémentation

L'expression i++ a un double effet :

l'expression a pour valeur l'ancienne valeur de i

puis i est incrémenté de 1

++ est ici l'opérateur de post-incrémentation

i-- : opérateur de post-décrémentation similaire

string Str ("Bonjour");


unsigned i = 3; i vaut 3;
cout << Str [i++]; affichage de Str [3] : 'j'
i vaut 4
cout << Str [i++]; affichage de Str [4] : 'o'
i vaut 5
exemple : afficher un mot lu au clavier
caractère/caractère à l'envers

string MotLu;
cin >> MotLu;

for (unsigned i = MotLu.size (); i-- > 0; )


cout << MotLu [i]
Plan
A. Le type string (part 2)

B. Espaces de noms nommés

C. Espaces de noms anonymes

D. Valeur par défaut

E. Passage optimisé des paramètres dans les fonctions

F. Arguments de commande

G. Segmenter ses fichiers

H. Allégement de code pour bloc à instruction unique

I. Allégement de code pour opérateurs mathématiques

J. Opérateurs ++ et –-

K. Opérateur ternaire
K. Opérateur ternaire
K.1 Utilité Eviter les redondances

char C;
cin >> C;

if (' ' == C || '\t' == C)


cout << C << " est un espace" << endl;
else
cout << C << " n'est pas un espace" << endl;

char C;
cin >> C;
cout << C;
if (' ' == C || '\t' == C)
cout << " est";
else
cout << " n'est pas";

cout << " un espace" << endl;


K.2 Simplification du code C++ : opérateurs ? :
Syntaxe

expression ? expression : expression

Sémantique

expression_1 ? expression_2 : expression_3

La valeur renvoyée par cet opérateur est égale à


expression_2 ou expression_3
selon que expression_1 est vrai ou faux


expression_1 doit être de type booléen,

expression_2 et expression_3 doivent être de même type,


qui est aussi celui du résultat
Exemple :

char C;
cin >> C;

cout << C;
if (' ' == C || '\t' == C)
cout << " est";
else
cout << " n'est pas";
cout << " un espace" << endl;
expression_1 booléen
char C;
cin >> (C); expression_2 expression_3
même type : NTCTS
cout << C
<< ((' ' == C || '\t' == C) ? " est" : " n'est pas")
<< " un espace" << endl;
operateur ? :
résultat injecté : Littéral chaine de caractères
Un des avantages : une seule instruction  if ..., for...
Exemple :

double X, AbsX;
cin >> X;

if (X < 0.0)
AbsX = -X;
else
AbsX = X;

double X, AbsX;
cin >> X;

AbsX = (X < 0.0) ? -X : X;


Exemple :
unsigned ValidRang (char CodeOp, unsigned Rang, unsigned Max)
{
if ('I' == CodeOp)
return min (Rang, Max);
else
return min (Rang, Max - 1);

} // ValidRang()

mieux :

CodeOp) ?
return ('I' == e1 min (Rang,
e2 Max)

: min (Rang,
e3 Max - 1);
encore mieux :

return min (Rang, ('I' ==e1CodeOp) ? Max e3 - 1);


e2 : Max
Exemple :

#include <cctype> // toupper(), isxdigit(), isalpha()

short Hexa2Dec (const char C)


{
if ( ! isxdigit (C)) return -1;
if (isalpha (C))
return toupper (C) - 'A' + 10;
else
return C - '0';

} // Hexa2Dec()

if ( ! isxdigit (C)) return -1;


return isalpha (C) ? toupper (C) - 'A' + 10 : C - '0';
return (!isxdigit (C)) ? -1
: isalpha (C) ? toupper (C) - 'A' + 10
: C - '0';
62 colonnes
K.3 Attention

cout << X;
if (X >= 0) cout << " non";
cout << " négatif"; pas de même type

cout << X << ((X >= 0) ? " non" : ) << " négatif"; FAUX

pas de même type

cout << X << ((X >= 0) ? " non " : ' ') << "négatif"; FAUX

même type

cout << X << ((X >= 0) ? " non " : " ") << "négatif"; JUSTE

Vous aimerez peut-être aussi