Langage C/C++

Les Fonctions en C : Concepts et Exercices Corrigés

En programmation C, une fonction est un bloc de code autonome qui effectue une tâche spécifique. Elle permet de diviser un programme complexe en sous-programmes plus petits, facilitant ainsi la gestion, la lecture, et la maintenance du code. Une fonction en C se compose de trois parties principales :

  1. Déclaration de la fonction : Prototypage de la fonction avant son utilisation.
  2. Définition de la fonction : Contient le code qui réalise la tâche spécifique.
  3. Appel de la fonction : Point du programme où la fonction est exécutée.
Structure d’une Fonction en C

La structure d’une fonction en C est la suivante :

type_de_retour nom_de_fonction(type_argument1 nom_argument1, type_argument2 nom_argument2, ...) {
    // Corps de la fonction
    return valeur_de_retour;
}
  • type_de_retour : Type de la valeur retournée par la fonction (par exemple, int, float, void).
  • nom_de_fonction : Nom unique attribué à la fonction.
  • type_argument : Type des paramètres passés à la fonction.
  • nom_argument : Nom des paramètres utilisés dans la fonction.
Exemple Simple : Fonction qui Additionne Deux Nombres
#include <stdio.h>

// Déclaration de la fonction
int addition(int a, int b);

int main() {
    int x = 10;
    int y = 20;
    int resultat;

    // Appel de la fonction
    resultat = addition(x, y);
    printf("La somme de %d et %d est %d\n", x, y, resultat);

    return 0;
}

// Définition de la fonction
int addition(int a, int b) {
    return a + b;
}

Dans cet exemple, la fonction addition prend deux paramètres a et b, puis retourne leur somme.

Avantages de l’Utilisation des Fonctions
  • Réutilisation du code : Une fonction peut être appelée plusieurs fois dans le programme.
  • Organisation du code : Le programme est plus clair et mieux structuré.
  • Facilité de maintenance : La modification d’une fonction n’affecte pas le reste du programme.
Exercices Corrigés
Exercice 1 : Calcul de la Factorielle d’un Nombre

Énoncé : Écrire une fonction factorielle qui calcule la factorielle d’un nombre entier n. La factorielle de n est définie comme n! = n * (n-1) * (n-2) * ... * 1.

Solution :

#include <stdio.h>

int factorielle(int n);

int main() {
    int nombre;
    printf("Entrez un nombre : ");
    scanf("%d", &nombre);

    printf("La factorielle de %d est %d\n", nombre, factorielle(nombre));
    return 0;
}

int factorielle(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorielle(n - 1);
    }
}

Explication : La fonction factorielle utilise une méthode récursive pour calculer la factorielle. Si n est 0, la fonction retourne 1 (car 0! = 1). Sinon, elle retourne n * factorielle(n-1).

Exercice 2 : Vérification d’un Nombre Premier

Énoncé : Écrire une fonction estPremier qui vérifie si un nombre donné est premier ou non. Un nombre est dit premier s’il n’a que deux diviseurs : 1 et lui-même.

Solution :

#include <stdio.h>
#include <stdbool.h>

bool estPremier(int n);

int main() {
    int nombre;
    printf("Entrez un nombre : ");
    scanf("%d", &nombre);

    if (estPremier(nombre)) {
        printf("%d est un nombre premier.\n", nombre);
    } else {
        printf("%d n'est pas un nombre premier.\n", nombre);
    }

    return 0;
}

bool estPremier(int n) {
    if (n <= 1) return false;
    for (int i = 2; i <= n / 2; i++) {
        if (n % i == 0) return false;
    }
    return true;
}

Explication : La fonction estPremier vérifie pour chaque nombre de 2 à n/2 si n est divisible par ce nombre. Si c’est le cas, n n’est pas premier. Sinon, n est premier.

Exercice 3 : Calcul de la Puissance d’un Nombre

Énoncé : Écrire une fonction puissance qui calcule la puissance p d’un nombre x, c’est-à-dire x^p.

Solution :

#include <stdio.h>

int puissance(int x, int p);

int main() {
    int base, exposant;
    printf("Entrez la base : ");
    scanf("%d", &base);
    printf("Entrez l'exposant : ");
    scanf("%d", &exposant);

    printf("%d^%d = %d\n", base, exposant, puissance(base, exposant));
    return 0;
}

int puissance(int x, int p) {
    int resultat = 1;
    for (int i = 0; i < p; i++) {
        resultat *= x;
    }
    return resultat;
}

Explication : La fonction puissance utilise une boucle pour multiplier la base x par elle-même p fois, ce qui donne x^p.

Exercice 4 : Calcul de la Moyenne d’un Tableau

Énoncé : Écrire une fonction moyenne qui prend en entrée un tableau d’entiers et sa taille, puis retourne la moyenne des éléments du tableau.

Solution :

#include <stdio.h>

float moyenne(int tableau[], int taille);

int main() {
    int notes[] = {12, 15, 10, 8, 16, 20};
    int taille = sizeof(notes) / sizeof(notes[0]);

    printf("La moyenne des notes est : %.2f\n", moyenne(notes, taille));
    return 0;
}

float moyenne(int tableau[], int taille) {
    int somme = 0;
    for (int i = 0; i < taille; i++) {
        somme += tableau[i];
    }
    return (float)somme / taille;
}

Explication : La fonction moyenne calcule d’abord la somme des éléments du tableau, puis divise cette somme par le nombre d’éléments pour obtenir la moyenne. La conversion en float permet de gérer les nombres décimaux pour une moyenne précise.

Exercice 5 : Recherche d’un Élément dans un Tableau

Énoncé : Écrire une fonction rechercher qui prend un tableau d’entiers, sa taille, et un élément à rechercher, puis retourne l’index de l’élément dans le tableau. Si l’élément n’est pas trouvé, la fonction retourne -1.

Solution :

#include <stdio.h>

int rechercher(int tableau[], int taille, int element);

int main() {
    int tableau[] = {3, 5, 7, 9, 11, 13};
    int taille = sizeof(tableau) / sizeof(tableau[0]);
    int element = 7;

    int index = rechercher(tableau, taille, element);
    if (index != -1) {
        printf("Élément trouvé à l'index : %d\n", index);
    } else {
        printf("Élément non trouvé dans le tableau.\n");
    }

    return 0;
}

int rechercher(int tableau[], int taille, int element) {
    for (int i = 0; i < taille; i++) {
        if (tableau[i] == element) {
            return i;
        }
    }
    return -1;
}

Explication : La fonction rechercher parcourt le tableau et compare chaque élément avec l’élément recherché. Si une correspondance est trouvée, elle retourne l’index de l’élément. Sinon, elle retourne -1 pour indiquer que l’élément n’est pas présent.

Exercice 6 : Inversion d’une Chaîne de Caractères

Énoncé : Écrire une fonction inverserChaine qui prend une chaîne de caractères et la renverse.

Solution :

#include <stdio.h>
#include <string.h>

void inverserChaine(char chaine[]);

int main() {
    char texte[] = "Programmation C";

    printf("Chaîne originale : %s\n", texte);
    inverserChaine(texte);
    printf("Chaîne inversée : %s\n", texte);

    return 0;
}

void inverserChaine(char chaine[]) {
    int longueur = strlen(chaine);
    for (int i = 0; i < longueur / 2; i++) {
        char temp = chaine[i];
        chaine[i] = chaine[longueur - i - 1];
        chaine[longueur - i - 1] = temp;
    }
}

Explication : La fonction inverserChaine utilise une boucle pour échanger les caractères aux extrémités de la chaîne, progressant vers le centre. Ainsi, la chaîne est inversée en place.

Exercice 7 : Conversion de Celsius en Fahrenheit

Énoncé : Écrire une fonction celsiusVersFahrenheit qui convertit une température donnée en degrés Celsius en Fahrenheit.

Solution :

#include <stdio.h>

float celsiusVersFahrenheit(float celsius);

int main() {
    float temperatureC = 25.0;

    printf("%.2f degrés Celsius équivaut à %.2f degrés Fahrenheit.\n", 
           temperatureC, celsiusVersFahrenheit(temperatureC));

    return 0;
}

float celsiusVersFahrenheit(float celsius) {
    return (celsius * 9 / 5) + 32;
}

Explication : La fonction celsiusVersFahrenheit applique la formule de conversion (C * 9/5) + 32 pour transformer la température de Celsius en Fahrenheit.

Conseils pour Approfondir vos Connaissances

  1. Expérimentez avec les Fonctions : Modifiez les fonctions existantes pour leur faire accomplir des tâches similaires, comme la gestion des tableaux multidimensionnels ou la manipulation des chaînes de caractères.
  2. Utilisez les Bibliothèques Standard C : Explorez les fonctions déjà disponibles dans les bibliothèques standard C, comme math.h pour des fonctions mathématiques ou string.h pour des opérations sur les chaînes de caractères.
  3. Implémentez des Algorithmes Plus Complexes : Après avoir maîtrisé les bases, tentez d’implémenter des algorithmes plus complexes comme le tri de tableaux, la recherche binaire, ou les algorithmes de tri et de recherche plus avancés.
  4. Développez des Programmes Modulaires : Lorsque vous travaillez sur des projets plus importants, divisez-les en modules fonctionnels et utilisez des fonctions pour chaque tâche. Cela rend le code plus facile à lire et à maintenir.

Exercices sur les Cas Particuliers des Fonctions en C

Voici une série d’exercices qui traitent des cas particuliers liés à l’utilisation des fonctions en C, tels que les cas de recursivité, les fonctions avec pointeurs, la gestion des erreurs, et les fonctions avec des structures.

Exercice 1 : Fonction Récursive avec un Cas de Base Particulier

Énoncé : Écrire une fonction récursive sommeImpaire qui calcule la somme des nombres impairs jusqu’à un nombre entier n donné. Si n est pair, la fonction doit ignorer n et considérer n-1.

Indications :

  • Si n est égal ou inférieur à 0, la fonction doit retourner 0.
  • Si n est impair, ajouter n à la somme des impairs précédents.

Solution Attendue :

#include <stdio.h>

int sommeImpaire(int n);

int main() {
    int nombre = 10;
    printf("La somme des impairs jusqu'à %d est : %d\n", nombre, sommeImpaire(nombre));
    return 0;
}

int sommeImpaire(int n) {
    if (n <= 0) return 0;
    if (n % 2 == 0) n--;  // Si n est pair, le rendre impair
    return n + sommeImpaire(n - 2);
}

Explication : Cette fonction gère le cas particulier où n est pair en le réduisant d’une unité pour le rendre impair avant de procéder à la somme récursive.

Exercice 2 : Fonction avec Pointeur et Gestion d’erreurs

Énoncé : Écrire une fonction divisionSecurisee qui prend deux entiers a et b, et qui retourne le quotient de a par b via un pointeur. Si b est égal à 0, la fonction doit retourner une erreur et ne pas tenter de diviser.

Indications :

  • Utilisez un pointeur pour retourner le quotient.
  • Gérez le cas où b est égal à 0 en retournant un code d’erreur.

Solution Attendue :

#include <stdio.h>
#include <stdbool.h>

bool divisionSecurisee(int a, int b, int *resultat);

int main() {
    int a = 10, b = 0;
    int quotient;

    if (divisionSecurisee(a, b, &quotient)) {
        printf("Le quotient de %d par %d est : %d\n", a, b, quotient);
    } else {
        printf("Erreur : division par zéro.\n");
    }

    return 0;
}

bool divisionSecurisee(int a, int b, int *resultat) {
    if (b == 0) return false;
    *resultat = a / b;
    return true;
}

Explication : Cette fonction utilise un pointeur pour retourner le résultat de la division et un booléen pour indiquer le succès ou l’échec de l’opération.

Exercice 3 : Fonction qui Modifie une Structure

Énoncé : Créez une structure Point avec deux champs x et y représentant les coordonnées d’un point dans un plan 2D. Écrire une fonction deplacerPoint qui prend un pointeur vers un Point et deux entiers dx et dy, et modifie les coordonnées du point en ajoutant dx et dy respectivement.

Indications :

  • La fonction doit modifier directement la structure passée en argument.

Solution Attendue :

#include <stdio.h>

typedef struct {
    int x;
    int y;
} Point;

void deplacerPoint(Point *p, int dx, int dy);

int main() {
    Point p = {3, 4};
    printf("Point avant déplacement : (%d, %d)\n", p.x, p.y);

    deplacerPoint(&p, 2, -1);
    printf("Point après déplacement : (%d, %d)\n", p.x, p.y);

    return 0;
}

void deplacerPoint(Point *p, int dx, int dy) {
    p->x += dx;
    p->y += dy;
}

Explication : La fonction deplacerPoint prend un pointeur sur une structure Point et modifie directement les coordonnées x et y en leur ajoutant dx et dy.

Exercice 4 : Fonction qui Retourne un Tableau Dynamique

Énoncé : Écrire une fonction genererTableauCarres qui prend un entier n et retourne un tableau dynamique contenant les carrés des nombres de 1 à n. Si n est inférieur ou égal à 0, la fonction doit retourner un tableau vide (de taille 0).

Indications :

  • Utilisez l’allocation dynamique de mémoire pour créer le tableau.
  • Gérez le cas où n est négatif ou nul en retournant un pointeur NULL.

Solution Attendue :

#include <stdio.h>
#include <stdlib.h>

int* genererTableauCarres(int n);

int main() {
    int n = 5;
    int *tableau = genererTableauCarres(n);

    if (tableau != NULL) {
        printf("Tableau des carrés de 1 à %d : ", n);
        for (int i = 0; i < n; i++) {
            printf("%d ", tableau[i]);
        }
        printf("\n");

        free(tableau);  // Libérer la mémoire allouée
    } else {
        printf("Le tableau est vide ou nulle.\n");
    }

    return 0;
}

int* genererTableauCarres(int n) {
    if (n <= 0) return NULL;

    int *tableau = (int*)malloc(n * sizeof(int));
    if (tableau == NULL) {
        printf("Erreur d'allocation de mémoire.\n");
        exit(1);
    }

    for (int i = 0; i < n; i++) {
        tableau[i] = (i + 1) * (i + 1);
    }

    return tableau;
}

Explication : La fonction genererTableauCarres alloue dynamiquement un tableau pour stocker les carrés des nombres de 1 à n. Si n est inférieur ou égal à 0, la fonction retourne NULL, indiquant un tableau vide.

Exercice 5 : Fonction de Gestion d’Erreurs avec Pointeurs Nuls

Énoncé : Écrire une fonction sommeTableauSecurisee qui prend un tableau d’entiers et sa taille, puis retourne la somme des éléments. Si le pointeur du tableau est NULL ou si la taille est négative, la fonction doit retourner une erreur.

Indications :

  • Vérifiez les entrées pour détecter les erreurs potentielles (pointeur NULL, taille négative).
  • Retournez un code d’erreur spécial si une condition invalide est détectée.

Solution Attendue :

#include <stdio.h>

int sommeTableauSecurisee(int *tableau, int taille);

int main() {
    int tableau[] = {1, 2, 3, 4, 5};
    int taille = sizeof(tableau) / sizeof(tableau[0]);

    int somme = sommeTableauSecurisee(tableau, taille);
    if (somme == -1) {
        printf("Erreur : tableau NULL ou taille invalide.\n");
    } else {
        printf("La somme du tableau est : %d\n", somme);
    }

    return 0;
}

int sommeTableauSecurisee(int *tableau, int taille) {
    if (tableau == NULL || taille <= 0) return -1;

    int somme = 0;
    for (int i = 0; i < taille; i++) {
        somme += tableau[i];
    }

    return somme;
}

Explication : La fonction sommeTableauSecurisee vérifie d’abord si le tableau est NULL ou si la taille est invalide. Si c’est le cas, elle retourne -1 pour indiquer une erreur. Sinon, elle calcule et retourne la somme des éléments du tableau.

Conclusion

Ces exercices couvrent divers cas particuliers dans la gestion des fonctions en C, tels que la gestion des erreurs, la manipulation de structures, l’utilisation de la récursivité, et l’allocation dynamique de mémoire. En les pratiquant, vous renforcerez votre capacité à écrire des fonctions robustes et à gérer efficacement les cas exceptionnels dans vos programmes C.

Autres articles

Guide : Comment créer un QCM en...
Le QCM en langage C peut être simulé dans un...
Read more
Tableaux en Langage C : Exercices Corrigés
Voici une série d'exercices corrigés sur les tableaux en langage...
Read more
Comment fonctionne la récursion terminale en C...
La récursion terminale en CLa récursion terminale est une forme...
Read more

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *