Feuille de triche C++
Apprenez le C++ avec des Labs Pratiques
Apprenez la programmation C++ grâce à des laboratoires pratiques et des scénarios réels. LabEx propose des cours C++ complets couvrant la syntaxe essentielle, la programmation orientée objet, les conteneurs STL, la gestion de la mémoire et les techniques avancées. Maîtrisez les fonctionnalités puissantes de C++ pour construire des applications haute performance et des logiciels système.
Syntaxe et Structure de Base
Programme Hello World
Structure de base d’un programme C++.
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
En-têtes et Espaces de Noms
Inclure des bibliothèques et gérer les espaces de noms.
#include <iostream> // Flux d'entrée/sortie
#include <vector> // Tableaux dynamiques
#include <string> // Classe string
#include <algorithm> // Algorithmes STL
using namespace std;
// Ou spécifier individuellement :
// using std::cout;
// using std::cin;
Commentaires
Commentaires sur une seule ligne et sur plusieurs lignes.
// Commentaire sur une seule ligne
/*
Commentaire
sur plusieurs lignes
*/
// TODO: Implémenter la fonctionnalité
/* FIXME: Bug dans cette section */
Fonction Main
Point d’entrée du programme avec valeurs de retour.
int main() {
// Code du programme ici
return 0; // Succès
}
int main(int argc, char* argv[]) {
// argc : nombre d'arguments
// argv : valeurs des arguments (ligne de commande)
return 0;
}
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Sortie de Base
Afficher du texte et des variables sur la console.
cout << "Hello" << endl;
cout << "Valeur: " << 42 << endl;
// Plusieurs valeurs sur une seule ligne
cout << "Nom: " << name << ", Âge: " << age << endl;
Entrée de Base
Lire l’entrée utilisateur depuis la console.
int age;
string name;
cin >> age;
cin >> name;
// Lire la ligne entière avec espaces
getline(cin, name);
Types de Données et Variables
Types Primitifs
Types de données de base pour stocker différents types de valeurs.
// Types entiers
int age = 25;
short small_num = 100;
long large_num = 1000000L;
long long huge_num = 9223372036854775807LL;
// Types à virgule flottante
float price = 19.99f;
double precise = 3.14159265359;
// Caractère et booléen
char grade = 'A';
bool is_valid = true;
Chaînes de Caractères et Tableaux
Types de données pour le texte et les collections.
// Chaînes de caractères
string name = "John Doe";
string empty_str;
// Tableaux
int numbers[5] = {1, 2, 3, 4, 5};
int matrix[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
// Tableaux dynamiques (vecteurs)
vector<int> dynamic_array = {10, 20, 30};
vector<string> names(5); // Taille 5, chaînes vides
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
vector par rapport aux tableaux réguliers en C++ ?Constantes et Auto
Valeurs immuables et déduction automatique de type.
// Constantes
const int MAX_SIZE = 100;
const double PI = 3.14159;
// Mot-clé Auto (C++11+)
auto x = 42; // int
auto y = 3.14; // double
auto name = "John"; // const char*
// Alias de type
typedef unsigned int uint;
using real = double;
Structures de Flux de Contrôle
Instructions Conditionnelles
Prendre des décisions basées sur des conditions.
// Instruction If-else
if (age >= 18) {
cout << "Adulte" << endl;
} else if (age >= 13) {
cout << "Adolescent" << endl;
} else {
cout << "Enfant" << endl;
}
// Opérateur ternaire
string status = (age >= 18) ? "Adulte" : "Mineur";
// Instruction Switch
switch (grade) {
case 'A':
cout << "Excellent !" << endl;
break;
case 'B':
cout << "Bon travail !" << endl;
break;
default:
cout << "Continuez d'essayer !" << endl;
}
Boucles For
Itérer avec des boucles basées sur un compteur.
// Boucle for traditionnelle
for (int i = 0; i < 10; i++) {
cout << i << " ";
}
// Boucle for basée sur la plage (C++11+)
vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
cout << num << " ";
}
// Auto avec boucle basée sur la plage
for (auto& item : container) {
// Traiter l'élément
}
Connectez-vous pour répondre à ce quiz et suivre votre progression d'apprentissage
Boucles While
Itération basée sur une condition.
// Boucle While
int count = 0;
while (count < 5) {
cout << count << endl;
count++;
}
// Boucle Do-while (s'exécute au moins une fois)
int input;
do {
cout << "Entrez un nombre (0 pour quitter) : ";
cin >> input;
} while (input != 0);
Contrôle de Boucle
Instructions break et continue.
for (int i = 0; i < 10; i++) {
if (i == 3) {
continue; // Sauter l'itération
}
if (i == 7) {
break; // Sortir de la boucle
}
cout << i << " ";
}
// Boucles imbriquées avec break étiqueté
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == j) break; // Sortir uniquement de la boucle interne
cout << i << "," << j << " ";
}
}
Fonctions
Déclaration et Définition de Fonction
Créer des blocs de code réutilisables.
// Déclaration de fonction (prototype)
int add(int a, int b);
void printMessage(string msg);
// Définition de fonction
int add(int a, int b) {
return a + b;
}
void printMessage(string msg) {
cout << msg << endl;
}
// Appel de fonction
int result = add(5, 3);
printMessage("Hello, functions!");
Surcharge de Fonction
Plusieurs fonctions avec le même nom.
// Types de paramètres différents
int multiply(int a, int b) {
return a * b;
}
double multiply(double a, double b) {
return a * b;
}
// Nombre différent de paramètres
int multiply(int a, int b, int c) {
return a * b * c;
}
Paramètres par Défaut
Fournir des valeurs par défaut pour les paramètres de fonction.
void greet(string name, string greeting = "Hello") {
cout << greeting << ", " << name << "!" << endl;
}
// Appels de fonction
greet("Alice"); // Utilise le défaut "Hello"
greet("Bob", "Good morning"); // Utilise un salut personnalisé
Passage par Référence
Modifier des variables via les paramètres de fonction.
// Passage par valeur (copie)
void changeValue(int x) {
x = 100; // Variable originale inchangée
}
// Passage par référence
void changeReference(int& x) {
x = 100; // Variable originale modifiée
}
// Référence constante (lecture seule, efficace)
void processLargeData(const vector<int>& data) {
// Peut lire les données mais pas les modifier
}
Programmation Orientée Objet
Définition de Classe
Définir des types de données personnalisés avec des attributs et des méthodes.
class Rectangle {
private:
double width, height;
public:
// Constructeur
Rectangle(double w, double h) : width(w), height(h) {}
// Constructeur par défaut
Rectangle() : width(0), height(0) {}
// Fonctions membres
double area() const {
return width * height;
}
void setDimensions(double w, double h) {
width = w;
height = h;
}
// Fonctions getter
double getWidth() const { return width; }
double getHeight() const { return height; }
};
Création et Utilisation d’Objets
Instancier et utiliser des objets de classe.
// Créer des objets
Rectangle rect1(5.0, 3.0);
Rectangle rect2; // Constructeur par défaut
// Utiliser les fonctions membres
cout << "Aire: " << rect1.area() << endl;
rect2.setDimensions(4.0, 2.0);
// Allocation dynamique
Rectangle* rect3 = new Rectangle(6.0, 4.0);
cout << rect3->area() << endl;
delete rect3; // Nettoyer la mémoire
Héritage
Créer des classes spécialisées à partir de classes de base.
class Shape {
protected:
string color;
public:
Shape(string c) : color(c) {}
virtual double area() const = 0; // Virtuel pur
string getColor() const { return color; }
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r, string c) : Shape(c), radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
};
Polymorphisme
Utiliser des pointeurs de classe de base pour accéder à des objets dérivés.
// Fonctions virtuelles et polymorphisme
vector<Shape*> shapes;
shapes.push_back(new Circle(5.0, "rouge"));
shapes.push_back(new Rectangle(4.0, 6.0));
for (Shape* shape : shapes) {
cout << "Aire: " << shape->area() << endl;
// Appelle la méthode de la classe dérivée appropriée
}
Gestion de la Mémoire
Allocation Mémoire Dynamique
Allouer et désallouer la mémoire à l’exécution.
// Objet unique
int* ptr = new int(42);
cout << *ptr << endl;
delete ptr;
ptr = nullptr;
// Allocation de tableau
int* arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i * i;
}
delete[] arr;
// Vérifier l'échec de l'allocation
int* large_array = new(nothrow) int[1000000];
if (large_array == nullptr) {
cout << "Échec de l'allocation !" << endl;
}
Pointeur Intelligents (C++11+)
Gestion automatique de la mémoire avec RAII.
#include <memory>
// unique_ptr (propriété exclusive)
unique_ptr<int> ptr1 = make_unique<int>(42);
unique_ptr<int> ptr2 = move(ptr1); // Transférer la propriété
// shared_ptr (propriété partagée)
shared_ptr<int> sptr1 = make_shared<int>(100);
shared_ptr<int> sptr2 = sptr1; // Partager la propriété
cout << sptr1.use_count() << endl; // Compte de références
Références vs Pointeurs
Deux façons d’accéder indirectement aux objets.
int x = 10;
// Référence (alias)
int& ref = x; // Doit être initialisée
ref = 20; // Change x à 20
// Pointeur
int* ptr = &x; // Pointeur vers l'adresse de x
*ptr = 30; // Déréférencement et changement de x
ptr = nullptr; // Peut pointer vers rien
// Variations Const
const int* ptr1 = &x; // Ne peut pas changer la valeur
int* const ptr2 = &x; // Ne peut pas changer l'adresse
const int* const ptr3 = &x; // Ne peut changer ni l'un ni l'autre
Pile vs Tas (Stack vs Heap)
Stratégies d’allocation mémoire.
// Allocation sur la pile (automatique)
int stack_var = 42;
int stack_array[100];
// Allocation sur le tas (dynamique)
int* heap_var = new int(42);
int* heap_array = new int[100];
// Objets sur la pile nettoyés automatiquement
// Objets sur le tas doivent être supprimés manuellement
delete heap_var;
delete[] heap_array;
Bibliothèque Standard (STL)
Conteneurs : Vector et String
Tableaux dynamiques et manipulation de chaînes.
#include <vector>
#include <string>
// Opérations sur les vecteurs
vector<int> nums = {1, 2, 3};
nums.push_back(4); // Ajouter un élément
nums.pop_back(); // Supprimer le dernier
nums.insert(nums.begin() + 1, 10); // Insérer à la position
nums.erase(nums.begin()); // Supprimer le premier
// Opérations sur les chaînes
string text = "Hello";
text += " World"; // Concaténation
text.append("!"); // Ajouter à la fin
cout << text.substr(0, 5) << endl; // Sous-chaîne
text.replace(6, 5, "C++"); // Remplacer "World" par "C++"
Conteneurs : Map et Set
Conteneurs associatifs pour les paires clé-valeur et les éléments uniques.
#include <map>
#include <set>
// Map (paires clé-valeur)
map<string, int> ages;
ages["Alice"] = 25;
ages["Bob"] = 30;
ages.insert({"Charlie", 35});
// Set (éléments uniques)
set<int> unique_nums = {3, 1, 4, 1, 5, 9};
unique_nums.insert(2);
unique_nums.erase(1);
// Automatiquement trié : {2, 3, 4, 5, 9}
Algorithmes
Algorithmes STL pour les opérations courantes.
#include <algorithm>
vector<int> nums = {64, 34, 25, 12, 22, 11, 90};
// Tri
sort(nums.begin(), nums.end());
sort(nums.rbegin(), nums.rend()); // Tri inverse
// Recherche
auto it = find(nums.begin(), nums.end(), 25);
if (it != nums.end()) {
cout << "Trouvé à la position: " << it - nums.begin();
}
// Autres algorithmes utiles
reverse(nums.begin(), nums.end());
int max_val = *max_element(nums.begin(), nums.end());
int count = count_if(nums.begin(), nums.end(),
[](int x) { return x > 50; });
Itérateurs
Naviguer efficacement dans les conteneurs.
vector<string> words = {"hello", "world", "cpp"};
// Types d'itérateurs
vector<string>::iterator it;
auto it2 = words.begin(); // Auto C++11
// Itérer sur le conteneur
for (it = words.begin(); it != words.end(); ++it) {
cout << *it << " ";
}
// Boucle basée sur la plage (préférée)
for (const auto& word : words) {
cout << word << " ";
}
Opérations d’Entrée/Sortie
Entrée Fichier : Lecture de Fichiers
Lire des données à partir de fichiers texte.
#include <fstream>
#include <sstream>
// Lire le fichier entier
ifstream file("data.txt");
if (file.is_open()) {
string line;
while (getline(file, line)) {
cout << line << endl;
}
file.close();
}
// Lire mot par mot
ifstream file2("numbers.txt");
int number;
while (file2 >> number) {
cout << number << " ";
}
// Lecture avec vérification d'erreurs
if (!file.good()) {
cerr << "Erreur de lecture de fichier !" << endl;
}
Traitement de Flux de Chaînes
Analyser et manipuler des chaînes comme des flux.
#include <sstream>
// Analyser des valeurs séparées par des virgules
string data = "apple,banana,cherry";
stringstream ss(data);
string item;
vector<string> fruits;
while (getline(ss, item, ',')) {
fruits.push_back(item);
}
// Convertir des chaînes en nombres
string num_str = "123";
int num = stoi(num_str);
double d = stod("3.14159");
string back_to_str = to_string(num);
Sortie Fichier : Écriture de Fichiers
Écrire des données dans des fichiers texte.
// Écrire dans un fichier
ofstream outfile("output.txt");
if (outfile.is_open()) {
outfile << "Hello, file!" << endl;
outfile << "Nombre: " << 42 << endl;
outfile.close();
}
// Ajouter à un fichier existant
ofstream appendfile("log.txt", ios::app);
appendfile << "Nouvelle entrée de journal" << endl;
// Écrire un vecteur dans un fichier
vector<int> numbers = {1, 2, 3, 4, 5};
ofstream numfile("numbers.txt");
for (int num : numbers) {
numfile << num << " ";
}
Formatage de Flux
Contrôler le format et la précision de la sortie.
#include <iomanip>
double pi = 3.14159265;
cout << fixed << setprecision(2) << pi << endl; // 3.14
cout << setw(10) << "Right" << endl; // Alignement à droite
cout << left << setw(10) << "Left" << endl; // Alignement à gauche
cout << hex << 255 << endl; // Hexadécimal: ff
Gestion des Erreurs
Blocs Try-Catch
Gérer les exceptions qui peuvent survenir pendant l’exécution.
try {
int result = 10 / 0; // Ceci pourrait lancer une exception
vector<int> vec(5);
vec.at(10) = 100; // Accès hors limites
} catch (const exception& e) {
cout << "Exception attrapée : " << e.what() << endl;
} catch (...) {
cout << "Exception inconnue attrapée !" << endl;
}
// Types d'exceptions spécifiques
try {
string str = "abc";
int num = stoi(str); // Lance invalid_argument
} catch (const invalid_argument& e) {
cout << "Argument invalide : " << e.what() << endl;
} catch (const out_of_range& e) {
cout << "Hors limites : " << e.what() << endl;
}
Lancer des Exceptions Personnalisées
Créer et lancer vos propres exceptions.
// Classe d'exception personnalisée
class CustomException : public exception {
string message;
public:
CustomException(const string& msg) : message(msg) {}
const char* what() const noexcept override {
return message.c_str();
}
};
// Fonction qui lance une exception
void validateAge(int age) {
if (age < 0 || age > 150) {
throw CustomException("Plage d'âge invalide !");
}
}
// Utilisation
try {
validateAge(-5);
} catch (const CustomException& e) {
cout << e.what() << endl;
}
Modèle RAII
Acquisition de Ressource Est Initialisation pour une gestion sûre des ressources.
// RAII avec pointeurs intelligents
{
unique_ptr<int[]> arr = make_unique<int[]>(1000);
// Le tableau est automatiquement supprimé lorsqu'il sort du scope
}
// RAII avec gestion de fichiers
{
ifstream file("data.txt");
// Le fichier est automatiquement fermé lorsqu'il sort du scope
if (file.is_open()) {
// Traiter le fichier
}
}
// Classe RAII personnalisée
class FileHandler {
FILE* file;
public:
FileHandler(const char* filename) {
file = fopen(filename, "r");
}
~FileHandler() {
if (file) fclose(file);
}
FILE* get() { return file; }
};
Assertions et Débogage
Déboguer et valider les hypothèses du programme.
#include <cassert>
#include <iostream>
void processArray(int* arr, int size) {
assert(arr != nullptr); // Assertion de débogage
assert(size > 0); // Valide l'hypothèse
// Traiter le tableau...
}
// Compilation conditionnelle pour la sortie de débogage
#ifdef DEBUG
#define DBG_PRINT(x) cout << "DEBUG: " << x << endl
#else
#define DBG_PRINT(x)
#endif
// Utilisation
DBG_PRINT("Démarrage de la fonction");
Compilation et Processus de Construction
Compilation GCC/G++
Collection de compilateurs GNU pour C++.
# Compilation de base
g++ -o programme main.cpp
# Avec informations de débogage
g++ -g -o programme main.cpp
# Niveaux d'optimisation
g++ -O2 -o programme main.cpp
# Fichiers sources multiples
g++ -o programme main.cpp utils.cpp math.cpp
# Inclure des répertoires supplémentaires
g++ -I/usr/local/include -o programme main.cpp
# Lier des bibliothèques
g++ -o programme main.cpp -lm -lpthread
Normes C++ Modernes
Compiler avec des versions standard C++ spécifiques.
# Standard C++11
g++ -std=c++11 -o programme main.cpp
# Standard C++14
g++ -std=c++14 -o programme main.cpp
# Standard C++17 (recommandé)
g++ -std=c++17 -o programme main.cpp
# Standard C++20 (le plus récent)
g++ -std=c++20 -o programme main.cpp
# Activer tous les avertissements
g++ -Wall -Wextra -std=c++17 -o programme main.cpp
Bases de Makefile
Automatiser la compilation avec l’utilitaire make.
# Makefile simple
CXX = g++
CXXFLAGS = -std=c++17 -Wall -g
TARGET = programme
SOURCES = main.cpp utils.cpp
$(TARGET): $(SOURCES)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(SOURCES)
clean:
rm -f $(TARGET)
.PHONY: clean
Bonnes Pratiques et Conseils
Conventions de Nommage
Un nommage cohérent rend le code plus lisible.
// Variables et fonctions : snake_case ou camelCase
int student_count;
int studentCount;
void calculateAverage();
// Constantes : UPPER_CASE
const int MAX_BUFFER_SIZE = 1024;
const double PI = 3.14159;
// Classes : PascalCase
class StudentRecord {
// Variables membres : préfixe avec m_ ou suffixe _
string m_name;
int age_;
public:
// Interface publique
void setName(const string& name);
string getName() const;
};
Sécurité Mémoire
Prévenir les bogues courants liés à la mémoire.
// Utiliser des pointeurs intelligents au lieu de pointeurs bruts
auto ptr = make_unique<int>(42);
auto shared = make_shared<vector<int>>(10);
// Initialiser les variables
int count = 0; // Bien
int count; // Dangereux - non initialisé
// Boucles basées sur la plage sont plus sûres
for (const auto& item : container) {
// Traiter l'élément en toute sécurité
}
// Vérifier la validité du pointeur
if (ptr != nullptr) {
// Sûr à déréférencer
}
Conseils de Performance
Écrire du code C++ efficace.
// Passer les objets volumineux par référence constante
void processData(const vector<int>& data) {
// Éviter de copier de gros objets
}
// Utiliser le pré-incrément pour les itérateurs
for (auto it = vec.begin(); it != vec.end(); ++it) {
// ++it est souvent plus rapide que it++
}
// Réserver la capacité du vecteur lorsque la taille est connue
vector<int> numbers;
numbers.reserve(1000); // Éviter les réallocations
// Utiliser emplace au lieu de push pour les objets
vector<string> words;
words.emplace_back("Hello"); // Construire sur place
words.push_back(string("World")); // Construire puis copier
Organisation du Code
Structurer le code pour la maintenabilité.
// Fichier d'en-tête (utils.h)
#ifndef UTILS_H
#define UTILS_H
class MathUtils {
public:
static double calculateArea(double radius);
static int fibonacci(int n);
};
#endif // UTILS_H
// Fichier d'implémentation (utils.cpp)
#include "utils.h"
#include <cmath>
double MathUtils::calculateArea(double radius) {
return M_PI * radius * radius;
}
// Utiliser des fonctions membres const lorsque c'est possible
double getRadius() const { return radius; }