Quelques raccourcis :

420-KBB-LG – Programmation orientée objet avancée

Ceci est un petit site de support pour le cours 420-KBB-LG – Programmation orientée objet avancée.

Vous trouverez aussi des liens sur divers langages (dont C#, notre outil de prédilection dans ce cours) un peu partout dans http://h-deb.clg.qc.ca/. Portez une attention particulière à ../../../Sujets/Divers--cdiese/index.html.

Les diverses sections de cette page (en fonction desquelles vous trouverez quelques liens dans l'encadré à droite) vous mèneront elles-aussi sur des pistes qui vous permettront d'explorer un peu plus par vous-mêmes, de valider vos acquis et d'enrichir votre apprentissage.

Cliquez sur cette cible pour le plan de cours, sous forme électronique

Pratiques de correction

Je corrige les programmes en appliquant des codes de correction. Vous trouverez ici la liste des codes les plus fréquents.

Ma stratégie de correction en tant que telle (pour le code, à tout le moins) est résumée ici.

Cliquez sur cette cible pour les normes appliquées dans ce cours, en ce qui a trait au pseudocode

Quelques trucs pour demander de l'aide plus efficacement

Détail des séances en classe

Puisque nous serons en quelque sorte laboratoire à la fois pour les séances théoriques et les séances de laboratoire, j'ai fait le choix de construire le cours sous forme de 30 séances (de S00 à S29) plutôt que sous forme de 15 séances théoriques et 15 séances de laboratoire. Le dosage prévu de temps en théorie et de temps en laboratoire (soit environ moitié-moitié) devrait être respecté.

Date Séance Détails

24 août (lundi 13h)

S00

Séance d'accueil (1 de 2). Au menu :

Si vous souhaitez le code du programme principal à partir duquel vous devrez démarrer, vous pouvez le prendre du fichier PDF ou encore le prendre ci-dessous (parfois, copier / coller d'un PDF...) :

// ...
static void Main(string[] args)
{
   List<Orque> orques = new List<Orque>();
   try
   {
      for(string s = Console.ReadLine(); "" != s; s = Console.ReadLine())
      {
         orques.Add(new Orque(s));
         Console.WriteLine($"Orque créé : {orques[orques.Count - 1].Nom}");
      }
   }
   catch(NomInvalideException nie)
   {
      Console.WriteLine(nie.Message);
   }
   if(Trier(ref orques, out int nbPermutations))
   {
      Console.WriteLine("Les orques ont été entrés en ordre alphabétique");
   }
   else
   {
      Console.WriteLine($"Trier les orques a nécessité {nbPermutations} permutations");
   }
   Console.Write("La tribu d'orques est :");
   foreach (Orque orque in orques)
      Console.Write($" {orque.Nom}");
}

À titre de référence, le code produit lors de cette séance pour démontrer le clonage était :

using System;
class Program
{
   enum Couleur { Rouge, Vert, Bleu }
   // il existe une interface ICloneable, qui expose une méthode Clone
   // ... mais ne l'utilisez pas :)
   abstract class Image
   {
      public Couleur Teinte { get; set; } 
      public abstract void Dessiner();
      protected Image(Couleur teinte)
      {
         Teinte = teinte;
      }
      protected Image(Image autre)
      {
         Teinte = autre.Teinte;
      }
      public abstract Image Cloner();
   }
   class Jpeg : Image
   {
      public override void Dessiner()
      {
         Console.WriteLine($"Je suis un Jpeg de couleur {Teinte}");
      }
      public Jpeg(Couleur teinte) : base(teinte)
      {
      }
      // constructeur "de copie" (écart de langage)
      protected Jpeg(Jpeg autre) : base(autre)
      {
      }
      public override Image Cloner()
      {
         return new Jpeg(this);
      }
   }
   class Png : Image
   {
      public override void Dessiner()
      {
         Console.WriteLine($"Je suis un Png de couleur {Teinte}");
      }
      public Png(Couleur teinte) : base(teinte)
      {
      }
      protected Png(Png autre) : base(autre)
      {
      }
      public override Image Cloner()
      {
         return new Png(this);
      }
   }
   class Bmp : Image
   {
      public override void Dessiner()
      {
         Console.WriteLine($"Je suis un Bmp de couleur {Teinte}");
      }
      public Bmp(Couleur teinte) : base(teinte)
      {
      }
      protected Bmp(Bmp autre) : base(autre)
      {
      }
      public override Image Cloner()
      {
         return new Bmp(this);
      }
   }
   static Image ModifierPeutÊtre(Image img)
   {
      Image backup = img.Cloner(); // schéma de conception (Design Pattern :) )
//       Image backup = img; // 1) faire une copie de sauvegarde (backup) de img (oups!)
      Console.Write("Avant : ");
      img.Dessiner();
      img.Teinte = Couleur.Rouge; // 2) modifier img
      Console.Write("Après : ");
      img.Dessiner();
      // 3) demander à l'usager s'il veut conserver la modif
      Console.Write("Conserver la modification? (o/n) "); 
      char c = char.Parse(Console.ReadLine());
      if (char.ToLower(c) == 'o')
         return img; // 4) si oui, retourner l'entité modifiée
      return backup; // 5) sinon, retourner la copie de sauvegarde
   }
   static void Main()
   {
      Image img = new Jpeg(Couleur.Bleu);
      img = ModifierPeutÊtre(img);
      Console.Write("Résultat : ");
      img.Dessiner();
   }
}

31 août (lundi 13h)

S01

Séance d'accueil (2 de 2). Au menu :

  • Retour sur la petite activité formative proposée à S00
  • Discussion de divers aspects techniques et architecturaux associés à cette activité
  • Avenues de raffinement ou d'optimisation
  • Quelques explorations qui nous mèneront vers notre premier travail pratique, le TP00

À titre de référence, le code d'aujourd'hui est :

using System;
using System.Collections.Generic;

class Program
{
   class Algos
   {
      //
      // Rappel : quand une fonction se limite à « return » suivi d'une
      // expression, les deux formes suivantes sont équivalentes (c'est
      // pour vous encourager à écrire de petites fonctions qui font une
      // et une seule chose!)
      //
      public static bool EstEntreInclusif(int val, int min, int max) =>
         min <= val && val <= max;
      //public static bool EstEntreInclusif(int val, int min, int max)
      //{
      //   return min <= val && val <= max;
      //}
   }
   class OutilsTexte
   {
      private readonly static char[] voyelles = new []{ 'a', 'e', 'i', 'o', 'u', 'y' };
      public static bool EstVoyelle(char c)
      {
         c = char.ToLower(c);
         foreach (char ch in voyelles)
            if (c == ch)
               return true;
         return false;
      }
      public static int CompterVoyelles(string s)
      {
         int nb = 0;
         foreach (char c in s)
            if (EstVoyelle(c))
               ++nb;
         return nb;
      }
   }
   class NomInvalideException : Exception
   {
      public NomInvalideException(string nom) : base($"Nom invalide : {nom}")
      {
      }
   }
   class Orque
   {
      private static bool EstNomValide(string s)
      {
         const int MIN_CAR = 1,
                   MAX_CAR = 4;
         const int MAX_VOYELLES = 1;
         return s != null && Algos.EstEntreInclusif(s.Length, MIN_CAR, MAX_CAR) &&
                             OutilsTexte.CompterVoyelles(s) <= MAX_VOYELLES;
      }
      private string nom;
      public string Nom
      {
         get => nom;
         private set
         {
            if (!EstNomValide(value))
               throw new NomInvalideException(value);
            nom = value;
         }
      }
      public Orque(string nom)
      {
         Nom = nom;
      }
   }
   static void Permuter(ref Orque a, ref Orque b)
   {
      Orque temp = a;
      a = b;
      b = temp;
   }
   static bool Trier(ref List<Orque> lst, out int nbPerm)
   {
      nbPerm = 0;
      Orque[] tab = lst.ToArray();
      // tri à bulles... très, très naïf
      for (int i = 0; i < tab.Length - 1; ++i)
         for (int j = i + 1; j < tab.Length; ++j)
            //
            // s'ils ne sont pas dans l'ordre, les permuter
            //
            // deux versions du même test : méthode d'instance (en commentaire)
            // et méthode de classe (pas en commentaire, suggéré par l'un d'entre
            // vous). L'avantage de la méthode de classe est qu'elle fonctionnera
            // si l'un des deux paramètres est null
            //
            //if (tab[i].Nom.CompareTo(tab[j].Nom) > 0)
            //
            if(string.Compare(tab[i].Nom, tab[j].Nom) > 0)
            {
               Permuter(ref tab[i], ref tab[j]);
               ++nbPerm;
            }
      lst = tab.ToList();
      return nbPerm == 0;
   }
   static void Main(string[] args)
   {
      List<Orque> orques = new List<Orque>();
      try
      {
         for (string s = Console.ReadLine(); "" != s; s = Console.ReadLine())
         {
            orques.Add(new Orque(s));
            Console.WriteLine($"Orque créé : {orques[orques.Count - 1].Nom}");
         }
      }
      catch (NomInvalideException nie)
      {
         Console.WriteLine(nie.Message);
      }
      if (Trier(ref orques, out int nbPermutations))
      {
         Console.WriteLine("Les orques ont été entrés en ordre alphabétique");
      }
      else
      {
         Console.WriteLine($"Trier les orques a nécessité {nbPermutations} permutations");
      }
      Console.Write("La tribu d'orques est :");
      foreach (Orque orque in orques)
         Console.Write($" {orque.Nom}");
   }
}

En espérant que cela vous soit utile!

9 sept.

S02

Au menu :

  • Créer une bibliothèque à liens dynamiques : création d'un petit système client / serveur
    • schéma de conception Interface et son implémentation en C#
    • implémentation(s) de cette interface
    • schéma de conception Fabrique
  • Écriture d'un client pour ce service
  • Utilité de ce type d'architecture
  • Présentation du TP00 (voir #tp pour les consignes de travaux pratiques en général)
  • Travail sur le TP00
  • Petit bonbon : introduction aux uplets

14 sept.

S03

Cette semaine, je serai (virtuellement) à CppCon 2020. Vous pourrez me suivre (à travers ../../Sujets/Orthogonal/cppcon2020.html) si vous le souhaitez.

16 sept.

S04

Cette semaine, je serai (virtuellement) à CppCon 2020. Vous pourrez me suivre (à travers ../../Sujets/Orthogonal/cppcon2020.html) si vous le souhaitez.

21 sept.

S05

Au menu :

Je vais revenir sur using, que je n'ai pas couvert aujourd'hui, et finally, le tout quand nous aurons rencontré des cas qui les rendent pertinent (ça s'en vient)

23 sept.

S06

Au menu :

  • Petite introduction à la complexité algorithmique et à la consommation de ressources :
    • pour un générateur séquentiel :
    • pour un générateur recycleur :
    • pour un générateur aléatoire naïf :
    • raffiner le générateur aléatoire
  • Examen du problème de la génération des statistiques :
    • conceptualiser les paires
    • introduction aux dictionnaires
    • traduction des paires clés / valeurs en uplets
  • Travail sur le TP00

Si le temps le permet, il se peut que nous abordions sommairement la surcharge d'opérateurs

N'oubliez pas de remettre votre TP00 avant  23 h 59 le 25 septembre

28 sept.

S07

Au menu :

À la demande générale, le code (incomplet mais fonctionnel) de l'observateur de clavier est :

using System;
using System.Collections.Generic;

class Program
{
   interface IRéactionClavier
   {
      void Réagir(char c);
   }
   class Afficheur : IRéactionClavier
   {
      public void Réagir(char c)
      {
         Console.WriteLine($"Touche pressée : {c}");
      }
   }
   class Crieur : IRéactionClavier
   {
      public void Réagir(char c)
      {
         Console.Beep();
         for(int i = 0; i != 10; ++i)
            Console.Write(char.ToUpper(c));
         Console.WriteLine();
      }
   }

   class ServeurClavier
   {
      List<IRéactionClavier> Abonnés { get; } = new List<IRéactionClavier>();
      public void Abonner(IRéactionClavier p)
      {
         Abonnés.Add(p);
      }
      public void Exécuter()
      {
         char k = Console.ReadKey(true).KeyChar;
         foreach (var p in Abonnés)
            p.Réagir(k);
      }
   }

   class GoUp : IRéactionClavier
   {
      char Touche { get; }
      public GoUp(char touche)
      {
         Touche = char.ToUpper(touche);
      }
      public void Réagir(char c)
      {
         if (char.ToUpper(c) == Touche)
            Console.WriteLine("On monte");
      }
   }
   class GoDown : IRéactionClavier
   {
      char Touche { get; }
      public GoDown(char touche)
      {
         Touche = char.ToUpper(touche);
      }
      public void Réagir(char c)
      {
         if (char.ToUpper(c) == Touche)
            Console.WriteLine("On descend");
      }
   }

   class Quitteur : IRéactionClavier
   {
      public void Réagir(char c)
      {
         if (char.ToUpper(c) == 'Q')
            Environment.Exit(0);
      }
   }

   // Singleton : classe dont il n'y a pas plus d'une instance dans le programme
   // Observateur : système d'abonnement qui rappelle les abonnés
   static void Main()
   {
      var serveur = new ServeurClavier();
      serveur.Abonner(new GoUp('w'));
      serveur.Abonner(new GoDown('s'));
      serveur.Abonner(new Quitteur()); // hum... au prochain cours...
      serveur.Abonner(new Afficheur());
      for ( ; ; )
      {
         serveur.Exécuter();
      }
   }
}

30 sept.

S08

Au menu :

  • Retour sur Q00
  • Mieux terminer l'exécution du ServeurClavier donné en exemple à S07
  • Retour bref sur les indexeurs
  • Les struct en C#
  • Lancer un programme en lui passant des paramètres
  • Présentation du TP01

5 oct.

S09

Au menu :

  • Travail sur le TP01

7 oct.

S10

Au menu :

Les exemples de la première moitié du cours suivent. Pour la fonction Afficher générique :

using System;
using System.Collections.Generic;
class Program
{
   static void Afficher<T>(T n)
   {
      Console.Write($"{n} ");
   }
   static void Main()
   {
      Afficher(3);
      Afficher(3.14159f);
   }
} 
// ...

... pour la fonction TriBulles générique, de même que Permuter (j'ai ajouté la classe X sous sa forme IComparable<X> pour fins d'illustration; si vous la remplacez par une version qui n'est pas IComparable<X>, on ne pourra plus trier un X[]) :

using System;
using System.Collections.Generic;
class Program
{
   static void Permuter<T>(ref T a, ref T b)
   {
      T temp = a;
      a = b;
      b = temp;
   }

   static void TriBulles<T>(T [] tab) where T : IComparable<T>
   {
      for (int i = 0; i < tab.Length - 1; ++i)
         for (int j = i + 1; j < tab.Length; ++j)
            if (tab[i].CompareTo(tab[j]) > 0)
               Permuter(ref tab[i], ref tab[j]);
   }
   class X : IComparable<X>
   {
      public int CompareTo(X x) => 0;
   }
   // class X
   // {
   // }
   static void Main()
   {
      int[] tab = new[] { 3, 7, 11, 2, 5 };
      TriBulles(tab);
      foreach (int n in tab)
         Console.Write($"{n} ");
      Console.WriteLine();
      string[] strs= new[] { "man", "allo", "genre" };
      TriBulles(strs);
      foreach (var s in strs)
         Console.Write($"{s} ");
      TriBulles(new X[] { new X(), new X(), new X() });
   }
} 
// ...

... pour la classe Pile<T> :

using System;
using System.Collections.Generic;
class Program
{
   class Pile<T>
   {
      const int TAILLE_MAX = 10;
      T[] Éléments { get; } = new T[TAILLE_MAX];
      public int Count { get; private set; } = 0;
      public bool EstVide { get => Count == 0; }
      public bool EstPleine { get => Count == TAILLE_MAX; }
      public void Push(T élem)
      {
         if (EstPleine) throw new Exception(); // bof
         Éléments[Count] = élem;
         ++Count;
      }
      public void Pop()
      {
         if (EstVide) throw new Exception(); // bof
         --Count;
      }
      public T Top()
      {
         if (EstVide) throw new Exception(); // bof
         return Éléments[Count - 1];
      }
   }
   static void Main()
   {
      var pile = new Pile<string>();
      pile.Push("prof");
      pile.Push("mon");
      pile.Push("J'aime");
      while(!pile.EstVide)
      {
         Console.WriteLine(pile.Top());
         pile.Pop();
      }
   }
} 
// ...

... Pour la fonction Chercher<T> :

using System;
using System.Collections.Generic;
class Program
{
   static int Chercher<T>(T[] tab, T val) where T : IEquatable<T>
   {
      for (int i = 0; i != tab.Length; ++i)
         if (tab[i].Equals(val))
            return i;
      return -1;
   }
   static void Main()
   {
      string[] strs = new string[] { "Tomate", "Concombre", "Radis" };
      int n = Chercher(strs, "Radis");
      if (n == -1)
         Console.WriteLine("Pas trouvé...");
      else
         Console.WriteLine($"Trouvé à l'indice {n}");
   }
} 
// ...

13 oct.

S11

Attention, mardi avec horaire du lundi

Au menu :

14 oct.

S12

Au menu :

19 oct.

S13

Au menu :

21 oct.

S14

Au menu :

Petit exemple donné en classe :

   static (T,long) Test<T>(Func<T> f)
   {
      var sw = new System.Diagnostics.Stopwatch();
      sw.Start();
      T res = f();
      sw.Stop();
      return (res, sw.ElapsedTicks);
   }


   static void Main()
   {
      const int N = 1_000_000;
      var (r0,dt0) = Test(() =>
      {
         int n = 0;
         var th0 = new Thread(() =>
         {
            for (int i = 0; i != N; ++i)
               ++n;
         });
         var th1 = new Thread(() =>
         {
            for (int i = 0; i != N; ++i)
               ++n;
         });
         th0.Start();
         th1.Start();
         th1.Join();
         th0.Join();
         return n;
      });
      var (r1, dt1) = Test(() =>
      {
         int n = 0;
         var mutex = new object();
         var th0 = new Thread(() =>
         {
            for (int i = 0; i != N; ++i)
               lock (mutex)
               {
                  ++n;
               }
         });
         var th1 = new Thread(() =>
         {
            for (int i = 0; i != N; ++i)
               lock (mutex)
               {
                  ++n;
               }
         });
         th0.Start();
         th1.Start();
         th1.Join();
         th0.Join();
         return n;
      });
      var (r2, dt2) = Test(() =>
      {
         int n = 0;
         var mutex = new object();
         var th0 = new Thread(() =>
         {
            int m = 0;
            for (int i = 0; i != N; ++i)
               ++m;
            lock (mutex)
            {
               n += m;
            }
         });
         var th1 = new Thread(() =>
         {
            int m = 0;
            for (int i = 0; i != N; ++i)
               ++m;
            lock (mutex)
            {
               n += m;
            }
         });
         th0.Start();
         th1.Start();
         th1.Join();
         th0.Join();
         return n;
      });
      Console.WriteLine($"Sans synchro : {r0} obtenu en {dt0} tics");
      Console.WriteLine($"Avec synchro : {r1} obtenu en {dt1} tics");
      Console.WriteLine($"Avec synchro : {r2} obtenu en {dt2} tics");
   }
}

 

26 oct.

S15

Au menu :

L'exemple utilisé en classe pour illustrer le faux-partage était :

using System;
using System.Threading;
using System.Diagnostics;

class Program
{
   static short[] CréerTableau(int n)
   {
      short[] tab = new short[n];
      for (int i = 0; i != tab.Length; ++i)
         tab[i] = (short)(i * 2 + 1);
      return tab;
   }
   static (T rés, long dt) Tester<T>(Func<T> f)
   {
      var sw = new Stopwatch();
      sw.Start();
      T rés = f();
      sw.Stop();
      return (rés, sw.ElapsedMilliseconds);
   }

   static int CompterSiMT(short[] tab, Func<short, bool> pred, int nthrs)
   {
      var thrs = new Thread[nthrs-1]; // initialisés à null en C#
      var nimpairs = new int[nthrs]; // initialisés à 0 en C#
      int tailleBloc = tab.Length / nthrs;

      for(int i = 0; i < thrs.Length; ++i)
      {
         int monIndice = i;
         int début = i * tailleBloc; // inclus
         int fin = (i + 1) * tailleBloc; // exclue
         thrs[i] = new Thread(() =>
         {
            int m = 0;
            for (; début != fin; ++début)
               if (pred(tab[début]))
                  ++m;
            nimpairs[monIndice] = m;
            //for (; début != fin; ++début)
            //   if (pred(tab[début]))
            //      ++nimpairs[monIndice];
         });
      }
      foreach (var th in thrs)
         th.Start();
      {
         int début = (nthrs - 1) * tailleBloc; // inclus
         int fin = tab.Length; // exclue
         int m = 0;
         for (; début != fin; ++début)
            if (pred(tab[début]))
               ++m;
         nimpairs[nthrs - 1] = m;
         //for (; début != fin; ++début)
         //   if (pred(tab[début]))
         //      ++nimpairs[nthrs - 1];
      }
      foreach (var th in thrs)
         th.Join();
      int cumul = 0;
      foreach (int n in nimpairs)
         cumul += n;
      return cumul;
   }

   static void Main()
   {
      const int N = 25_000;
      var tab = CréerTableau(N * N);
      for(int i = 1; i <= 16; ++i)
      {
         var (r0, dt0) = Tester(() => CompterSiMT(tab, n => n % 2 != 0, i));
         if(i < 10) // bof, mais je ne me souviens plus du code de formatage...
            Console.WriteLine($"Compté {r0} impairs avec  {i} fils en {dt0} ms");
         else
            Console.WriteLine($"Compté {r0} impairs avec {i} fils en {dt0} ms");
      }
   }
}

Pour les zones de transit, nous avons fait un pipeline très naïf, particulièrement pour ce qui est de l'arrêt du traitement. On y reviendra

28 oct.

S16

Au menu :

En réponse à une question du public, voici ce que ça donnerait pour EX01.0 :

   // ...
   class ZoneVideException : Exception { }
   class ZoneTransit<T>
   {
      List<T> Data { get; } = new List<T>();
      object mutex = new object();
      public void Ajouter(List<T> elems)
      {
         lock (mutex)
            Data.AddRange(elems);
      }
      public List<T> Extraire()
      {
         var temp = new List<T>();
         lock (mutex)
         {
            temp.AddRange(Data);
            Data.Clear();
         }
         return temp;
      }
      // EX01.0 : est-ce une bonne idée?
      public void Ajouter(T elem)
      {
         lock (mutex)
            Data.Add(elem);
      }
      public T ExtraireUn()
      {
         lock (mutex)
         {
            if (Data.Count == 0)
               throw new ZoneVideException();
            T elem = Data[0];
            Data.RemoveAt(0);
            return elem;
         }
      }
      public int Count
      {
         get
         {
            lock (mutex)
               return Data.Count;
         }
      }
      public bool EstVide
      {
         get => Count == 0;
      }
   }

   static (T rés, long dt) Tester<T>(Func<T> f)
   {
      var sw = new Stopwatch();
      sw.Start();
      T rés = f();
      sw.Stop();
      return (rés, sw.ElapsedMilliseconds);
   }
   static void Main()
   {
      const int N = 1_000_000;
      {
         var zt = new ZoneTransit<string>();
         string msg = "J'aime mon prof";
         var (r0, dt0) = Tester(() =>
         {
            for (int i = 0; i != N; ++i)
               zt.Ajouter(msg);
            return zt;
         });
         Console.WriteLine($"Ajout un à un : {dt0} ms");
      }
      {
         var zt = new ZoneTransit<string>();
         string msg = "J'aime mon prof";
         var (r0, dt0) = Tester(() =>
         {
            var lst = new List<string>();
            for (int i = 0; i != N; ++i)
               lst.Add(msg);
            zt.Ajouter(lst);
            return zt;
         });
         Console.WriteLine($"Ajout en bloc : {dt0} ms");
      }
   }
// ...

N'oubliez pas, si vous testez le tout, de le faire en mode Release (avec optimisation), pas en mode Debug (sans optimisation), sinon les chiffres que vous obtiendrez ne seront pas crédibles.

2 nov.

S17

Au menu :

  • Présentation du TP02a
  • Disponibilité et soutien

4 nov.

S18

Au menu :

  • Q03
  • Travail sur TP02a avec soutien de votre chic prof

9 nov.

S19

Nous n'aurons pas de séance aujourd'hui, car je serai en plénière pour WG21 (le comité de standardisation de C++) et que cela avalera la totalité de ma journée. Détails sur ../../../Sujets/Orthogonal/wg21-2020-Zoom.html

11 nov.

S20

Au menu :

  • Travail sur TP02a avec soutien de votre chic prof

16 nov.

S21

Au menu :

18 nov.

S22

Au menu :

23 nov.

S23

Au menu :

25 nov.

S24

Au menu :

  • Q05
  • Travail sur avec TP02b soutien de votre chic prof

30 nov.

S25

Au menu :

  • Présentation de la PFI
  • Travail sur la PFI
  • Travail sur avec TP02b soutien de votre chic prof

2 déc.

S26

Au menu :

  • Q06
  • Travail sur la PFI
  • Travail sur avec TP02b soutien de votre chic prof

Il y a eu des questions qui ont mené à des exemples. Pour celui de la course entre fonctions asynchrones :

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
   static async Task<string> Coureur(int n, Random r, CancellationToken jeton)
   {
      await Task.Delay(r.Next(200, 400), jeton);
      return $"Je suis le coureur {n}";
   }
   static void Main()
   {
      const int N = 5;
      Random r = new Random();
      var coureurs = new List<Task<string>>();
      var src = new CancellationTokenSource();
      var jeton = src.Token;
      for (int i = 0; i != N; ++i)
         coureurs.Add(Coureur(i, r, jeton));
      var lequel = Task.WaitAny(coureurs.ToArray());
      src.Cancel(); // on annule les autres
      Console.WriteLine($"Résultat : {coureurs[lequel].Result}");
   }
}

... et pour celui du policier qui crie quand on approche d'un poteau :

using System;
using System.Collections.Generic;
class Program
{
   interface ISuiveux
   {
      void Réagir(int nouvPosition);
   }
   class Avanceur
   {
      List<ISuiveux> Abonnés { get; } = new List<ISuiveux>();
      public int Pos { get; private set; } = 0;
      public void Abonner(ISuiveux suiveux)
      {
         Abonnés.Add(suiveux);
      }
      public void Bouger()
      {
         Pos++;
         foreach (var p in Abonnés)
            p.Réagir(Pos);
      }
   }
   class Poteau
   {
      public int Pos { get; }
      public Poteau(int pos, Policier popo)
      {
         Pos = pos;
         popo.Ajouter(p0 => Math.Abs(p0 - Pos) <= 2);
      }
   }
   class Policier : ISuiveux
   {
      List<Func<int, bool>> Règles { get; } = new List<Func<int, bool>>();
      public void Ajouter(Func<int,bool> règle)
      {
         Règles.Add(règle);
      }
      public void Réagir(int nouvPosition)
      {
         foreach (var r in Règles)
            if (r(nouvPosition))
               Console.WriteLine($"ATTENTION {nouvPosition}!!!!");
      }
   }
   static void Main()
   {
      Avanceur a = new Avanceur();
      Policier popo = new Policier();
      Poteau p = new Poteau(10, popo);
      a.Abonner(popo);
      for (int i = 0; i != 15; ++i)
      {
         Console.WriteLine("Déplacement de l'avanceur...");
         a.Bouger();
      }
   }
}

7 déc.

S27

Au menu :

  • Travail sur la PFI

9 déc.

 

Journée d'examen de français / formation générale (cours suspendus)

14 déc.

S28

Au menu :

  • Travail sur la PFI

16 déc.

 

Épreuve uniforme ministérielle en français (cours suspendus)

21 déc.

S29

Attention : cours selon l'horaire du mercredi

À remettre :

  • La PFI de la session A2020

Chic examen final

Petits coups de pouces

Vous trouverez ici quelques documents, la plupart petits, qui peuvent vous donner un petit coup de pouce occasionnel.

Comment accéder à du code .NET à partir d'un client C++ natif.

Vous trouverez aussi des exemples de code C# dans la section Divers – C# du site, mais notez que je n'ai pas nécessairement harmonisé ces exemples (écrits pour des cours plus avancés, sous forme de survols) aux standards de programmation appliqués dans le présent cours. À lire avec prudence et discrimination, donc.

Consignes des travaux pratiques

Les consignes des travaux pratiques suivent.

Consignes Détails supplémentaires

TP00

Un programme de test possible est proposé ici : TP00-code-test-simpliste.html

TP01

Un démonstrateur de ce que pourrait être le programme final avec la carte CarteTest.txt serait : Thésée.exe

Pour tester ce programme, déposez les deux fichiers dans le même dossier, puis déplacez-vous dans ce dossier à la ligne de commande. Enfin, tapez :

Thésée CarteTest.txt

... et vous pourrez profiter de l'expérience.

TP02a

Un démonstrateur de ce que pourrait être le programme final avec la carte CarteTest.txt serait : ThéséeMT.exe

Pour tester ce programme, déposez les deux fichiers dans le même dossier, puis déplacez-vous dans ce dossier à la ligne de commande. Enfin, tapez :

ThéséeMT CarteTest.txt

... et vous pourrez profiter de l'expérience.

Notez que j'ai mis une version monoprogrammée fonctionnelle du TP01 à votre disposition sur Colnet, au cas où vous choisiriez de l'utiliser comme base de travail pour TP02a. Sentez-vous bien à l'aise de la prendre ou de ne pas la prendre comme base pour TP02a; je vous l'offre au cas où vous auriez eu des ennuis, mais je ne vous l'impose pas du tout.

TP02b

Un démonstrateur de ce que pourrait être le programme final avec la carte CarteTest.txt serait : ThéséeAsync.exe

Pour tester ce programme, déposez les deux fichiers dans le même dossier, puis déplacez-vous dans ce dossier à la ligne de commande. Enfin, tapez :

ThéséeAsync CarteTest.txt

... et vous pourrez profiter de l'expérience.

Notez que j'ai mis une version monoprogrammée fonctionnelle du TP01 à votre disposition sur Colnet, au cas où vous choisiriez de l'utiliser comme base de travail pour TP02b

PFI

Un démonstrateur de ce que pourrait être le programme final avec la carte CarteTestPFI.txt serait : ThéséePFI.exe (il vous faudra aussi IADirectrice.dll dans le même dossier)

Pour tester ce programme, déposez les trois fichiers dans le même dossier, puis déplacez-vous dans ce dossier à la ligne de commande. Enfin, tapez :

ThéséePFI CarteTestPFI.txt

... et vous pourrez profiter de l'expérience.

Solutionnaires

Quelques solutionnaires suivent.

Travail

Exercices sur la généricité

Exercices sur la multiprogrammation

Exercices sur les opérateurs

Exercices sur les opérations asynchrones

En espérant que ça vous aide à organiser vos idées!


Valid XHTML 1.0 Transitional

CSS Valide !