Fonction récursive en C : Exercices Corrigés
Recommandés
Installer un environnement C (en 10 minutes) vous permet de disposer rapidement de tous les outils essentiels pour compiler, tester et exécuter vos premiers programmes _- sujets d’exercices sur les Fonction récursive en C : Exercices Corrigés –– en toute autonomie, afin de passer immédiatement de la théorie à la pratique sans blocage technique.⬇️
Récursion en C pour débutants guide pratique et exercices corrigés
La programmation récursive est une technique où une fonction s’appelle elle-même pour résoudre un problème. Cette approche est particulièrement utile pour les problèmes qui peuvent être décomposés en sous-problèmes similaires. En langage C, la récursivité est un concept puissant mais doit être utilisé avec précaution pour éviter les erreurs telles que les débordements de pile.
Structure d’une fonction récursive
Pour qu’une fonction récursive soit correctement implémentée, elle doit comporter deux éléments clés :
- Cas de base : une condition qui met fin à la récursivité.
- Appel récursif : la fonction s’appelle elle-même avec des arguments modifiés, rapprochant ainsi la solution du cas de base.
Exemple de base : Factorielle
La fonction factorielle d’un nombre ( n ) (notée ( n! )) est un exemple classique de récursion. Voici comment on peut l’implémenter en C :
#include <stdio.h>
int factorielle(int n) {
if (n <= 1) {
return 1;
} else {
return n * factorielle(n - 1);
}
}
int main() {
int nombre = 5;
printf("La factorielle de %d est %d\n", nombre, factorielle(nombre));
return 0;
}Exercices Corrigés en langage C : Fonction récursive
Voici une série de 16 exercices corrigés pour approfondir la compréhension des fonctions récursives en C.
Exercice 1 : Somme des entiers de 1 à n
Énoncé : Écrire une fonction récursive qui calcule la somme des entiers de 1 à ( n ).
Correction :
#include <stdio.h>
int somme(int n) {
if (n == 1) {
return 1;
} else {
return n + somme(n - 1);
}
}
int main() {
int nombre = 10;
printf("La somme des entiers de 1 à %d est %d\n", nombre, somme(nombre));
return 0;
}Exercice 2 : Série de Fibonacci
Énoncé : Écrire une fonction récursive pour générer le ( n )-ième terme de la série de Fibonacci.
Correction :
#include <stdio.h>
int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
int main() {
int terme = 6;
printf("Le %d-ième terme de la série de Fibonacci est %d\n", terme, fibonacci(terme));
return 0;
}Exercice 3 : Calcul de la puissance
Énoncé : Écrire une fonction récursive pour calculer ( x ) élevé à la puissance ( y ) ( ( x^y ) ).
Correction :
#include <stdio.h>
int puissance(int x, int y) {
if (y == 0) {
return 1;
} else {
return x * puissance(x, y - 1);
}
}
int main() {
int base = 2, exposant = 3;
printf("%d à la puissance %d est %d\n", base, exposant, puissance(base, exposant));
return 0;
}Exercice 4 : Inverser une chaîne de caractères
Énoncé : Écrire une fonction récursive pour inverser une chaîne de caractères.
Correction :
#include <stdio.h>
#include <string.h>
void inverser(char *str, int debut, int fin) {
if (debut >= fin) {
return;
}
char temp = str[debut];
str[debut] = str[fin];
str[fin] = temp;
inverser(str, debut + 1, fin - 1);
}
int main() {
char chaine[] = "recursion";
inverser(chaine, 0, strlen(chaine) - 1);
printf("Chaîne inversée : %s\n", chaine);
return 0;
}Exercice 5 : Nombre de chiffres
Énoncé : Écrire une fonction récursive pour compter le nombre de chiffres d’un entier.
Correction :
#include <stdio.h>
int compte_chiffres(int n) {
if (n == 0) {
return 0;
} else {
return 1 + compte_chiffres(n / 10);
}
}
int main() {
int nombre = 12345;
printf("Le nombre de chiffres dans %d est %d\n", nombre, compte_chiffres(nombre));
return 0;
}Exercice 6 : Somme des chiffres
Énoncé : Écrire une fonction récursive pour calculer la somme des chiffres d’un entier.
Correction :
#include <stdio.h>
int somme_chiffres(int n) {
if (n == 0) {
return 0;
} else {
return (n % 10) + somme_chiffres(n / 10);
}
}
int main() {
int nombre = 12345;
printf("La somme des chiffres de %d est %d\n", nombre, somme_chiffres(nombre));
return 0;
}Exercice 7 : Recherche d’un élément dans un tableau
Énoncé : Écrire une fonction récursive pour rechercher un élément dans un tableau.
Correction :
#include <stdio.h>
int recherche(int arr[], int taille, int element) {
if (taille == 0) {
return -1;
} else if (arr[taille - 1] == element) {
return taille - 1;
} else {
return recherche(arr, taille - 1, element);
}
}
int main() {
int tableau[] = {2, 4, 6, 8, 10};
int taille = sizeof(tableau) / sizeof(tableau[0]);
int element = 6;
int index = recherche(tableau, taille, element);
if (index != -1) {
printf("Élément %d trouvé à l'index %d\n", element, index);
} else {
printf("Élément %d non trouvé\n", element);
}
return 0;
}Exercice 8 : Calcul de la somme des éléments d’un tableau
Énoncé : Écrire une fonction récursive pour calculer la somme des éléments d’un tableau.
Correction :
#include <stdio.h>
int somme_tableau(int arr[], int taille) {
if (taille == 0) {
return 0;
} else {
return arr[taille - 1] + somme_tableau(arr, taille - 1);
}
}
int main() {
int tableau[] = {2, 4, 6, 8, 10};
int taille = sizeof(tableau) / sizeof(tableau[0]);
printf("La somme des éléments du tableau est %d\n", somme_tableau(tableau, taille));
return 0;
}Exercice 9 : Trouver le maximum dans un tableau
Énoncé : Écrire une fonction récursive pour trouver le maximum dans un tableau.
Correction :
#include <stdio.h>
int maximum(int arr[], int taille) {
if (taille == 1) {
return arr[0];
} else {
int max = maximum(arr, taille - 1);
return (arr[taille - 1] > max) ? arr[taille - 1] : max;
}
}
int main() {
int tableau[] = {2, 4, 6, 8, 10};
int taille = sizeof(tableau) / sizeof(tableau[0]);
printf("Le maximum du tableau est %d\n", maximum(tableau, taille));
return 0;
}Exercice 10 : Tri à bulle récursif
Énoncé : Écrire une fonction récursive pour trier un tableau en utilisant le tri à bulle.
Correction :
#include <stdio.h>
void echanger(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void tri_bulle(int arr[], int taille) {
if (taille == 1) {
return;
}
for (int i = 0; i < taille - 1; i++) {
if (arr[i] > arr[i + 1]) {
echanger(&arr[i], &arr[i + 1]);
}
}
tri_bulle(arr, taille - 1);
}
int main() {
int tableau[] = {10, 9, 8, 7, 6};
int taille = sizeof(tableau) / sizeof(tableau[0]);
tri_bulle(tableau, taille);
printf("Tableau trié : ");
for (int i = 0; i < taille; i++) {
printf("%d ", tableau[i]);
}
printf("\n");
return 0;
}Exercice 11 : Convertir un entier en binaire
Énoncé : Écrire une fonction récursive pour convertir un entier en binaire.
Correction :
#include <stdio.h>
void convertir_binaire(int n) {
if (n == 0) {
return;
}
convertir_binaire(n / 2);
printf("%d", n % 2);
}
int main() {
int nombre = 10;
printf("Le binaire de %d est ", nombre);
convertir_binaire(nombre);
printf("\n");
return 0;
}Exercice 12 : Calcul de la moyenne des éléments d’un tableau
Énoncé : Écrire une fonction récursive pour calculer la moyenne des éléments d’un tableau.
Correction :
#include <stdio.h>
float somme_elements(float arr[], int taille) {
if (taille == 0) {
return 0;
} else {
return arr[taille - 1] + somme_elements(arr, taille - 1);
}
}
float moyenne(float arr[], int taille) {
return somme_elements(arr, taille) / taille;
}
int main() {
float tableau[] = {2.0, 4.0, 6.0, 8.0, 10.0};
int taille = sizeof(tableau) / sizeof(tableau[0]);
printf("La moyenne des éléments du tableau est %.2f\n", moyenne(tableau, taille));
return 0;
}Exercice 13 : Trouver le nombre d’occurrences d’un élément dans un tableau
Énoncé : Écrire une fonction récursive pour trouver le nombre d’occurrences d’un élément dans un tableau.
Correction :
#include <stdio.h>
int occurrences(int arr[], int taille, int element) {
if (taille == 0) {
return 0;
} else {
int count = (arr[taille - 1] == element) ? 1 : 0;
return count + occurrences(arr, taille - 1, element);
}
}
int main() {
int tableau[] = {2, 4, 6, 8, 4, 10};
int taille = sizeof(tableau) / sizeof(tableau[0]);
int element = 4;
printf("Le nombre d'occurrences de %d est %d\n", element, occurrences(tableau, taille, element));
return 0;
}Exercice 14 : Trouver la somme des éléments pairs d’un tableau
Énoncé : Écrire une fonction récursive pour trouver la somme des éléments pairs d’un tableau.
Correction :
#include <stdio.h>
int somme_pairs(int arr[], int taille) {
if (taille == 0) {
return 0;
} else {
int sum = (arr[taille - 1] % 2 == 0) ? arr[taille - 1] : 0;
return sum + somme_pairs(arr, taille - 1);
}
}
int main() {
int tableau[] = {2, 4, 6, 8, 10};
int taille = sizeof(tableau) / sizeof(tableau[0]);
printf("La somme des éléments pairs du tableau est %d\n", somme_pairs(tableau, taille));
return 0;
}Exercice 15 : Trouver la profondeur maximale d’un arbre binaire
Énoncé : Écrire une fonction récursive pour trouver la profondeur maximale d’un arbre binaire.
Correction :
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* left;
struct Node* right;
};
int profondeur_max(struct Node* node) {
if (node == NULL) {
return 0;
} else {
int left_depth = profondeur_max(node->left);
int right_depth = profondeur_max(node->right);
return (left_depth > right_depth) ? (left_depth + 1) : (right_depth + 1);
}
}
struct Node* nouveauNoeud(int data) {
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
int main() {
struct Node* root = nouveauNoeud(1);
root->left = nouveauNoeud(2);
root->right = nouveauNoeud(3);
root->left->left = nouveauNoeud(4);
root->left->right = nouveauNoeud(5);
printf("La profondeur maximale de l'arbre binaire est %d\n", profondeur_max(root));
return 0;
}Exercice 16 : Vérifier si une chaîne est un palindrome
Énoncé : Écrire une fonction récursive pour vérifier si une chaîne est un palindrome.
Correction :
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool est_palindrome(char *str, int debut, int fin) {
if (debut >= fin) {
return true;
}
if (str[debut] != str[fin]) {
return false;
}
return est_palindrome(str, debut + 1, fin - 1);
}
int main() {
char chaine[] = "radar";
if (est_palindrome(chaine, 0, strlen(chaine) - 1)) {
printf("%s est un palindrome\n", chaine);
} else {
printf("%s n'est pas un palindrome\n", chaine);
}
return 0;
}Les fonctions récursives offrent une méthode élégante et efficace pour résoudre divers problèmes de programmation. Bien que la récursion puisse être plus intuitive pour certains problèmes, il est important de comprendre ses limitations, notamment en termes de consommation de mémoire et de temps d’exécution. Les exercices corrigés ci-dessus devraient fournir une base solide pour approfondir la maîtrise de la récursion en C.
Encadré Méthode – Guide rapide pour comprendre la récursion en C
Cet encadré est un outil d’aide visuelle conçu pour les développeurs débutants qui souhaitent maîtriser la récursion en C sans se perdre dans des explications trop théoriques.
Il agit comme une mini-feuille de route intégrée directement dans la page, toujours visible et consultable pendant que l’on code.
À quoi sert cet encadré ?
Son utilité principale est de transformer un concept souvent abstrait en étapes concrètes et applicables immédiatement.
Au lieu de relire tout un chapitre ou de chercher ailleurs, l’utilisateur dispose d’un repère clair et synthétique qui lui rappelle :
- où s’arrête la fonction récursive
- comment réduire progressivement le problème
- quelle structure de code utiliser
- quels pièges éviter
- quoi vérifier avant de valider son programme
C’est à la fois un mémo, un guide de méthode, et un outil de sécurisation du raisonnement.
Pourquoi il est utile pour un dev junior
Pour un débutant, la récursion peut sembler déroutante. Cet encadré :
- évite la confusion entre boucle et récursion
- réduit le risque de récursion infinie
- structure la réflexion avant même d’écrire le code
- favorise l’autonomie sans dépendre constamment d’un tutoriel externe
- renforce la confiance lors du débogage
En pratique, il sert de check-list intelligente que l’on consulte rapidement avant d’exécuter son programme.
Ce que l’utilisateur y gagne
- Gain de temps : plus besoin de chercher la méthode ailleurs
- Clarté : une vision globale en quelques secondes
- Sécurité : moins d’erreurs logiques
- Progression rapide : compréhension accélérée du mécanisme récursif
- Mémoire visuelle : le design type terminal aide à retenir la structure
Il s’agit d’un outil pédagogique actif qui accompagne l’utilisateur pendant l’apprentissage, l’écriture et la vérification du code.
Il transforme une notion complexe en processus simple, visuel et répétable, exactement ce dont un développeur junior a besoin pour passer de la théorie à la pratique avec assurance.
🧠 Méthode rapide pour coder une fonction récursive en C
Objectif : écrire une récursion qui termine, qui réduit le problème à chaque appel, et qui reste lisible au débogage.
1️⃣ Définis la règle d’arrêt
- Écris la condition qui stoppe les appels (cas de base).
- Décide la valeur retournée dans ce cas (souvent 0, 1, ou un état “neutre”).
- Teste mentalement 2 cas simples : n=0 et n=1.
2️⃣ Réduction du problème
- Choisis une transformation qui rapproche du cas de base : n → n-1, p → p/10, liste → liste->next…
- Assure-toi que la transformation ne peut pas “rester bloquée”.
- Écris la relation : f(n) = … f(n-1) …
3️⃣ Schéma universel de récursion
Tu peux partir de ce gabarit et remplacer les éléments en gras.
// f : résout le problème pour "state"
int f(int state) {
// (A) cas de base : STOP
if (/* condition d'arrêt */) {
return /* valeur de base */;
}
// (B) réduction : state -> smaller_state
int smaller_state = /* transformation */;
// (C) appel récursif
int sub = f(smaller_state);
// (D) combinaison : reconstruire la réponse
return /* combine(state, sub) */;
}4️⃣ Debug comme un hacker
- Ajoute un log minimal : printf(« n=%d\n », n);
- Indentation dynamique : afficher des espaces selon la profondeur.
- Stoppe sur un cas précis : si n == 7 alors print + return.
// mini trace de profondeur
int f(int n, int depth){
for(int i=0;i n=%d\n", n);
if(n<=1) return 1;
return n * f(n-1, depth+1);
} 5️⃣ Pièges classiques
- Confondre pré-traitement et post-traitement (avant/après l’appel).
- Oublier les cas négatifs (ex : n < 0).
- Explosion de complexité (ex : Fibonacci naïf) → memoization ou itération.
- Stack overflow si la profondeur peut être énorme → version itérative.
Mini checklist avant validation
- Cas de base existe et couvre tous les scénarios limites
- À chaque appel, le problème se réduit vraiment
- La valeur retournée est correcte dans le cas de base
- La combinaison reconstruit la réponse finale
- Tests rapides : petit input, input limite, input “bizarre”
Installer un environnement C (en 10 minutes)
Choisis ton système. Chaque option ci-dessous te donne un compilateur + (optionnel) un éditeur pour coder proprement.
Objectif : pouvoir lancer gcc ou cl et compiler ton premier hello.c.
- Option A (recommandée) : GCC via MSYS2 (rapide + moderne).
- Option B : Visual Studio Community (MSVC, très standard pro).
// Test rapide (après install)
// 1) Vérifie le compilateur
gcc --version
// 2) Compile
gcc hello.c -o hello
// 3) Exécute
./hello- Installe d’abord les Command Line Tools (compilo + outils).
- Optionnel : installe Homebrew pour gérer gcc/clang et outils.
// Command Line Tools (terminal)
xcode-select --install
// Vérifie
clang --version- Sur Ubuntu/Debian : installe build-essential (gcc + make).
- Ensuite tu compiles directement depuis le terminal.
// Ubuntu / Debian
sudo apt-get update
sudo apt-get install build-essential
gcc --versionÉditeur gratuit (optionnel mais confortable)
Si tu veux une interface propre (syntax highlight, terminal intégré, extensions), utilise VS Code.
Alternative “Clang sur Windows” (pour les curieux)
LLVM-MinGW fournit une toolchain Clang prête à dézipper (pratique si tu veux tester Clang/LLD).
FAQ récursion en C pour dev juniors
Questions qu’on se pose vraiment quand on apprend la récursion, avec des réponses simples, pratiques et orientées code.
Q C’est quoi la différence entre récursion et boucle ? ⌄
- Boucle : contrôle par
for/while. - Récursion : contrôle par cas de base + réduction du problème.
Q Comment savoir si ma récursion va se terminer ? ⌄
- Est-ce que j’ai un cas de base qui stoppe les appels ?
- À chaque appel, est-ce que je rapproche mon entrée du cas de base (ex :
n = n - 1) ?
Q Pourquoi j’ai un stack overflow (ou mon programme plante) ? ⌄
- Réduis la profondeur (meilleure réduction du problème).
- Passe en version itérative si la profondeur peut exploser.
- Évite les récursions inutiles (ex : Fibonacci naïf).
Q Comment déboguer une fonction récursive sans devenir fou ? ⌄
- Ajoute
printf("n=%d\n", n);au début de la fonction. - Option : affiche une indentation (profondeur) pour voir la “descente” et la “remontée”.
- Teste avec de petits inputs :
0,1,2,5.
Q Je dois faire le calcul avant ou après l’appel récursif ? ⌄
- Avant l’appel : utile quand tu veux traiter en “descendant” (pré-traitement).
- Après l’appel : utile quand tu as besoin du résultat du sous-problème pour combiner (post-traitement).
Q Quand la récursion est-elle meilleure qu’une boucle ? ⌄
- parcours d’un arbre (dossiers/fichiers, expressions)
- algorithmes de division (tri fusion, quicksort)
- backtracking (labyrinthe, combinaisons)
Q Pourquoi Fibonacci récursif est lent et comment l’améliorer ? ⌄
- Solution 1 : mémoïsation (tableau qui stocke les résultats).
- Solution 2 : version itérative (souvent la plus simple et rapide).
Q Quels tests minimum faire avant de valider un exercice récursif ? ⌄
- un cas de base (ex :
n=0oun=1) - un petit cas (ex :
n=3) - un cas “plus grand” (ex :
n=10) - un cas limite si possible (ex : valeur négative / entrée vide)
Mini-projets en C pour maîtriser la récursion pas à pas
La récursion est souvent perçue comme abstraite jusqu’au moment où on l’applique à des situations concrètes. Cette page propose une approche orientée pratique : de petits mini-projets progressifs qui transforment la théorie en réflexe. L’objectif est simple : comprendre le cas de base, la réduction du problème et le moment du traitement.
Table des mini-projets
Mini-projet 1 — Afficher un nombre en binaire
Objectif : comprendre le traitement après l’appel récursif.
void print_binary(unsigned int n){
if(n<2){ printf("%u",n); return; }
print_binary(n/2);
printf("%u",n%2);
}Exercice corrigé
Modifier la fonction pour afficher un espace tous les 4 bits.
---Mini-projet 2 — Somme des chiffres
int sum_digits(int n){
if(n<0) n=-n;
if(n<10) return n;
return (n%10)+sum_digits(n/10);
}Exercice corrigé
Adapter la fonction pour compter le nombre de chiffres.
---Mini-projet 3 — Parcours d’un tableau
void print_array(int *a,int n,int i){
if(i>=n) return;
printf("%d ",a[i]);
print_array(a,n,i+1);
}Exercice corrigé
Retourner la valeur maximale du tableau.
---Mini-projet 4 — Permutations
void permute(char*s,int l,int r){
if(l==r){ puts(s); return; }
for(int i=l;i<=r;i++){
swap(&s[l],&s[i]);
permute(s,l+1,r);
swap(&s[l],&s[i]);
}
}Exercice corrigé
Afficher uniquement les permutations commençant par une voyelle.
---Installer rapidement un environnement C
FAQ Dev Junior
Différence récursion / boucle ?
La boucle répète, la récursion se rappelle elle-même.
Pourquoi stack overflow ?
Profondeur trop grande ou absence de cas de base.
Quand préférer une boucle ?
Quand la structure du problème est linéaire.
