Aller au contenu

🔧 B2.4 - Fonctions et Méthodes en C

📋 Objectifs du cours

À la fin de ce cours, vous serez capable de : - ✅ Comprendre l'utilité des fonctions et méthodes - ✅ Créer des méthodes avec et sans paramètres - ✅ Utiliser les valeurs de retour - ✅ Maîtriser les différents types de paramètres - ✅ Appliquer les bonnes pratiques de programmation modulaire


🎯 Introduction aux méthodes

🔧
Qu'est-ce qu'une méthode ?
Une méthode est un bloc de code réutilisable qui effectue une tâche spécifique. Elle permet de diviser un programme complexe en parties plus petites et plus gérables, favorisant la réutilisabilité et la lisibilité du code.
💡 Avantages des méthodes :
  • Réutilisabilité : Évite la duplication de code
  • Lisibilité : Code plus organisé et compréhensible
  • Maintenance : Modifications centralisées
  • Test : Facilite les tests unitaires

📝 Anatomie d'une méthode

// Syntaxe générale
[modificateur] [type_retour] NomMethode([paramètres])
{
    // Corps de la méthode
    [return valeur;] // Si type_retour != void
}

// Exemple concret
public static int Additionner(int a, int b)
{
    int resultat = a + b;
    return resultat;
}

🚀 Méthodes simples

🔤 Méthodes sans paramètres ni retour

// Méthode qui affiche un message
public static void AfficherBienvenue()
{
    Console.WriteLine("===================");
    Console.WriteLine("  BIENVENUE !  ");
    Console.WriteLine("===================");
}

// Méthode qui affiche la date actuelle
public static void AfficherDate()
{
    DateTime maintenant = DateTime.Now;
    Console.WriteLine($"Nous sommes le {maintenant:dd/MM/yyyy}");
}

// Utilisation dans Main
static void Main(string[] args)
{
    AfficherBienvenue();
    AfficherDate();
}

📤 Méthodes avec valeur de retour

// Méthode qui retourne un nombre aléatoire
public static int GenererNombreAleatoire()
{
    Random random = new Random();
    return random.Next(1, 101); // Entre 1 et 100
}

// Méthode qui retourne l'heure actuelle formatée
public static string ObtenirHeureActuelle()
{
    return DateTime.Now.ToString("HH:mm:ss");
}

// Méthode qui vérifie si une année est bissextile
public static bool EstBissextile(int annee)
{
    return (annee % 4 == 0 && annee % 100 != 0) || (annee % 400 == 0);
}

// Utilisation
static void Main(string[] args)
{
    int nombre = GenererNombreAleatoire();
    string heure = ObtenirHeureActuelle();
    bool bissextile = EstBissextile(2024);

    Console.WriteLine($"Nombre : {nombre}");
    Console.WriteLine($"Heure : {heure}");
    Console.WriteLine($"2024 est bissextile : {bissextile}");
}

📥 Paramètres de méthodes

🎯 Paramètres simples

// Méthode avec un paramètre
public static void SaluerPersonne(string nom)
{
    Console.WriteLine($"Bonjour {nom} !");
}

// Méthode avec plusieurs paramètres
public static double CalculerAire(double longueur, double largeur)
{
    return longueur * largeur;
}

// Méthode avec paramètres de types différents
public static void AfficherInfoPersonne(string nom, int age, bool estEtudiant)
{
    Console.WriteLine($"Nom : {nom}");
    Console.WriteLine($"Âge : {age} ans");
    Console.WriteLine($"Statut : {(estEtudiant ? "Étudiant" : "Non étudiant")}");
}

// Utilisation
static void Main(string[] args)
{
    SaluerPersonne("Alice");

    double aire = CalculerAire(5.5, 3.2);
    Console.WriteLine($"Aire : {aire} m²");

    AfficherInfoPersonne("Bob", 22, true);
}

🔧 Paramètres avec valeurs par défaut

// Paramètres optionnels avec valeurs par défaut
public static void CreerCompte(string nom, string email, bool estActif = true, string role = "Utilisateur")
{
    Console.WriteLine($"Compte créé :");
    Console.WriteLine($"- Nom : {nom}");
    Console.WriteLine($"- Email : {email}");
    Console.WriteLine($"- Actif : {estActif}");
    Console.WriteLine($"- Rôle : {role}");
}

// Méthode de calcul avec paramètres optionnels
public static double CalculerPrix(double prixBase, double tva = 0.20, double remise = 0.0)
{
    double prixAvecTva = prixBase * (1 + tva);
    double prixFinal = prixAvecTva * (1 - remise);
    return prixFinal;
}

// Utilisation avec différentes combinaisons
static void Main(string[] args)
{
    // Tous les paramètres
    CreerCompte("Alice", "alice@email.com", true, "Admin");

    // Paramètres par défaut utilisés
    CreerCompte("Bob", "bob@email.com");

    // Paramètres nommés
    CreerCompte("Charlie", "charlie@email.com", role: "Modérateur");

    // Calculs de prix
    double prix1 = CalculerPrix(100);           // 120€ (TVA 20%)
    double prix2 = CalculerPrix(100, 0.10);     // 110€ (TVA 10%)
    double prix3 = CalculerPrix(100, 0.20, 0.15); // 102€ (TVA 20%, remise 15%)
}

📋 Paramètres params

// Méthode avec nombre variable de paramètres
public static int Additionner(params int[] nombres)
{
    int somme = 0;
    foreach (int nombre in nombres)
    {
        somme += nombre;
    }
    return somme;
}

// Méthode pour formater un message avec plusieurs valeurs
public static string FormaterMessage(string template, params object[] valeurs)
{
    return string.Format(template, valeurs);
}

// Utilisation
static void Main(string[] args)
{
    // Différentes façons d'appeler la méthode
    int somme1 = Additionner(1, 2, 3);           // 6
    int somme2 = Additionner(10, 20, 30, 40);    // 100
    int somme3 = Additionner();                  // 0

    // Avec un tableau
    int[] nombres = { 5, 10, 15 };
    int somme4 = Additionner(nombres);           // 30

    // Formatage de messages
    string msg = FormaterMessage("Bonjour {0}, vous avez {1} ans", "Alice", 25);
    Console.WriteLine(msg); // "Bonjour Alice, vous avez 25 ans"
}

🔄 Paramètres par référence

📤 Paramètres out

// Méthode qui retourne plusieurs valeurs avec out
public static bool DiviserAvecReste(int dividende, int diviseur, out int quotient, out int reste)
{
    if (diviseur == 0)
    {
        quotient = 0;
        reste = 0;
        return false; // Division impossible
    }

    quotient = dividende / diviseur;
    reste = dividende % diviseur;
    return true; // Division réussie
}

// Méthode pour analyser une chaîne de nombres
public static bool AnalyserNombres(string texte, out int minimum, out int maximum, out double moyenne)
{
    minimum = 0;
    maximum = 0;
    moyenne = 0;

    string[] parties = texte.Split(',');
    List<int> nombres = new List<int>();

    foreach (string partie in parties)
    {
        if (int.TryParse(partie.Trim(), out int nombre))
        {
            nombres.Add(nombre);
        }
    }

    if (nombres.Count == 0)
        return false;

    minimum = nombres.Min();
    maximum = nombres.Max();
    moyenne = nombres.Average();
    return true;
}

// Utilisation
static void Main(string[] args)
{
    // Division avec reste
    if (DiviserAvecReste(17, 5, out int quotient, out int reste))
    {
        Console.WriteLine($"17 ÷ 5 = {quotient} reste {reste}");
    }

    // Analyse de nombres
    string donnees = "10, 25, 8, 33, 12";
    if (AnalyserNombres(donnees, out int min, out int max, out double moy))
    {
        Console.WriteLine($"Min: {min}, Max: {max}, Moyenne: {moy:F2}");
    }
}

🔄 Paramètres ref

// Méthode qui échange deux valeurs
public static void Echanger(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

// Méthode qui modifie une chaîne
public static void TransformerTexte(ref string texte)
{
    texte = texte.ToUpper().Replace(" ", "_");
}

// Méthode qui applique une remise
public static void AppliquerRemise(ref double prix, double pourcentageRemise)
{
    prix = prix * (1 - pourcentageRemise / 100);
}

// Utilisation
static void Main(string[] args)
{
    // Échange de valeurs
    int x = 10, y = 20;
    Console.WriteLine($"Avant : x={x}, y={y}");
    Echanger(ref x, ref y);
    Console.WriteLine($"Après : x={x}, y={y}");

    // Transformation de texte
    string message = "Bonjour le monde";
    Console.WriteLine($"Avant : {message}");
    TransformerTexte(ref message);
    Console.WriteLine($"Après : {message}");

    // Application de remise
    double prix = 100.0;
    Console.WriteLine($"Prix initial : {prix}€");
    AppliquerRemise(ref prix, 15); // 15% de remise
    Console.WriteLine($"Prix après remise : {prix}€");
}

🏗️ Méthodes avancées

🔄 Surcharge de méthodes (Overloading)

// Plusieurs versions de la même méthode avec des paramètres différents
public static class Calculatrice
{
    // Addition de deux entiers
    public static int Additionner(int a, int b)
    {
        return a + b;
    }

    // Addition de trois entiers
    public static int Additionner(int a, int b, int c)
    {
        return a + b + c;
    }

    // Addition de deux doubles
    public static double Additionner(double a, double b)
    {
        return a + b;
    }

    // Addition d'un tableau d'entiers
    public static int Additionner(int[] nombres)
    {
        int somme = 0;
        foreach (int nombre in nombres)
        {
            somme += nombre;
        }
        return somme;
    }
}

// Utilisation
static void Main(string[] args)
{
    int somme1 = Calculatrice.Additionner(5, 3);           // 8
    int somme2 = Calculatrice.Additionner(1, 2, 3);        // 6
    double somme3 = Calculatrice.Additionner(2.5, 3.7);    // 6.2
    int somme4 = Calculatrice.Additionner(new int[] { 1, 2, 3, 4 }); // 10
}

🎯 Méthodes d'extension

// Classe statique pour les méthodes d'extension
public static class StringExtensions
{
    // Méthode d'extension pour compter les mots
    public static int CompterMots(this string texte)
    {
        if (string.IsNullOrWhiteSpace(texte))
            return 0;

        return texte.Split(new char[] { ' ', '\t', '\n' }, 
                          StringSplitOptions.RemoveEmptyEntries).Length;
    }

    // Méthode d'extension pour inverser une chaîne
    public static string Inverser(this string texte)
    {
        if (string.IsNullOrEmpty(texte))
            return texte;

        char[] caracteres = texte.ToCharArray();
        Array.Reverse(caracteres);
        return new string(caracteres);
    }

    // Méthode d'extension pour capitaliser chaque mot
    public static string CapitaliserMots(this string texte)
    {
        if (string.IsNullOrWhiteSpace(texte))
            return texte;

        return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(texte.ToLower());
    }
}

// Utilisation
static void Main(string[] args)
{
    string phrase = "bonjour le monde";

    // Utilisation comme si c'étaient des méthodes de la classe string
    int nombreMots = phrase.CompterMots();           // 3
    string inverse = phrase.Inverser();              // "ednom el ruojnob"
    string capitalise = phrase.CapitaliserMots();    // "Bonjour Le Monde"

    Console.WriteLine($"Phrase : {phrase}");
    Console.WriteLine($"Nombre de mots : {nombreMots}");
    Console.WriteLine($"Inversée : {inverse}");
    Console.WriteLine($"Capitalisée : {capitalise}");
}

🎯 Exercices pratiques

🏋️ Exercice 1 : Calculatrice avancée

Créez une classe Calculatrice avec les méthodes suivantes : 1. `Additionner`, `Soustraire`, `Multiplier`, `Diviser` (avec gestion division par zéro) 2. `Puissance` (nombre élevé à une puissance) 3. `Factorielle` (calcul récursif ou itératif) 4. `EstPremier` (vérifier si un nombre est premier)
public static class Calculatrice
{
    // Vos méthodes ici
}

🏋️ Exercice 2 : Gestionnaire de mots de passe

Créez des méthodes pour : 1. `GenererMotDePasse(int longueur, bool inclureSymboles = false)` 2. `ValiderMotDePasse(string motDePasse, out string[] erreurs)` 3. `CalculerForce(string motDePasse)` qui retourne un score de 0 à 100 Critères de validation : au moins 8 caractères, une majuscule, une minuscule, un chiffre.
// Votre code ici

🏋️ Exercice 3 : Analyseur de fichier texte

Créez des méthodes pour analyser un texte : 1. `CompterCaracteres(string texte, out int lettres, out int chiffres, out int espaces)` 2. `TrouverMotLePlusLong(string texte)` 3. `CalculerFrequenceMots(string texte)` qui retourne un Dictionary 4. `RemplacerMots(ref string texte, Dictionary remplacements)`
// Votre code ici

🏋️ Exercice 4 : Système de notes

Créez un système de gestion de notes avec : 1. `AjouterNote(List notes, double note)` avec validation (0-20) 2. `CalculerMoyenne(List notes)` 3. `ObtenirStatistiques(List notes, out double min, out double max, out double ecartType)` 4. `AttribuerMention(double moyenne)` qui retourne "Très bien", "Bien", etc.
// Votre code ici

🚀 Bonnes pratiques

Conseils pour de bonnes méthodes
**1. Nommage clair et descriptif :**
// ❌ Mauvais
public static int Calc(int x, int y) { return x + y; }

// ✅ Bon
public static int CalculerSomme(int premier, int second) { return premier + second; }
**2. Une méthode = une responsabilité :**
// ❌ Fait trop de choses
public static void TraiterUtilisateur(string nom, string email)
{
    // Validation
    // Sauvegarde en base
    // Envoi d'email
    // Logging
}

// ✅ Responsabilités séparées
public static bool ValiderUtilisateur(string nom, string email) { /* ... */ }
public static void SauvegarderUtilisateur(string nom, string email) { /* ... */ }
public static void EnvoyerEmailBienvenue(string email) { /* ... */ }
**3. Éviter les méthodes trop longues :**
// ✅ Si une méthode fait plus de 20-30 lignes, la diviser
public static void TraiterCommande(Commande commande)
{
    ValiderCommande(commande);
    CalculerPrix(commande);
    AppliquerRemises(commande);
    EnregistrerCommande(commande);
}
**4. Gérer les cas d'erreur :**
public static double Diviser(double a, double b)
{
    if (b == 0)
        throw new ArgumentException("Division par zéro impossible");

    return a / b;
}
⚠️ Erreurs courantes à éviter :
  • Oublier le return : Dans une méthode non-void
  • Modifier des paramètres : Sans ref/out quand nécessaire
  • Méthodes trop complexes : Diviser en sous-méthodes
  • Pas de validation : Toujours valider les paramètres d'entrée

📚 Points clés à retenir

🎯 Résumé du chapitre :
  • Méthodes : Blocs de code réutilisables avec paramètres et retour
  • Paramètres : Simples, optionnels, params, ref, out
  • Surcharge : Plusieurs versions avec paramètres différents
  • Extensions : Ajouter des méthodes aux types existants
  • Bonnes pratiques : Nommage clair, responsabilité unique, gestion d'erreurs

🔗 Liens utiles


Étape précédente : B2.3 - Listes et collections
Prochaine étape : B2.5 - Programmation Orientée Objet