Guillaume Belz

Apprendre le C++ en utilisant les IA de modèle de langage (ChatGPT, Bard, etc)

Mise à jour 8 juin 2024 : utilisation de ChatGPT 4

Une question qui revient de régulièrement ces derniers temps est de savoir si on peut apprendre en utilisant les modéles de langages, du type chatGPT ou Bard. Dans le cas qui va nous intéresser ici, la programmation en C++.

Pour rappel, un modèle de langage est une forme d’intelligence artificielle (plus précisement du traitement automatique du langage naturel) qui cherche a prédire la suite de mots la plus probable, à partir d’une conversation. On parle de chatbot ou d’agent conversationnel.

L’idée est de discuter avec ces chatbot pour leur demander d’expliquer les concepts qu’on veut apprendre, proposer des exercices, des solutions à ces exercices, etc. L’utiliser en quelque sorte comme un professeur particulier, expert dans tous les domaines.

Je ne vais pas aller plus dans les détails de ce type d’outil, il existe pleins de ressources pour cela. Je vous conseille en particulier les vidéos de MrPhi sur le sujet.

Pour aider les débutants a mieux utiliser les chatbots pour apprendre le C++, je vais demander a un chatbot (ChatGPT 4) de générer des exercices pour le cours de C++ de Zeste de Savoir (le cours en version beta, que vous trouverez ici) et je vais commenter les solutions proposées, de façon à expliquer les bonnes pratiques du C++ moderne et vous donner des mots-clés permettant d’améliorer votre apprentissage avec des chatbots.

Apprendre le C++ avec un chatbot ?

Pour commencer, je vais vous montrer un problème général des chatbot pour l’apprentissage (pas uniquement le C++ et la programmation). Demandons a Bard de donner un cours de C++ pour débutant :

Écris un plan détaillé d’un cours d’introduction à la syntaxe de base du C++

#include et int main()
(...)
V. Tableaux et chaînes de caractères
(...)
VI. Introduction aux pointeurs

A mon sens, le problème de cette approche est similaire à celui rencontré dans l’auto-apprentissage en général : comment un débutant dans un domaine peut-il faire le tri dans les informations qu’il reçoit ?

En informatique, il existe souvent plusieurs façons de faire quelque chose et cela demande souvent un niveau d’expertise avancé pour savoir faire le tri entre les différentes pratiques. Et comme il n’est pas possible d’être expert en tout, et donc que chaque développeur puisse faire le tri lui même entre les pratiques, on utilise souvent des “guides de bonnes pratiques. C’est-à-dire un ensemble de pratiques qui sont validées et recommandées par les communautés d’experts. En C++ par exemple, il existe les C++ Core Guidelines.

En plus, il faut ajouter un problème plus spécifique au C++ (et plus généralement aux langages de programmation anciens) : les pratiques ont évolué au cours du temps. Les raisons de ces changements sont multiples, mais pour simplifier, c’est simplement parce que l’univers de l’informatique a évolué : les ordinateurs modernes et les applications logicielles n’ont rien à voir avec ce qui existait il y a 20 ans. La structure des équipes de développement, les exigences de qualité logiciel, la complexité des programmes, tout a changé radicalement.

Le problème est que l’on continue de trouver sur internet des codes et pratiques d’une autre époque ou spécifiques d’un domaine particulier. Pour le débutant qui apprend, il est impossible de faire le tri entre toutes les informations qu’il reçoit, savoir si c’est des pratiques obsolètes ou dangereuse (en termes de qualité logicielle) ou non recommandées dans le monde professionel.

La programmation impérative en C++

Écris des exercices et les solutions correspondantes en C++ pour apprendre a écrire des programmes simples du type hello world

Exercice 1 : Écrivez un programme C++ qui affiche le message “Hello World” dans le terminal.

Pour écrire un programme C++ qui affiche le message “Hello World” dans le terminal, vous pouvez suivre ces étapes simples: Créez un fichier avec l’extension .cpp, par exemple hello_world.cpp.

Ouvrez ce fichier dans un éditeur de texte et écrivez le code suivant:

#include <iostream>

int main() {
    std::cout << "Hello World";
    return 0;
}

Enregistrez le fichier et compilez-le à l’aide d’un compilateur C++, comme g++:

g++ hello_world.cpp -o hello_world

Exécutez le programme compilé dans le terminal:

./hello_world

Ce programme commence par inclure la bibliothèque qui permet d'utiliser std::cout pour afficher des messages dans le terminal. La fonction main() est le point d'entrée du programme. À l'intérieur de cette fonction, std::cout << "Hello World"; affiche le message "Hello World" dans le terminal. Enfin, return 0; indique que le programme s'est terminé avec succès. Pour plus d'informations sur la création de votre premier programme en C++, vous pouvez consulter les ressources suivantes:

  • Programme Hello World en C++ avec explication du code - Guru99
  • Écrivez votre premier programme - Apprenez à programmer en C++
  • Bonjour tout le monde ! Exemple : votre premier programme - Guru99

Dès ce premier code simple, on peut déjà faire des remarques sur le code produit. Pour commencer, quelle est la version du C++ utilisée ? Dans la dernière version du C++ (le C++23), le code serait :

import std;

int main() {
  println("Hello World!");
  return 0;
}

L’utilisation des modules et du mot clé import est récent et il arrivera souvent que les chatbots proposent des codes qui ne sont pas à jour ou ne suivent pas les bonnes pratiques.

On peut également critiquer le manque de retour à la ligne, mais c’est accessoire. Les liens donnés sont des vieux tutoriels, que je ne recommenderais pas de suivre.

Et lorsque l’on demande des explications sur ce code, les explications ne sont pas forcément satisfaisantes :

La ligne avec #include en programmation C est utilisée pour inclure le contenu d’un fichier dans un autre. Cette directive est facile à reconnaître car elle commence toujours par le symbole #. Lorsque vous utilisez #include avec des guillemets, le préprocesseur recherche d’abord le fichier dans le même répertoire que le fichier qui contient l’instruction #include, puis dans les répertoires des fichiers inclus actuellement ouverts, dans l’ordre inverse dans lequel ils ont été ouverts. Pour ouvrir un fichier .h en programmation C, vous devez inclure la bibliothèque correspondante à ce fichier en utilisant la directive #include. Par exemple, pour inclure le fichier exemple.h, vous devez ajouter la ligne suivante en début de votre code : #include "exemple.h".

D’abord, on remarque que la réponse indique spécifiquement le C et pas le C++. Ici, ce n’est pas grave, mais ChatGPT peut faire la confusion (comme certains développeurs en fait, ChatGPT ne fait que reproduire les erreurs qu’il voit sur internet) en le C et le C++.

Plus problématique, cette réponse expliquer l’utilisation de include avec des guillemets, mais pas avec des chevrons, comme c’est le cas dans le code. Ca peut être perturbant pour les débutants et le perdre dans des détails inutile à ce niveau.

Et surtout, il manque l’explication sur ce qu’est la bibliothèque standard, ce qui est justement un des points les plus importants dans cet exercice “hello world”.

Dans un cours écrit par un expert, l’auteur peut établir un plan pédagogique, choisir les points qu’il lui semble important à mettre en avant et les détails qui seront détaillés plus tard dans le cours. Dans le cas de l’apprentissage avec ChatGPT, c’est le hasard des questions de celui qui apprend qui va orienter les points détaillés, pas forcément la cohérence pédagogique.

À noter quand même un point positif : ChatGPT 3 ne donnait que le code de l’exercice, avec peu d’explication et sans les lignes de commandes pour compiler ce programme. Donc un conseil : utilisez ChatGPT 4.

Les littérals et les variables

Exercices sur le chapitre Une super mémoire

Écris des exercices et leur solution en C++ pour apprendre a manipuler différents types de littérales

Bien sûr! Voici quelques exercices et leurs solutions en C++ pour vous aider à manipuler différents types de littérales:

Exercice 1: Écrivez un programme en C++ qui demande à l’utilisateur de saisir deux nombres entiers et affiche leur somme.

#include <iostream>
using namespace std;

int main() {
    int num1, num2, sum;
    
    cout << "Entrez le premier nombre: ";
    cin >> num1;
    
    cout << "Entrez le deuxième nombre: ";
    cin >> num2;
    
    sum = num1 + num2;
    
    cout << "La somme est: " << sum << endl;
    
    return 0;
}

Exercice 2: Écrivez un programme en C++ qui demande à l’utilisateur de saisir un nombre réel et affiche sa racine carrée.

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    double num, squareRoot;
    
    cout << "Entrez un nombre réel: ";
    cin >> num;
    
    squareRoot = sqrt(num);
    
    cout << "La racine carrée est: " << squareRoot << endl;
    
    return 0;
}

Exercice 3: Écrivez un programme en C++ qui demande à l’utilisateur de saisir un caractère et affiche son code ASCII.

#include <iostream>
using namespace std;

int main() {
    char ch;
    
    cout << "Entrez un caractère: ";
    cin >> ch;
    
    cout << "Le code ASCII de " << ch << " est: " << int(ch) << endl;
    
    return 0;
}

J’espère que ces exercices vous aideront à vous familiariser avec la manipulation des différents types de littérales en C++. N’hésitez pas à me demander si vous avez d’autres questions!

Là, ChatGPT est complètement hors sujet. Ces exercices n’abordent pas les littérales.

Écris des exercices et leur solution pour pratiquer les variables en C++

Voici quelques exercices sur les variables en C++ avec leurs solutions pour vous aider à pratiquer et à mieux comprendre leur utilisation :

Exercice 1 : Échange de Variables

Énoncé : Écrire un programme qui demande à l’utilisateur de saisir deux entiers A et B, échange le contenu des variables A et B, puis affiche A et B.

Solution :

#include <iostream>
using namespace std;

int main() {
    int A, B, temp;
    cout << "Entrez la valeur de A : ";
    cin >> A;
    cout << "Entrez la valeur de B : ";
    cin >> B;
    
    // Échange des valeurs
    temp = A;
    A = B;
    B = temp;
    
    cout << "Après échange, A = " << A << " et B = " << B << endl;
    return 0;
}

Il y a beaucoup plus de choses à dire sur les exercices proposés ici par ChatGPT, je vais détailler pour chaque exercice.

Pour commencer, cette pratique de déclarer les variables en début de fonction date du début du C. Cela était une obligation du langage. C’est une obligation qui n’existe plus depuis plusieurs dizaines d’années et une pratique qui est déconseillée en C++. On va préférer déclarer les variables quand on en a besoin.

Une autre pratique hérité du C est l’absence du mot clé const. temp est une variable qui n’est plus modifiée après son initialisation. En C++, on préfère écrire par exemple :

const int temp = A;

Sans entrer dans les détails, il existe d’autres styles d’écriture, par exemple :

const auto temp { A };

Mais ce type de problématiques sur le style est sujet à de longues discussions. C’est quelque chose que l’on peut aborder avec un débutant, mais il faut éviter de le perdre dans des détails et débats peu pertinents pour son apprentissage. Je pense que le mieux est que l’auteur d’un cours fasse des choix (peu importe lequels au final, tant qu’ils ont du sens) et soit cohérent. ChatGPT n’aura pas cette cohérence et pourra utiliser des styles différents dans chaque solution, ce qui peut être problématique pour l’apprentissage.

Un autre point, dans les recommandations actuelles, on évite de déclarer plusieurs variables sur un ligne.

Exercice 2 : Addition de Deux Nombres

Énoncé : Utilisez les variables pour calculer la somme de deux nombres. Solution :

#include <iostream>
using namespace std;

int main() {
    int a = 5, b = 8, resultat;
    resultat = a + b;
    cout << "La somme de a et b est : " << resultat << endl;
    return 0;
}

Comment détermine-t-on qu’un code est correct ?

Dans les solutions à ces deux premiers exercices, on voit un manque de cohérence dans les réponses de ChatGPT. Dans le premier cas, on demandait des valeurs de tests à l’utilisateur en utilisant l’instruction std::cin. Dans le second cas, on utise des valeurs écritent directement dans le code. Quelle est la “bonne” façon de savoir quand un code est correct ?

Ce type de question est justement un bon moyen d’introduire la question du la qualité logicielle et des tests. Certains sites de programmation vérifient les codes via des tests, en particulier sur les cas limites. Encore une fois, c’est pas une erreur de ChatGPT, il ne fait que reproduire ce qu’on voit dans beaucoup de (mauvais, à mon avis) tutotiels. Mais justement, ChatGPT ne peut pas avoir l’idée d’aborder de lui même ce type de concepts et c’est pas le débutant qui peut penser à demander cela.

Exercice 3 : Utilisation de Variables pour Dessiner

Énoncé : Définissez une variable et utilisez-la pour dessiner un rectangle et deux ellipses. À quelle abscisse x les ellipses sont-elles dessinées ?

Solution : Cet exercice est plus conceptuel et vise à comprendre comment les variables peuvent être utilisées pour contrôler les positions des formes dans un environnement graphique. La solution dépendra de l’environnement de programmation graphique que vous utilisez (par exemple, SFML, SDL, etc.).

Bon, un exercice sur une interface graphique. Pourquoi pas, cela peut être un exercice intéressant. Mais pas pour un débutant qui découvre les variables. Encore une fois, ChatGPT ne peut pas avoir de cohérence pédagogique, comme dans un vrai cours.

Exercice 4 : Affichage et Adresse de Variables

Énoncé : Écrire un programme C++ qui déclare un entier a, une référence vers cet entier ref_a, et un pointeur vers cet entier p_a, puis affiche les variables, leurs adresses, et la valeur pointée.

Solution :

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int& ref_a = a;
    int* p_a = &a;
    
    cout << "Valeur de a : " << a << endl;
    cout << "Adresse de a : " << &a << endl;
    cout << "Valeur de ref_a : " << ref_a << endl;
    cout << "Adresse de ref_a : " << &ref_a << endl;
    cout << "Valeur pointée par p_a : " << *p_a << endl;
    cout << "Adresse stockée dans p_a : " << p_a << endl;
    return 0;
}

Ces exercices couvrent différents aspects de l’utilisation des variables en C++, de la manipulation basique à des concepts plus avancés comme les références et les pointeurs. Pratiquez-les pour renforcer votre compréhension des variables en C++.

Un autre exemple de problème de cohérence et de progression dans ce que propose ChatGPT. Et encore une fois, ce n’est pas réellement de sa faute, il ne fait que reproduire ce qu’il a appris sur internet. On voit régulièrement ce type de code pour montrer les pointeurs et références. Ce qui n’a aucun sens ! Dans un vrai code, on ne ferait jamais cela. C’est un code d’exemple pour illustrer ces deux concepts, mais dans un contexte qui n’a aucun sens. Pédagogiquement, c’est très discutable.

Dans mon cours C++ par exemple, je présentais les références dans la partie sur les fonctions, pour le passage d’arguments. Et les pointeurs (intelligents) dans la partie programmation objet, pour la création dynamique d’objets polymorphiques.

Conclusion

Je ne vais pas aller plus loin pour l’instant dans les exemples d’exercices et de solutions. Les critiques principales sont :

Il me semble très difficile pour une débutant d’apprendre avec ChatGPT, seul. À la rigueur, en suivant un cours et en étant encadré. Mais la majorité des débutants perdront plus de temps à se perdre dans les mauvais codes proposés par ChatGPT.