1.2- Variables, affichage de valeurs et tableaux

Transcription

1.2- Variables, affichage de valeurs et tableaux
1.2- Variables, affichage de valeurs et tableaux
1- Variables : type et déclaration
2- Variables : affectation de valeurs et opérateurs
3- Les constantes et les énumérations
4- Transtypage
5- Affichage de valeurs et récupération de valeurs saisies par l'utilisateur
6- Les tableaux
7- Commentaires
1 Variables : types et déclaration
C++ est un langage typé : toutes les variables utilisées ont dues êtres préalablement déclarées. Le chapitre sur les pointeurs
donnera des indications sur l'organisation de la mémoire.
Nom variable
Certaines limites sur les noms de variables :
•
Les noms de variables ne peuvent pas contenir un certain nombre de caractères particuliers, notamment :
{,},#,~,&,^,^,@ etc...
•
Aucun espace dans le nom des variables. Il existe deux manières d'écrire les noms de variables : "sous total" ne
passera pas comme nom de variable, on choisira donc "sous_total" ou "sousTotal"
•
Pas de chiffre comme premier caractère d'un nom de variable
•
Les noms sont sensibles à la casse, c'est à dire que : "valeur" et "Valeur" désignent deux variables différentes
•
Un nom de variable ne peut pas être un mot clé de C++. A défaut de tous les connaître, l'EDI qu'on utilise met
généralement en évidence les mots clés du langage et permet d'éviter cet ecueil.
Pour les variables, une convention souvent adoptée est la suivante : on écrit les noms des variables en commençant par une
minuscule et en introduisant des majuscules à chaque nouveau mot dans le nom de la variable :
int nombreEtudiants;
En poursuivant cette convention, les noms de fonctions sont écrits de la même manière que les noms de variables. Les
constantes sont écrites en majuscules :
const double PI 3.14;
et les noms de classe seront écrits en commençant par une majuscule et en continuant en minuscules.
Ces prescriptions n'ont pas valeur d'obligation, mais elles facilitent la relecture d'un code par son auteur, voire sa lecture par
d'autres personnes.
Types primitifs
Le C++ définit 4 types primitifs (built-in data types), soit des types qui ne sont pas des types objets, des types que le
compilateur comprend directement. Chaque type correspond à un encodage. Un encodage est une mise en correspondance
d'une valeur avec un code. Par exemple, pour coder des valeurs entières avec des séries de bits, on peut donner comme code
pour chaque entier sa valeur en base 2. Soit par exemple un codage sur 8 bits :
0 => 000 000 00
1 => 000 000 01
2 => 000 000 10
...
10 => 000 010 10
...
255 => 111 111 11
La puissance lexicographique d'un code est le nombre de valeurs qu'il est possible d'encoder avec ce code. Donc par exemple,
8
un ensemble de 8 bits, soit 1 octet (Byte en anglais), a une puissance lexicographique de 2 =256 valeurs. En déclarant une
variable, on demande à la machine de réserver un nombre d'octets pour cette variable. Comme on déclare toujours une
variable en lui affectant un type (C++ est un langage typé), la machine saura comment encoder (remplir et lire) les bits des
octets réservés.
Les 4 types primitifs en C++ sont char, int, float et double. Pour chacun des types la norme ne spécifie pas un nombre
d'octets, mais elle spécifie un nombre d'octets minimum et maximum. Les valeurs maximales et minimales pouvant être
stockées dans chacun des types de données sont définies dans les fichiers headers <climits> et <cfloat>. Un char est toujours
stocké sur au moins 1 octet (et généralement sur 1 octet seulement). Ce type peut être manipulé comme un entier, mais sert
aussi au stockage de caractères. Un int est de taille minimale 2 octets et sert à stocker des nombres entiers. Les types float et
double servent à stocker des décimaux.
La définition d'un type de donnée est modifiée par des specifiers : unsigned, signed, long, short. Ces derniers servent à
modifier la définition. Pour une variable unsigned, elle n'aura pas de signe. En supposant qu'un int soit codé sur 4 octets, un
signed int varie dans [-32768:32767] alors qu'un unigned int varie dans [0:65535]. Les specifiers signed et unsigned ne
s'appliquent que pour int et char. Les specifiers long et short modifient le nombre d'octects consacrés à la variable. Ils
s'appliquent uniquement à int, à l'exception du type long double. Un long int se verra réserver plus d'octets en mémoire qu'un int
qui lui même se verra plus réserver d'octets en mémoire qu'un short int.
Dans ce qui suit, on donne le codage standard des valeurs. Est ensuite proposé une procédure pour tester les tailles
respectives en fonction de votre implémentation.
char
Entier entre -128 et 127
unsigned char
Entier entre 0 et 255
short int
"Petit" entier à valeurs positives et négatives
unsigned short int
"Petit" entier à valeurs positives
int
Entier à valeurs positives et négatives
unsigned int
Entier à valeurs positives et négatives
long int
"Grand" entier à valeurs positives et négatives
unsigned long int
"Grand" entier à valeurs positives
float
Flottant décimal
double
Flottant double
long double
Flottant double de grande taille
bool
Variable à valeur dans true false.
Dans le tableau précédent, on n'a pas fait apparaître signed char, signed short int ou signed long int, puisqu'ils sont
respectivement équivalents à char, short int, long int.
Pour le type short int, on peut se contenter de mettre short (idem pour long), ainsi :
short int nombreEtudiants;
et
short nombreEtudiants;
sont deux instructions équivalentes.
Pour connaître la taille précise consacrée au stockage de chaque type, pour la machine et le compilateur qu'on utilise, on peut
aller voir la documentation du compilateur. Une autre solution consiste à exécuter le code suivant :
#include <iostream>
int main()
{
std::cout << "La taille d'un int est \t\t\t " << sizeof(int) << " octets\n";
std::cout << "La taille d'un short est \t\t " << sizeof(short int) << " octets\n";
std::cout << "La taille d'un long est \t\t " << sizeof(long int) << " octets\n";
std::cout << "La taille d'un float est \t\t " << sizeof(float) << " octets\n";
std::cout << "La taille d'un double est \t\t " << sizeof(double) << " octets\n";
std::cout << "La taille d'un char est \t\t " << sizeof(char) << " octets\n";
std::cout << "La taille d'un boolean est \t\t " << sizeof(bool) << " octets\n";
std::cout << "La taille d'un long double est \t\t " << sizeof(long double) << " octets\n";
}
Sur l'utilisateur de l'auteur de ce cours, l'affichage suivant est constaté avec ce code :
La taille d'un int est
4 octets
La taille d'un short est
2 octets
La taille d'un long est
4 octets
La taille d'un float est
4 octets
La taille d'un double est
8 octets
La taille d'un char est
1 octets
La taille d'un boolean est
1 octets
La taille d'un long double est
12 octets
Dans ce code, on utilise l'opérateur sizeof. Cet opérateur renvoie pour un type donné, le nombre d'octets que l'implémentation
du compilateur réserve. Noter que cet opérateur utilisé avec une variable permet d'obtenir la taille en mémoire du type de cette
variable.
Déclaration d'une variable
Pour déclarer une variable n de type entier :
int n;
Il est possible de définir plusieurs variables à la fois :
unsigned int monAge, monPoids;
long int surface, largeur, longueur;
Dans le code qui précède, monAge, monPoids sont définies comme des variables unsigned int. Les variables surface, largeur
et longueur sont déclarées de type long int.
Char
8
Une variable de type char est codée sur un octet, soit 8 bits. En tout il y a 2 =256 caractères numérotées de 0 à 255 qui sont
les 256 caractères de la norme ASCII. char peut être considéré comme un type entier : on peut ajouter, multiplier des char, ils
se comporteront comme des entiers. Cependant, en fonction des contextes, le contenu des variables pourra être interprété non
pas comme le nombre, mais comme le caractère correspond au nombre dans la norme ASCII. Ansi :
char a=67,b='0',c='6',d=6;
std::cout << a << " " << b << " " << c << " " << d << "\n";
L'exécution de ce code affiche :
C06♠
On peut en conclure que 'C' est le 67ème caractère dans la norme ASCII et que '♠' est le 6ème caractère de la norme. Il faut
bien faire la différence entre l'instruction
char c='6';
qui affecte la valeur entière correspondant au caractère 6 à la variable c, et l'instruction :
char d=6;
qui affecte la valeur entière 6 à la variable d/
Des caractères spéciaux sont disponibles :
Valeur entière
Caractere
Signification
\a
Alerte sonore
7
\b
Retour en arrière
8
\f
Saut de page
12
\n
Nouvelle ligne
10
\r
Retour chariot
13
\t
tabulation
9
\v
Tabulation verticale
11
\'
guillemet simple
39
\"
guillemet double
34
\?
Point d'interrogation
63
\\
Barre oblique inverse
92
correspondante
On verra leur utilisation de manière plus précise dans le chapitre sur les chaînes dans la partie 2. Pour l'instant, on peut les
utiliser pour améliorer l'affichage en ligne de commandes :
#include <iostream>
int main()
{
std::cout << "Voici un peu de texte\n";
std::cout << "\tVoici un peu de texte\n";
std::cout << "\vVoici un peu de texte\n";
std::cout << "\aVoici un peu de texte\n";
std::cout << "En C++, le separateur \' sert a isoler les caracteres et \" les chaines";
}
Ici, on voit qu'en ligne de commande, on a un saut de ligne qui est ajouté à la fin de chaque phrase : cela parce qu'on finit les
chaînes par le caractère de saut de ligne '\n'. Concernant, la dernière instruction, elle sert à introduire des guillemets au sein du
texte que l'on veut afficher.
Bool
Une variable bool peut aussi être manipulée comme un entier. Elle est codée sur 1 octet. La valeur 0 encode "FALSE", tout
autre valeur encode "TRUE".
int n=5,m=77;
bool b=(n>m);
bool b1=(5>=4);
std::cout << b << " " << b1 << "\n";
2 Variables : affectation de valeurs et opérateurs
Attention : en C++, la déclaration ne vaut pas affectation implicite. Dans le cas des langages comme java ou vba, la
déclaration sans affectation d'une variable int conduit à son initialisation à 0. En C ou en C++, cela n'est pas vrai. Lorsque l'on
déclare une variable, la machine sélectionne un emplacement de suffisamment d'octets qui est libre. Cet emplacement a
cependant pu servir lors du fonctionnement d'une application ou d'un programme précédent, de sorte que les bits des octets ont
déjà été modifiés et ce, de manière tout à fait imprévisible. Donc en déclarant simplement une variable, on ne pas du tout être
assuré de sa valeur.
#include <iostream>
int main(){
int a;double b;
std::cout << a << " " << b;
}
Affectation de valeurs aux variables
= est l'opérateur d'affectation. Quelques exemples :
int i=8;/*Declaration et affectation*/
int j;/*Declaration*/
j=7;/*Affectation*/
char c='a';/*Declaration et affectation (initialisation)*/
char d='\n';/*Décalaration et affectation, caractère de saut de ligne*/
char tabulation='\t';/*Décalaration et affectation, caractère de tabulation*/
int n1,n2,n3;/*Declaration multiple*/
double x1=0.1,x2=1002.5,x3=9;/*Decalaration et affectation multiple*/
long int h=89;/*Declaration d'un entier de type long*/
unsigned short x;/*Declaration d'un entier short non signé*/
De manière générale, l'opérateur = transfère la valeur située à droite ou r-value (r pour right) dans l'opérande à gauche de
l'opérateur. L'opérande située à gauche de = est la l-value (l pour left)
Que se passe t'il si on cherche à passer une valeur trop grande à une variable d'une taille trop petite ? Sur la machine de
l'auteur, un short int est codé sur 2 octets. Soit, la valeur maximale d'un unsigned short int est 65535
#include <iostream>
using namespace std;
int main() {
unsigned short int n1=65535;
unsigned short int n2=65536;
unsigned short int n3=65537;
cout << n1 << " " << n2 << " " << n3 << "\n";
}
Dans ce cas, le code s'exécute sans signaler erreur et affiche 65535, 0 et 1 : on revient à 0 et on recommence le compte à
partir de 65535. Il convient d'avoir conscience de la que ces erreurs sont possibles.
Opérateurs arithmétiques
On dispose d'abord des opérateurs traditionnels : +, -, /, *. Ces opérateurs s'utilisent sans surprise et avec l'ordre de
priorité suivant : * et / sont prioritaires sur + et -. A l'instar de nombreux langages, C++ propose un opérateur modulo qui a le
même niveau de priorité que * et / :
int a=5;
int b=78;
std::cout << b%a;
Deux opérateurs unaires, un de décrémentation et d'incrémentation : ++ et - -. Ces deux opérateurs servent à ajouter
ou enlever 1 à une variable.
int a=5;
a++;
std::cout << a << "\n";
double b=0.9;
b++;
std::cout << b;
D'autres opérateurs sont introduits qui permettent de simplifier les expressions. L'opérateur += ajoute une valeur à une
variable :
int a=5;
a+=3; // cette instruction est absolument équivalente à a=a+3;
std::cout << a;
Il existe des opérateurs qui fonctionnent de la même façon : /=, *=, -=. Le bout de code suivant permet de tester ces
opérateurs :
int a=5;
a-=2; // cette instruction est absolument équivalente à a=a-2;
double x=0.5,y=90.3;
x/=0.25;
y*=10;
// cette instruction est absolument équivalente à x=x/0.5;
// cette instruction est absolument équivalente à y=y*10;
std::cout << a << " " << x << " " << y;
Dans le cas d'opérations complexes, on peut rajouter des parenthèses pour éviter les erreurs dans l'exécution de l'opération.
Ceci a par ailleurs comme qualité de faciliter la lecture du code. On peut également utiliser cet exemple :
#include<iostream>
int main()
{
std::cout << "5+3=" << 5+3 << std::endl;
std::cout << "156.45-3=" << 156.45-3 << std::endl;
std::cout << "9*7=" << 9*7 << std::endl;
std::cout << "675%37=" << 675%37 << std::endl;
return 0;
}
Expression booléennes et conditions logiques
Dans l'optique de spécifier des expressions booléennes, on introduit un certain nombre d'opérateurs de comparaison. Une
expression booléenne est de valeur vraie ou fausse. Elle est composée d'expressions booléennes élémentaires articulées par
des connecteurs logiques (voir ci dessous). Une expression booléenne élémentaire utilise un opérateur de comparaison :
Opérateur de comparaison – égalité
Opérateur de comparaison -inégalités larges
Opérateur de comparaison – inégalités strictes
Opérateur de comparaison – inégalité
==
>= <=
>
<
!=
Un expression booléenne élémentaire est de la forme : valeur - opérateur de comparaison – valeur. Comme ces expressions
sont à valeurs booléennes, il est possible d'en affecter le résultat à un booléen :
int a=8;char c='\n';
bool b1=(a==5); // a==5 est une expression booléenne élémentaire
bool b2=(a>=7); // a>=5 est une expression booléenne élémentaire
bool b3=(c<'t'); // c<'t' est une expression booléenne élémentaire
Les expressions booléennes élémentaires sont constructibles à partir des valeurs et des types de base. Les valeurs comparées
peuvent être de tous les types de base.
Il est également possible de construire des expressions booléennes complexes à partir de booléens, d'expressions booléennes
élémentaires. Les conditions sont enchaînées par des opérateurs logiques :
Opérateur logique ET
&&
Opérateur logique OU
||
Opérateur logique NON
!
L'enchainement des conditions s'avère très rapidement nécessaire. Par exemple, l'expression suivante :
int a=5,b=6,c=7;
bool b=a>b>c;
La deuxième instruction ne sera pas accepté à la compilation. Pour tester que b est entre a et c, il faut écrire :
int a=5,b=6,c=7;
bool b=a>b && c>b;
A noter que le ! est prioritaire sur le && lui même prioritaire sur le ||. Quelques exemples :
bool b1=(5==1 && 6>5);
std::cout<<"La valeur de b1 "<<(b1) << "\n";/*Affiche 0 qui correspond à faux*/
bool b2=('\n'=='\n' || 5>6);
std::cout <<(b2) << "\n";/*Affiche 1*/
bool b3=(7!=5.65 && (3>4 || 6>5));
std::cout << (b3) << "\n";/*Affiche vrai*/
bool b4=b3 || !b1 && 7.8>5;
std::cout << (b4) << "\n";/*Affiche vrai*/
Comme toute valeur entière différente de 0 est assimilable à un bool à valeur vraie, les opérateurs peuvent être utilisés avec
des formes particulières :
int i=5,j=6;
std::cout << i&&j << "\n"; // affiche 1
i=0;
std::cout << i&&j << "\n"; // affiche 0
Opérateur conditionnel ternaire
C++ fournit un opérateur ternaire quand tous les autres opérateurs étaient unaires ou binaires. Cet opérateur est de la forme :
(expression1) ? (expression2) : (expression3);
ce qui signifie : si l'expression1 est vraie, retourner la valeur de expression2, sinon retourner la valeur de expression3. Par
exemple :
double x,y;
std::cout << "Rentrer une premiere valeur\n";
std::cin >> x;
std::cout << "Rentrer une seconde valeur\n";
std::cin >> y;
double z=(x>=y)?x:y;
std::cout << "La valeur max qui a ete saisie : " << z << "\n";
Cet opérateur permet d'éviter d'avoir à introduire des structures de contrôle, pour des cas de conditionnalité simples. Noter
également qu'on a introduit cin. Alors que cout est un flux à destination de l'invite de commandes, cin est un flux depuis l'invite
de commandes qui permet de récupérer des valeurs saisies par l'utilisateur.
Les opérateurs "bitwise"
Ces opérateurs permettent de manipuler les bits individuels d'un nombre. Ces opérateurs n'existent que pour les
variables int, char et long.
ème
a&b renvoie un entier, soit une série de bits, pour le n
le n
ème
bit de b à 1, sinon, il sera à 0. Pour a|b, pour le n
sont à 0. Pour a^b, pour le n
ème
le n
ème
ème
bit de la valeur calculée, il sera à 1 si le n
bit du resultat, il sera à 0 seulement si les deux n
bit du résultat, il sera à 0 si les deux n
bit de retour sera l'inverse du n
ème
ème
ème
bit de a est à 1 et
ème
bit bits de a ou b
bit de a et b sont à 0 ou si les deux sont à 1. Pour ~a,
bit de a.
5:
0
0
0
...
0
0
1
0
1
6:
0
0
0
...
0
0
1
1
0
5&6 :
0&0=0
0&0=0
0&0=0
...
0&0=0
0&0=0
1&1=1
0&1=0
1&0=0
5|6 :
0|0=0
0|0=0
0|0=0
...
0|0=0
0|0=0
1|1=1
0|1=1
1|0=1
5^6 :
0^0=0
0^0=0
0^0=0
...
0^0=0
0^0=0
1^1=0
0^1=1
1^0=1
~5
~0=1
~0=1
~0=1
...
~0=1
~0=1
~1=0
~0=1
~1=0
Donc, 5&6 donne 4, 5|6 donne 7, 5^6 donne 3.
Pour les opérateurs bitwise non unaires, il est possible de les manipuler avec : ^=, &=, |= à l'instar des opérateurs classiques.
Ces opérateurs n'ont pas un usage immédiat. Leur utilisation permet cependant de concevoir un certain nombre d'optimisations
dans des cas particuliers.
Première source d'erreurs
Attention à ne pas confondre respectivement les opérateurs == et =, les opérateurs && et &, les opérateurs || et |. La difficulté
principale vient du fait que les erreurs ne sont pas toujours signalée à la compilation. Soit l'expression conditionnelle suivante :
double x,y;
std::cout << "Rentrer une premiere valeur\n";
std::cin >> x;
std::cout << "Rentrer une seconde valeur\n";
std::cin >> y;
double max;
if(x=y)
std::cout << "Les deux valeurs saisies sont egales";
else
std::cout << "Les deux valeurs saisies sont differentes";
Si on teste ce code, on constate qu'à moins de rentrer 0 comme seconde valeur, ce code renvoie toujours la valeur de x comme
la valeur maximale. Pourquoi ? Lors de l'exécution de if(x=y), la machine commence par exécuter x=y qui est une opération
d'affectation de la valeur de y à la valeur de x. Ensuite la machine test if(x) : soit, dès que x est différent de 0, la machine
renvoie vrai. Des préventions identiques sont à avoir par rapport aux opérateurs pré-cités.
Attention également à ne pas importer des opérateurs qui n'existent pas dans le langage C++, alors qu'ils existent dans d'autres
langages : par exemple ^ n'est pas l'opérateur puissance en C++. L'erreur dans l'utilisation de l'opérateur n'est pas
spécialement évidente :
int n=5;
n=n^2;
std::cout << n;
3 Les constantes et les énumérations
L'intérêt d'une constante est qu'elle permet d'optimiser le code au moment de la compilation. Pour déclarer une constante, on
donne son type et on utilise le mot clé const. Par convention, on écrit le nom des constantes en majuscules. Pour définir une
constante on précise son type.
const double PI=3.14;
Une énumérations est une liste de constantes de type unsigned int. On utilise le mot clé enum. U
enum categorie {CADRE, OS, COMPABLE, DRH, PRESIDENT};
Par défaut, la première valeur de l'énumération est 0, le second élément est 1 etc... Soit sur l'exemple : CADRE=0, OS=1 etc...
Il est possible de déclarer une variable de cette énumération :
categorie myCat=OS;
4 Transtypage
Le transtypage peut être implicite, mais il existe aussi des opérateurs explicites ou cast operators. Le transtypage peut être
source d'erreurs, même dans le cas des programmes les plus simples.
Transtypage implicite
int a=5;
float x=a;
Ici le compilateur appelle une fonction implicite ou rajoute du code pour faire la conversion. Il est possible de faire des
transtypage explicites. Si dans un calcul on introduit 200, ce sera considéré comme une variable entière (type int), si on introduit
200.0, ce sera considéré comme une variable réelle (type double). A noter que l'on peut faire en sorte que la saisie d'une valeur
décimale ne soit pas considérée comme un double mais comme un float :
float x=200.9f;
Dans un calcul entre deux int, le résultat renvoyé sera transtypé vers un int et donc, les résultats obtenus peuvent être
aberrants :
int a=5;
std::cout << 5/200 << "\n";
std::cout << 5/200.0 << "\n";
Ce code affiche 0 et 0.025. Une autre manière de le faire est de procéder à un transtypage :
std::cout << 5/(double)200 << "\n";
Ici 0.025 sera affiché. On comprend bien ce qui se passe dans le cas d'un transtypage d'un type plus petit vers un type plus
large. C'est à dire que tout int a un équivalent double, sans difficulté. En revanche, l'inverse n'est pas vraie. Il est possible à
l'utilisateur de forcer le transtypage dans le sens inverse :
std::cout << (int)(5/(double)200) << "\n";
Dans ce cas, 0 sera affiché. En rajoutant un type entre parenthèse, on indique au compilateur de ne pas considérer la valeur
comme il l'aurait considérée par défaut : 200 est considéré comme un int par défaut et si la machine rencontre cette valeur dans
un calcul, elle fera le calcul en créant un int comme variable intermédiaire dans le calcul. En mettant (double)200, on stocke la
valeur 200 dans une variable intermédiaire double. Le transtypage d'un double vers un int se fait par une troncature.
Opérateurs de transtypage
Les formes de transtypages précédentes sont héritées du C et ne sont conservées que dans un soucis de compatibilité
ascendante des langages C et C++. Des opérateurs typiques de C++ ont été introduits qu'il convient d'utiliser en priorité :
static_cast
Cet opérateur est à utiliser pour les transtypages qui ne posent pas de difficultés, y compris ce qui pourrait être fait
automatiquement sans expliciter le transtypage.
void func(int) {}
int main() {
int i = 30000; long l;
float f; double d=0.0;
int x;
// (1) Des transtypages implicites vers un type plus large :
l = i;
f = i;
//Explicitation de ces transtypages :
l = static_cast<long>(i);
f = static_cast<float>(i);
/* (2) Des transtypages implicites avec une déperdition potentielle d'information mais qui sont automatiquement rélalisés
par le compilateur :*/
i = l;
i = f;
x = d;
func(d);
/* pour éviter les avertissements du compilateur et ne pas oublier qu'il y a transtypage lors de le la relecture :*/
i = static_cast<int>(l);
i = static_cast<int>(f);
char c = static_cast<char>(i);
x = static_cast<int>(d);
func(static_cast<int>(d)); // More explicit
}
const_cast
Pour transtyper depuis une constante vers une variable non constante, on utilise const_cast.
int main() {
const int i = 0;
int *j;
j
= const_cast<int*>(&i); // Preferred
volatile int k = 0;
int* u = const_cast<int*>(&k);
}
reinterpret_cast
Cette méthode dangereuse et très peu utile en pratique n'est pas évoquée ici.
dynamic_cast
Cette méthode sera évoquée plus loin dans la suite du cours.
Dans la suite du cours ou dans les exemples proposés, l'auteur aura tendance à faire des transtypages à la mode C et non pas
à la mode C++, soit :
int n=5
double x=7/(double)5;
plutôt que
int n=5;
double x = 7/static_cast<double>(n);
Pourquoi bien expliciter les cast ? Ce qui fonctionne automatiquement en dehors des cast explicités dépend du compilateur et
des choix de celui qui l'a rédigé, tandis que le comportements des cast est clair. A la limite, un compilateur n'autorisant pas un
transtypage automatique serait préférable.
5 Affichage de valeurs et récupération de valeurs saisies par l'utilisateur
Écrire en sortie sur l'invite de commande
L'instruction qui permet d'écrire sur l'invite de commande a déjà été évoquée plusieurs fois dans ce qui précède. On l'a
utilisée sans préciser son sens. std::cout vient de la libairie <iostream> (std::cout n'est pas renconnu si on n'inclut pas la librairie
précédemment). Ce peut être une variable, une constante ou une fonction. Ici, c'est une variable objet. std::cout est un flux de
sortie. En l'occurrence, sous Windows, il sert à écrire sur l'invite de commande, sous Linux, il sert à écrire sur le shell. Plus ou
moins implicitement, on a utilisé std::cout selon différentes syntaxes :
std::cout << "Les sanglots longs des violons\n"; //on demande l'affichage d'une chaine
std::cout << 5+6; // le calcul sera effectué puis son résultat affiché
int j=7;
std::cout << '\n' << j; //on affiche un caractère puis la valeur contenue dans la variable j
Les chaînes de caractères sont écrites entre des guillemets. Généralement, le compilateur permet de les mettre en évidence au
sein du code. Des développements sur leur manipulation seront apportés dans la deuxième partie du cours.
Pour introduire des sauts de ligne, on peut également trouver cette syntaxe :
std::cout << "Les sanglots longs des violons" << std::endl;
std::cout << 5+6;
int j=7;
std::cout << std::endl << j;
Récupérer des données utilisateurs
Là aussi on utilise un objet de la librairie <iostream>, l'objet std::in. Pour indiquer à la machine de lire la valeur saisie par
l'utilisateur :
std::cin >> x;
La valeur sera lue une fois que l'ordinateur aura appuyé la touche ENTREE. Le code suivant illustre la récupération de
variable :
#include
int main()
{
double x;
std::cout << "Rentrez une valeur entiere" << std::endl;
std::cin >> x;
std::cout << "La valeur que vous avez saisie " << x << std::endl;
return 0;
}
Attention : seul un certain nombre des caractères de la chaîne sera pris en compte dans le cas d'une saisie incohérente : dans
le code précédent, faire de x une variable char et voir le rendu si on saisit une chaîne ou un nombre décimal. Faire la même
chose en faisant de x une variable int et en passant un nombre décimal ou un entier de taille trop importante.
6 Les tableaux
Déclaration d'un tableau
Les tableaux sont une première forme de collection. On en donne ici une première présentation qui sera complétée
dans le cours sur les pointeurs et dans le cours sur les objets. Pour déclarer une variable tableau :
int t[5];
Avec l'instruction précédente, on définit une variable t comme un tableau de 5 entiers numérotés de 0 à 4. Par suite, il est
possible d'utiliser le tableau en affectant des valeurs aux éléments du tableau ou en utilisant les valeurs des éléments du
tableau dans des calculs :
t[1]=6;
// affectation d'une valeur au 2ème élement du tableau
int a=5*t[2];
//utilisation d'une valeur du tableau dans un calcul
L'avantage principal des tableaux est que l'accès aux éléments du tableau est très rapide. Le désavantage principal
des tableaux est qu'il n'est pas possible de redéfinir leur taille en cours d'exécution. De fait, on sera amener à utiliser d'autres
collections. Il serait possible de définir des collections à la manière du C, mais ce cours ne propose pas une telle démarche : la
partie 2 introduira un objet collection de nom vector, qui est moins performant que les tableaux en terme de temps d'accès,
mais qui permet de gérer des collections d'objets de taille non fixe.
Initialisation des tableaux
Note : la déclaration des tableaux ne vaut pas initialisation des variables du tableau. Sans une initialisation postérieure
à la création du tableau, il est impossible de savoir quelles sont les valeurs introduites dans le tableau. Donc, le programmeur
devra introduire des valeurs dans le tableau en fonction du contexte :
int tailleTableau=50;
int tab[tailleTableau];
for(int i=0;i<tailleTableau;i++)
tab[i]=0
Ce code utilise une boucle et permet d'initialiser l'ensemble des valeurs du tableau à 0.
Une autre manière d'initialiser le tableau en même temps qu'on le déclare :
int tailleTableau[4]={10,20,30,40}
L'instruction :
int tailleTableau[]={10,20,30,40};
déclare et initialise le tableau comme un tableau de taille 4 avec 10, 20, 30 et 40 comme valeurs.
Taille d'un tableau
Pour connaître la taille d'un tableau :
long tailleTableau=sizeof(tab)/(szieof(tab[0]));
Tableau de plusieurs dimensions
Il est également possible de déclarer et de manipuler un tableau de plusieurs dimensions :
double x[5][6];
ici le tableau x est de 30 éléments double.
7 Commentaires
Il existe deux manières d'introduire des commentaires sur du code. Elles ont été utilisées dans ce document. La première
manière est de commencer une ligne par \\ : tout ce qui sera écrit sur la ligne ensuite sera considéré comme du commentaire.
La seconde manière consiste à commencer par /* : tout ce qui sera écrit, même si cela représente plusieurs lignes, sera
considéré comme du commentaire jusqu'à */.