owned this note
owned this note
Published
Linked with GitHub
---
tags: Enseignement, Info 111
---
# Foire Aux Questions, Amphi Info 111, Semaine 5
Ceci est un document partagé. Vous pouvez tous l'éditer!
## Consignes
- Mettez à jour régulièrement le sondage pour indique où vous en êtes.
- Mettez à jour régulièrement votre statut (bouton en bas de l'écran à gauche du micro) pour indiquer comment cela se passe pour vous.
- Vous pouvez poser vos questions ici en amont de l'amphi, au fur et à mesure où vous consultez les documents
- Avant de poser une question, vérifier si la réponse n'est pas disponible ci-dessous.
- Lorsque «ça ne marche pas» donner des détails (messages d'erreurs, ...) pour que je puisse analyser le problème.
- Si la question est courte, vous pouvez la poser directement dans le chat.
- Si la question est longue, l'écrire ci-dessous avec votre nom, et si nécessaire me mettre une notification dans le chat.
- Vous pouvez aussi poser des questions à l'oral.
## Consignes
### Que doit-on faire? Dans quel ordre?
> Doit-on faire les TD et les TP?
Travaillez sur les [documents de la Semaine 5](http://nicolas.thiery.name/Enseignement/Info111/Web/Semaine5/).
Vous pouvez par exemple suivre l'ordre que j'ai indiqué dans le sondage. Mais il n'est pas imposé. Notamment si vous avez des soucis techniques, vous pouvez vous concentrer sur ce qui se fait sur papier (Cours, TD).
### Rédaction
> pour l'ecriture des programmes sur feuille, pour les partiels, vous acceptez qu'on mette une } sur une meme ligne que du code par exemple ? parce que sinon mes petits programmes prennent une page à être écrits
Il vaut mieux éviter, cela nuit à la lisibilité.
En revanche, vous pouvez ne pas mettre les accolades chaque fois qu'un bloc d'instruction contient une seule instruction
## JupyterHub
> Je n'arrive pas à me connecter sur https://jupytercloud.lal.in2p3.fr/jupyter/hub/home
>
> Service d'authentification - Demande non supportée
Il semblerait que l'authentification via votre compte Paris-Saclay soit en panne aujourd'hui; je ne savais même pas qu'elle fonctionnait tout court :-)
Assurez-vous de vous connecter via votre compte Paris-Sud, comme indiqué dans les instructions.
Si vous travailliez précédement avec votre compte Paris-Saclay: votre dossier personnel ne sera pas le même. Si vous avez bien déposé (submit) votre travail au fur et à mesure, ce n'est pas un problème; il suffit de télécharger à nouveau votre travail (fetch).
## GitLab / soumission
> Bonjour Monsieur, nous sommes plusieurs à ne pas pouvoir faire de submit sur Jupyter
Merci pour l'alerte. Je viens d'avoir le problème aussi. Je l'ai signalé aux administrateurs, cela devrait être réglé rapidement. Connectez vous plus tard dans la journée pour faire le submit.
Mise à jour 12h59: problème corrigé.
> Cela signifie que je peux me déconnecter sans faire le submit ?
Oui, tout à fait; votre dossier personnel persiste d'une fois sur l'autre tant que vous vous connectez avec les mêmes identifiants. Mais assurez vous de faire le submit avant de travailler ailleurs (par exemple en salle de TP).
## int, long, ...
> qu'est ce que cela veux dire ?
> type: unsigned long
C'est un type similaire à `int` pour stocker des entiers
- unsigned: sans signe: on ne peut mettre que des entiers positifs
- long: cela permet de stocker des entiers plus grands que int
## Compilation
### Ouvrir un éditeur de texte
> nous devons ouvrir un editeur de texte dans la feuille des programmes compilés, pouvez vous m'indiquer comment faire svp ?
Sur JupyterHub:
Depuis le navitateur de fichier: si le fichier existe, cliquez simplement dessus. Sinon utiliser le menu `New` -> `Text File`. Puis ajustez le nom du fichier dans la barre de titre (par défaut il est appelé quelque chose comme `untitledX.txt`).
<!--Cela tombe bien, j'ai écrit des instructions hier et j'ai besoin de relectures 🙂
Consultez: nicolas.thiery.name/Enseignement/Info111/devoirs.html
et dites-moi si cela réponds à la question.
!-->
### Pourquoi compiler?
> ça sert à quoi les programmes compilés?
Comme indiqué dans le cours, «pour écrire des programmes plus gros il est souhaitable de s'affranchir de Jupyter et de passer à des programmes compilés.»
Tu souhaiterais en savoir plus sur pourquoi c'est souhaitable?
> oui c'est ça parce que je vois pas pourquoi on ne peut pas faire des programmes plus gros sans avoir besoin de programmes compilés
Pour des programmes avec plus de quelques fonctions, cela devient vite la pagaille dans une feuille Jupyter: on perd vite le fil de ce qui a été exécuté, dans quel ordre.
Ce n'est aussi pas facile de partager du code entre plusieurs feuilles Jupyter: rappelez vous les copier-coller des fonctions puissance et factorielle d'une feuille à l'autre la semaine dernière.
En outre, les éditeurs de texte, voire les environnements de développement intégrés offrent des outils pour naviguer rapidement dans du code.
Enfin, un programme compilé fonctionne tel quel. C'est pratique pour l'utilisateur final de pouvoir l'utiliser sans avoir à installer Jupyter au préalable.
## Tableaux
### Tableaux vs listes
> Est ce qu'une liste c'est comme un vecteur ?
Les listes Python sont en effet similaires au `vector` de C++. On va utiliser le terme générique de tableau pour les deux.
À noter que dans de nombreux langages, le terme «liste» est utilisé comme racourci pour «liste chaînée». Ces dernières ont un rôle similaire de conteneur, mais une implantation différente et notamment pas d'accès indexé `t[i]` efficace.
### Construction des tableaux
> si on fait une allocation d'un tableau :
```
t = vector<int>(5);
```
> puis on met `t[0] = 2;`, les autres indices auront pour valeur 0, c'est bien ca ?
Les autres valeurs comme `t[1]`, ... ne seront pas initialisés; leurs valeurs seront donc quelconques. Certaines implantation de C++ peuvent garantir une initialisation à `0`, mais **il ne faut pas compter dessus**.
## Taille des vecteurs
> comment l'ordinateur connait d'avance la taille du vecteur ?
Il ne la connait pas à l'avance. La taille est donnée lors de la construction du vecteur; c'est le rôle de l'allocation:
v = vector<int>(4)
> Est-ce que l'on peut changer la taille avec:
>
> noms.size()=4
Ce serait une syntaxe assez naturelle, notamment dans un langage comme Python. Mais non cette syntaxe n'est pas valide en C++. Il y a une méthode `resize`, mais nous n'en aurons pas besoin dans ce cours. Nous nous contenterons de `push_back` qui permets de rajouter un élément à la fin (ce qui incrémente la taille au passage).
### Tableaux et fonctions
> je ne trouve pas dans le cours comment definir une fonction avec le type vector ?
En effet: il n'y a rien dans le cours à ce sujet car il n'y a rien à dire de particulier: `vector<...>` est un type comme un autre. Donc il peut être utilisé comme les autres types (int, ...) pour donner le type de l'entrée et de la sortie.
> donc je mets `vector<int> mafonction(vector<int> t)` par exemple ?
Exactement.
### Affichage de tableau
> est-ce possible d'afficher un vector avec cout ?
La bibliothèque standard de C++ ne fournit pas cette fonctionnalité, parce que tout le monde à ses propres préférences pour afficher un tableau: avec des espaces, des virgules, etc. Il est possible de la rajouter soi-même en fonction de ses préférences.
### Qu'entendez vous par «source no1 des trous de sécurité»?
Source des failles de sécurité qui sont exploitées par les attaquants pour contourner les sécurités des systèmes. Nous verrons un exemple «jouet» en amphi la semaine prochaine.
## Fonctions
> dans une fonction avec un entier en entrée, est ce qu'on doit traiter le cas ou un entier n'est pas rentré dans la fonction ?
Si une fonction déclare qu'elle prend, par exemple, un entier en argument, alors C++ rejettera tout appel à cette fonction sans entier. Autrement dit, la fonction est assurée d'avoir un entier en paramètre lorsqu'elle est appelée.
## Nouvelles questions
### Question 1, exercice 3
> je ne comprends pas pourquoi j'ai l'erreur control reaches end of non-void function [-Werror,-Wreturn-type] avec ce programme;
```cpp
bool positif(vector<int> t2) {
bool resultat;
for (int i = 0; i < t2.size(); i++){
if ( t2[i] > 0){
resultat = true;
}
else { resultat = false;
}
}
resultat;
}
```
Il manque le `return` à la fin de la fonction.
## «Spécifier» une fonction
> Dans la question 1 de l'exercice 3, on nous demande de spécifier la fonction. Est-ce que cela veut dire écrire une javadoc comme nous avons vu en cours ?
Spécifier, c'est décrire ce que fait la fonction: entrées, sorties, ... C'est une bonne approche de le faire sous forme de documentation comme tu le proposes:
> Comme cela ? Doit-on préciser le type de ce qui est retourné ou simplement l'élément ?
```cpp
/* Retourne vrai si tous les éléments sont positifs
* @param list La liste des éléments
* @return bool true ssi tous les éléments sont positifs
*/
bool isEverythingPositive(vector<int> list)
{
for (int item : list)
if (item < 0)
return false;
return true;
}
```
Si le type est évident comme ici, vous pouvez le passer sous silence. Voici les deux variantes:
```
* @return true si ...
* @return un booléen: true si ...
```
### Afficher un vecteur
> Peut-on afficher un vector avec cout ?
La bibliothèque standard de C++ ne fournit pas cette fonctionnalité (parce que tout le monde à ses propres préférences pour afficher un tableau: avec des espaces, des virgules, etc) .
### Fonctions type tableau
> Dans le TP et TD, on demande de créer une fonction qui incrémente un tableau de 1 et retourne le tableau. Mais lorsque je le fais, ils me disent "function definition is not allowed here".
Voici mon code :
```cpp
vector<int> incremente(vector<int> t) {
for (int i = 0; i < t.size(); i++) {
t[i] = t[i] + 1;
}
return t;
}
```
Il y a hélas une limitation arbitraire dans Jupyter: une fonction doit être toute seule dans sa cellule.
> Donc cela signifie qu'une fonction de type vector<...> est en réalité composée de 2 fonctions ?
Ah zut, tu tappes ici dans un autre bug. Ton code est du C++ tout à fait correct, mais Jupyter/cling n'aime pas `vector<...>` comme type de retour. Voir le [contournement proposé dans la feuille de TP](http://nicolas.thiery.name/Enseignement/Info111/Web/Semaine5/tableaux-fonctions.html#Fonction-incremente).
### TD Exercice 1
> Pouvez vous m'indiquer pour l'exercice 1 la valeur de v[0] et de v[1] afin que je vois si j'ai bien compris comment exécuter le programme
`v[i]` contiendra $i^2$. Par exemple, `v[2]` contiendra $4$.
### TD Exercice 3 Question 2
> j'ai une erreur de définition de ma fonction à la fin de la 1ere ligne au niveau du '{'
```cpp
vector<int> incremente(vector<int> t) {
for ( int i = 0; i < t.size(); i++ )
t[i] += 1;
return t;
}
```
Oui tu as le même problème que moi.
Enfaite, tu dois exécuter avant ton code:
`typedef vector<int> tableau;`
Et ensuite tu remplace `vector<int>` devant "incremente" par "tableau".
En fait non c'est bon je l'ai executé dans une cellule différente et ça a marché J'avais typedef dans le même que ma fonction incremente c'est sans doute pour ça
### TD Exercice 4 question 5
> Qu'est-ce que vous entendez par fonction la plus expressive ? Est-ce la plus simple à comprendre ?
> Une implémentation qui contient beaucoup d'affectations de variables ?
> Est-ce possible que ça soit la plus longue ?
Non, une implémentation qui exprime le mieux l'intention du programmeur.
Idéalement, le lecteur la parcourt en diagonale et voit immédiatement qu'est-ce que cela fait, voire comment.
Souvent, ce sera plutôt l'implantation la plus concise.
> D'accord donc vous vous attendez à ce qu'on dise que c'est la fonction récursive ?
> Parce que celle que j'ai faite est effectivement plus courte que les autres mais je pense qu'il y a besoin de plus réfléchir pour la comprendre que pour celle avec les vecteurs (notamment la condition d'arrêt qui est n <= 2 pour moi).
Oui, ce sera en effet l'opinion du mathématicien qui a en tête la définition récursive de la suite de Fibonacci.
Tu notes que l'on entre vite dans le domaine du subjectif: il s'agit d'être au plus près de ce qui se passe dans le cerveau du lecteur. Mais nous avons tous des cerveaux un peu différents 🙂
### TD Exercice 4 question 6
> On nous demande de mesurer les performances des fonctions. La semaine précédente nous avons utilisé ``timeit`` sur Jupyter. Cette semaine j'ai compilé le C++, timeit est-il disponible dans la stdlib ? Si oui comment l'utiliser ?
Ici on vous demande une étude théorique.
> J'ai un peu de mal à répondre à la question du coup. J'aurais tendance à dire que la version reposant sur une liste ou sur la pile (la fonction récursive) vont avoir une grosse consommation de mémoire. Les calculs étant en plus repoussés à la fin pour la fonction récursive. Celle avec les trois variables sera probablement plus efficace.
Bonne intuition. Tu peux raffiner cela en évaluant la *complexité* de tes algos: quantité de mémoire et nombre d'opérations requises.
Après, ça peut être sympa de vérifier dans la pratique: https://xeus-cling.readthedocs.io/en/latest/magics.html
```cpp
int f(int i) {
return i+1;
}
```
%timeit f(3);
2.42 ns +- 0.043 ns per loop (mean +- std. dev. of 7 runs 100000000 loops each)
> J'ai une erreur en essayant de créer ma feuille Jupyter. J'ai choisis C++ 17, est-ce que c'est compatible ?
![](https://i.imgur.com/izPVxTq.png)
C'est ce que j'ai utilisé aussi. Je ne vois rien de choquant dans le code. Tu as essayé de redémarer le noyau au cas où l'interpréteur se soit mal remis d'une erreur?
> ça semble fonctionner en redémarrant ! Je vais tester les fonctions tout de suite
> je ne comprends pas : la fonction récursive C est presque aussi rapide que la B et la fonction A qui utilise les vecteurs est clairement dernière.
Voici les benchmarks pour ~~factorielle~~ fibonacci(100) :
```md
# Fonction A (vectors)
886 ns +- 13.4 ns per loop (mean +- std. dev. of 7 runs 1000000 loops each)
# Fonction B (variables)
267 ns +- 3.11 ns per loop (mean +- std. dev. of 7 runs 1000000 loops each)
# Fonction C (récursive)
309 ns +- 18.3 ns per loop (mean +- std. dev. of 7 runs 1000000 loops each)
```
Pour n = 100 000
```md
# Fonction A (vectors)
782 us +- 9.16 us per loop (mean +- std. dev. of 7 runs 1000 loops each)
# Fonction B (variables)
265 us +- 3.79 us per loop (mean +- std. dev. of 7 runs 1000 loops each)
# Fonction C (récursive)
427 us +- 14 us per loop (mean +- std. dev. of 7 runs 1000 loops each)
```
> Je mets ici les fonctions que j'ai faites pour que mes résultats aient un sens :
```cpp
/** Suite de Fibonacci
* @param n un entier strictement positif
* @return le n-i`eme terme de la suite de Fibonacci
**/
int fibonacciA(int n) {
vector<int> vec = vector<int>(n);
vec[0] = 1;
vec[1] = 1;
for (int i = 2; i < n; i++)
vec[i] = vec[i-1] + vec[i-2];
return vec[n-1];
}
int fibonacciB(int n) {
int a = 1;
int b = 1;
int c;
for (int i = 2; i < n; i++) {
c = b;
b = a + c;
a = c;
}
return b;
}
int fibonacciC(int n, int a=1, int b=1) {
return (n <= 2) ? b : fibonacciC(n-1, b, a+b);
}
```
### Exercice Morse
Comment puis-je faire pour "décomposer" une chaine de cararctère en tableau de type char ?
Mon code actuellement :
```cpp
string morseString(string texte) {
vector<char> t = texte;
for (int i = 0; i < t.size(); i++) {
cout << morseCaractere(t[i]);
}
}
```
Tu peux directement faire `texte[i]` pour accéder au i-ème caractère. Pour accéder à la taille de la chaîne de caractère, c'est, de mémoire, indiqué dans le cours ou le sujet de TP; quelque chose comme `length` plutôt que `size`.
Si string se comporte comme un tableau, alors ce code devrait marcher :
```cpp
string morseString(string texte) {
for (int i = 0; i < texte.size(); i++) {
cout << morseCaractere(texte[i]);
}
}
```
> Or, il y a une liste gigantesque d'erreur lorsque je l'exécute
Quelques sources possibles:
- Y-a-t'il bien le:
using namespace std;
> ah oui je viens de rajouter <iostream>
Ok!
À noter aussi: de mémoire, pour les chaînes de caractères ce n'est pas `size` mais `length`.
>> Je ne saurais pas vous dire.
En revanche, j'ai toujours une erreur de type "non void" à mon avis car il n'y a pas de return explicite.
Mais il y a un cout
Ah oui je comprend. Donc si je remplace string par void cela devrait marcher
Que doit faire la fonction? Renvoyer une chaine de caractères? Ou l'afficher? Là, elle annonce l'autre et fait l'un :-)
Ok donc ce code renvoie bien la bonne traduction en morse mais ne passe pas les tests car ce n'est pas une chaine de caractere
```cpp
void morseString(string texte) {
for (int i = 0; i < texte.length(); i++) {
cout << morseCaractere(texte[i]);
}
}
```
Si ta fonction affiche le résultat plutôt que de le renvoyer, c'est difficile pour les tests de récupérer le résultat pour le vérifier! Il faudrait qu'ils lisent l'écran à ta place.
> Et ce n'est pas possible ?
Si, mais c'est compliqué.
Alors que tu peux faire simple.
> Ok je vais essayer.
Rejette un oeil au cours sur "fonction qui agit" versus "fonction qui calcule"
J'ai réussi, enfaite je ne savais comment "concatener" en C++
Cela me donne :
string morseString(string texte) {
string morse;
for (int i = 0; i < texte.length(); i++) {
morse = morse + morseCaractere(texte[i]);
}
return morse;
}