Remédiation en C++

Auto-évaluation

Université de Bordeaux – Licence Ingénierie Mathématique

Question 1

C++ est un langage

• compilé
 
• interprété

 

Réponse 1

C++ est un langage

• compilé
 
• interprété

C++ nécessite de transformer les fichiers sources qui contiennent le code C++ en un fichier exécutable, ce qui s’appelle la compilation.

Question 2

L’option pour que le compilateur m’avertisse de potentielles erreurs est

• -g
 
• -Wall
 
• -warnings

 

Réponse 2

L’option pour que le compilateur m’avertisse de potentielles erreurs est

• -g
 
• -Wall
 
• -warnings

L’option -g est pour le debug. Pour les avertissements, je vous rappelle qu’il est dangereux de les ignorer !

Question 3

Je suis capable de lire un fichier exécutable

• bien sûr !
 
• pas vraiment

 

Réponse 3

Je suis capable de lire un fichier exécutable

• bien sûr !
 
• pas vraiment

Les fichiers exécutables contiennent des instructions en binaire qui ne sont pas lisibles par les humains.

Question 4

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 ?

• Une variable n’est pas initialisée
 
• Il manque un point-virgule

• Le compilateur ne sait pas ce qu’est un double


Réponse 4

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 ?

• Une variable n’est pas initialisée
 
• Il manque un point-virgule

• Le compilateur ne sait pas ce qu’est un double


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.

Question 5

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 ?

• std::string
 
• int
 
• double

Quel type de variable puis-je utiliser pour calculer le résultat à une minute près avant l’affichage ?

• std::string
 
• int
 
• double


Réponse 5

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 ?

• std::string
 
• int
 
• double

Quel type de variable puis-je utiliser pour calculer le résultat à une minute près avant l’affichage ?

• std::string
 
• int
 
• double


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.

Question 6

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 mal déclaré les variables
 
• La division est entière
 
• Je ne peux afficher que des entiers


Réponse 6

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 mal déclaré les variables
 
• La division est entière
 
• Je ne peux afficher que des entiers

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!

Question 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


Réponse 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.

Question 8

Dans la parenthèse suivant for, on trouve les éléments suivants:

(incrémentation ; condition ; initialisation)

(initialisation ; condition ; indentation)

(initialisation ; condition ; incrémentation)

(initialisation ; incrémentation ; condition)


Réponse 8

Dans la parenthèse suivant for, on trouve les éléments suivants:

(incrémentation ; condition ; initialisation)

(initialisation ; condition ; indentation)

(initialisation ; condition ; incrémentation)

(initialisation ; incrémentation ; condition)


Question 9

int k=0;
for (int i=0;i*i*<1000;i++)
  k++;
  std::cout << k << std::endl;

Que fait le code ci-dessus ?

Affiche le carré des nombres entiers inférieurs à 1000.

Affiche les entiers dont le carré est inférieur à 1000

Affiche le nombre d’entiers dont le carré est inférieur à 1000


Réponse 9

int k=0;
for (int i=0;i*i*<1000;i++)
  k++;
  std::cout << k << std::endl;

Que fait le code ci-dessus ?

Affiche le carré des nombres entiers inférieurs à 1000.

Affiche les entiers dont le carré est inférieur à 1000

Affiche le nombre d’entiers dont le carré est inférieur à 1000


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.

Question 10

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 ?

Il y a deux variables nStars.
 
La variable incrémentée revient à son état initial à la sortie du for.

Il n’y a que de l’affichage qui est fait, rien n’est modifié.


 

Réponse 10

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 ?

Il y a deux variables nStars.
 
La variable incrémentée revient à son état initial à la sortie du for.

Il n’y a que de l’affichage qui est fait, rien n’est modifié.

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.

Question 11

L’instruction suivante:

std::vector<int> vec(10,2);
…initialise un vecteur de 2 entiers qui valent 10.

…initialise un vecteur de 10 entiers qui valent 2.

…initialise un tableau d’entiers de dimensions 10 et 2.


Réponse 11

L’instruction suivante:

std::vector<int> vec(10,2);
…initialise un vecteur de 2 entiers qui valent 10.

…initialise un vecteur de 10 entiers qui valent 2.

…initialise un tableau d’entiers de dimensions 10 et 2.


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.

Question 12

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


Réponse 12

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\).

Question 13

On peut déclarer une fonction à n’importe quel endroit du code.

Vrai
 
Faux


Réponse 13

On peut déclarer une fonction à n’importe quel endroit du code.

Vrai
 
Faux


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.

Question 14

Lorsque j’appelle la fonction prodscal avec prodscal(a,b), avec pour prototype

double prodScal(std::vector<double>& u, std::vector<double>& v);
le vecteur a est copié

le vecteur b est copié

aucun vecteur n’est copié

les deux vecteurs sont copiés


Réponse 14

Lorsque j’appelle la fonction prodscal avec prodscal(a,b), avec pour prototype

double prodScal(std::vector<double>& u, std::vector<double>& v);
le vecteur a est copié

le vecteur b est copié

aucun vecteur n’est copié

les deux vecteurs sont copiés


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é.

Question 15

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);


Réponse 15

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.

Retour au cours Moodle