C++ est un langage
C++ est un langage
C++ nécessite de transformer les fichiers sources qui contiennent le code C++ en un fichier exécutable, ce qui s’appelle la compilation.
L’option pour que le compilateur m’avertisse de potentielles erreurs est
L’option pour que le compilateur m’avertisse de potentielles erreurs est
L’option -g
est pour le debug. Pour les avertissements,
je vous rappelle qu’il est dangereux de les ignorer !
Je suis capable de lire un fichier exécutable
Je suis capable de lire un fichier exécutable
Les fichiers exécutables contiennent des instructions en binaire qui ne sont pas lisibles par les humains.
Je compile le code suivant, et le compilateur m’envoie cette erreur:
#include <iostream>
int main() {
double a=2 double b=3;
std::cout << "La somme vaut " << a+b << std::endl;
return 0;
}
Qu’est-ce qui cause cette erreur ?
Je compile le code suivant, et le compilateur m’envoie cette erreur:
#include <iostream>
int main() {
double a=2 double b=3;
std::cout << "La somme vaut " << a+b << std::endl;
return 0;
}
Qu’est-ce qui cause cette erreur ?
J’ai oublié un point-virgule qui complèterait la déclaration de
a
: double a=2;
. Tant que le compilateur ne
voit pas de point-virgule, il continue, et doit donc comprendre ce que
veut dire “2 double
”. Ça n’a pas de sens en C++, donc il
dit qu’il y a une erreur à cet endroit, même si l’oubli est juste
avant.
Dans un programme, je dois afficher l’heure à laquelle un train arrive, si je connais son heure de départ, sa vitesse moyenne et la distance à parcourir.
Quel type de variable vais-je utiliser pour manipuler le résultat à afficher en heure et minutes ?
Quel type de variable puis-je utiliser pour calculer le résultat à une minute près avant l’affichage ?
Dans un programme, je dois afficher l’heure à laquelle un train arrive, si je connais son heure de départ, sa vitesse moyenne et la distance à parcourir.
Quel type de variable vais-je utiliser pour manipuler le résultat à afficher en heure et minutes ?
Quel type de variable puis-je utiliser pour calculer le résultat à une minute près avant l’affichage ?
L’affichage à l’écran se fait à l’aide de caractères. Surtout si je
veux un bel affichage avec un format (hh:mm). On utilisera donc une
chaîne de caractères.
Pour calculer le résultat, on aura sans doute
un opération qui impliquera des nombres réels (vitesse*distance). On
peut stocker le résultat dans un float
ou un
double
, mais également dans un int
, ce qui
tronquerait la partie décimale du nombre. Ce ne serait pas grave, parce
que le résultat est à une minute près.
Pour votre culture, il existe en fait un type time_t
qui a
été spécifiquement conçu pour gérer les données temporelles.
J’ai eu 11, 9 et 9 à mes contrôles dans un module. Je calcule la moyenne en faisant
#include <iostream>
int main() {
int n1(11), n2(9), n3(9);
std::cout << "Ma moyenne est de " << (n1+n2+n3)/3 << std::endl;
return 0;
}
Et ce programme me dit que j’ai 9, alors qu’en fait j’ai 9,66 et je pourrais espérer être remonté à 10!
Quel est le souci ?
J’ai eu 11, 9 et 9 à mes contrôles dans un module. Je calcule la moyenne en faisant
#include <iostream>
int main() {
int n1(11), n2(9), n3(9);
std::cout << "Ma moyenne est de " << (n1+n2+n3)/3 << std::endl;
return 0;
}
Et ce programme me dit que j’ai 9, alors qu’en fait j’ai 9,66 et je pourrais espérer être remonté à 10!
Quel est le souci ?
On peut déclarer et initialiser plusieurs variables d’un même type en
une fois sur un même ligne, pas de souci. (j’avoue je ne vous
l’avais pas dit avant) En revanche, l’erreur est dans la
division, car (n1+n2+n3)
est une addition d’entiers, donc
un entier. “3
” est une expression constante entière, donc
la division réalisée est entière, et le résultat tronqué par rapport à
la valeur réelle. Il aurait fallu écrire “3.
” au
dénominateur, ou mieux, utiliser des réels pour les notes, car elles
peuvent avoir des demi-points!
Laquelle de ces expressions utiliser pour tester l’égalité de deux
float
a
et b
?
(std::abs
calcule la valeur absolue de l’argument entre
parenthèses, et std::min
le minimum de deux nombres donnés
en argument)
a==b
std::abs(a-b)<1.e-7*std::min(std::abs(a),std::abs(b))
(a-1.e-7)==(b-1.e-7)
std::min(a,b)<1.e-7
Laquelle de ces expressions utiliser pour tester l’égalité de deux
float
a
et b
?
(std::abs
calcule la valeur absolue de l’argument entre
parenthèses, et std::min
le minimum de deux nombres donnés
en argument)
a==b
std::abs(a-b)<1.e-7*std::min(std::abs(a),std::abs(b))
(a-1.e-7)==(b-1.e-7)
std::min(a,b)<1.e-7
On ne peut pas tester directement l’égalité de deux nombres réels en
programmation, car ils ne sont définis qu’avec une certaine précision: 7
chiffres après la virgule pour les float
.
On va donc plutôt tester si l’écart entre a
et
b
est inférieur à cette précision, relativement à la valeur
de a
ou de b
.
Dans la parenthèse suivant for
, on trouve les éléments
suivants:
Dans la parenthèse suivant for
, on trouve les éléments
suivants:
Que fait le code ci-dessus ?
Que fait le code ci-dessus ?
Attention au piège de l’indentation. Il n’y a pas d’accolades après
le for
, donc seule l’instruction k++
est
effectuée dans la boucle.
int nStars = 0;
for (int nStars=0; nStars<20; nStars++)
std::cout << "*";
std::cout << std::endl << "Number of stars "
<< nStars << std::endl;
Pourquoi cette partie de programme me dit-elle qu’aucune étoile n’a été affichée ?
nStars
.
for
.
int nStars = 0;
for (int nStars=0; nStars<20; nStars++)
std::cout << "*";
std::cout << std::endl << "Number of stars "
<< nStars << std::endl;
Pourquoi cette partie de programme me dit-elle qu’aucune étoile n’a été affichée ?
nStars
.
for
.
Le bloc d’initialisation du for
contient la déclaration
d’une variable. Même si une variable avec le même nom existait déjà,
c’est une nouvelle variable qui sert pendant la boucle. Cette nouvelle
variable est détruite à la sortie du bloc. L’ancienne est restée
inchangée.
L’instruction suivante:
Les std::vector
sont des tableaux unidimensionnels.
Quand deux arguments sont donnés à l’initialisation, la première indique
la taille du tableau, et la seconde la valeur à laquelle les éléments
sont initialisés.
Qu’affiche l’opération suivante ?
std::vector<int> vec = {1,2,3,4,5,6};
int prod = 1;
for (unsigned int i=0; i<vec.size(); i++) {
prod *= vec[i];
std::cout << prod << " ";
}
std::cout << std::endl;
1 2 6 24 120 720
1 2 3 4 5 6
1 2 6 12 72 864
La valeur de prod
est mise à jour à chaque passage dans
la boucle, en faisant prod = prod*vec[i]
. Au final, le code
affiche les produits des \(v_k\) pour
\(0<k<n-1\), pour tous les \(n<6\).
On peut déclarer une fonction à n’importe quel endroit du code.
On peut déclarer une fonction à n’importe quel endroit du code.
On ne peut déclarer et définir des fonctions telles qu’on les a
vues qu’en dehors de toute autre fonction. Il faut cependant qu’une
fonction soit au moins déclarée avant tout appel.
Lorsque j’appelle la fonction prodscal
avec
prodscal(a,b)
, avec pour prototype
a
est copié
b
est copié
Lorsqu’on passe un argument par référence (avec le symbole
&
après le type de l’argument), seule l’adresse de la
variable en argument est transmise à la fonction, ce qui permet de
modifier directement sa valeur, mais aussi d’éviter de la recopier, ce
qui est utile quand elle représente une grande quantité de données. Ici,
les deux vecteurs sont passés par référence, donc aucun ne sera
copié.
Je veux écrire une fonction qui utilise les \(n\) premiers éléments d’un grand vecteur pour écrire un fichier. Le prototype de la fonction sera:
void (std::vector<int> v, int n);
void (std::vector<int>& v, int n);
std::vector<int> (std::vector<int> v, int n);
std::vector<int> (std::vector<int>& v, int n);
Je veux écrire une fonction qui utilise les \(n\) premiers éléments d’un grand vecteur pour écrire un fichier. Le prototype de la fonction sera:
void (std::vector<int> v, int n);
void (std::vector<int>& v, int n);
std::vector<int> (std::vector<int> v, int n);
std::vector<int> (std::vector<int>& v, int n);
Cette fonction écrit un fichier, elle ne retourne rien au reste du
programme. Donc son type de retour, placé au début du prototype, est
void
. Ensuite, j’ai précisé que le vecteur est grand, donc
il vaut mieux le passer par référence, avec le symbole “&” après le
type. Cela évite la recopie des arguments qui est effectuée à chaque
appel de la fonction.