Exercices
Consignes
- Activer la null safety
- Ne pas utiliser les fonctions de tri de .Net
Collections
Partie 1
Utiliser foreach
si besoin (et ne pas utiliser LINQ: Select, etc.):
- Créer une fonction qui prend une liste d'entiers en argument et affiche uniquement les entiers pairs.
- Créer une fonction qui prend une liste d'entiers en argument et retourne la liste des entiers pairs.
- Créer une fonction qui prend une chaîne de caractères en argument (string) et retourne la liste de ses consonnes (pour rappel, les voyelles sont a, i, u, e, o et y).
- Créer une fonction qui prend une liste de chaînes de caractères et retourne la liste des longueurs de chaque chaîne.
- Par exemple:
["hello", "C#"]
retourne[5, 2]
- Par exemple:
- Définir un
record
Person
avec les propriétésName
etAge
. Créer une liste de personnes et:- afficher les personnes dont l'âge est supérieur à 18 ans.
- afficher les personnes dont le nom commence par la lettre 'A'.
- Créer une fonction qui change le nom en Camel case de chaque personne.
- Par exemple:
Person("john doe", 20)
devientPerson("John Doe", 20)
- Par exemple:
- Créer un fonction qui donne l'âge moyen des personnes.
Partie 2
Utiliser LINQ pour la partie algorithmie. Utiliser foreach
uniquement pour l'affichage.
- Refaire les exos de la partie 1 avec LINQ.
- Créer une fonction qui prend un entier n. La fonction génère une liste de n entiers aléatoires entre 0 et 100 et affiche le min, le max, la somme et la moyenne.
- Par exemple: si
n = 5
génère le tableau[10, 20, 30, 40, 50]
, affichermin: 10, max: 50, sum: 150, avg: 30
- Par exemple: si
- Créer une fonction qui prend une liste de chaînes de caractères et retourne la liste des chaînes de caractères triées par ordre croissant de longueur. (💡 utiliser
OrderBy((s) => s.Length)
).- Par exemple:
["hello", "C#", "world"]
retourne["C#", "hello", "world"]
- Par exemple:
- Créer une fonction qui prend une liste de chaînes de caractères et retourne le nombre de caractères total de toutes les chaînes.
- Par exemple:
["hello", "C#", "world"]
retourne12
- Par exemple:
- Créer une fonction qui prend une liste de chaînes de caractères et retourne le nombre de mots qui ont une longueur supérieure à 3.
- Par exemple:
["hello", "C#", "world"]
retourne2
- Par exemple:
- Définir un
record
Ninja
avec les propriétésName
,Hp
etIsHokage
. Créer une liste de ninjas et:- Afficher les noms des Hokage.
- Par exemple:
Ninja("Naruto", 150, true)
etNinja("Sasuke", 120, false)
retourneNaruto
- Par exemple:
- Afficher le nombre de ninjas qui ont plus de 100 points de vie.
- Par exemple:
Ninja("Naruto", 150, true)
etNinja("Sasuke", 120, false)
retourne2
- Par exemple:
- Afficher le nom ninja qui a le plus de points de vie.
- Par exemple:
Ninja("Naruto", 150, true)
etNinja("Sasuke", 120, false)
retourneNaruto
- Par exemple:
- Afficher les noms des Hokage.
Corrections
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text;
void RunQ1()
{
void ShowEvenNumbers(List<int> numbers)
{
var evenNumbers = from n in numbers where n % 2 == 0 select n;
Console.WriteLine(string.Join(",", evenNumbers));
}
Console.WriteLine("Exercise 1");
ShowEvenNumbers([1, 2, 3, 4, 5, 6, 7]);
// Enumerable.Range equivalent of Python range with less features
ShowEvenNumbers(Enumerable.Range(-10, 20).ToList());
}
void RunQ2()
{
// Avec la method syntax
List<int> GetEvenNumbers(List<int> numbers)
{
var evenNumbers = numbers.Where(n => n % 2 == 0);
return evenNumbers.ToList();
}
// Avec la query syntax et avec un single statement function
List<int> GetEvenNumbers2(List<int> numbers) =>
(from n in numbers where n % 2 == 0 select n).ToList();
List<int> numbers = Enumerable.Range(1, 10).ToList();
Console.WriteLine("Exercise 2");
Console.WriteLine(string.Join(",", GetEvenNumbers(numbers)));
Console.WriteLine(string.Join(",", GetEvenNumbers2(numbers)));
}
void RunQ3()
{
string GetConsonants(string input)
{
string lowerCased = input.ToLower();
var consonants = lowerCased.Where(c => !"aeiuyo".Contains(c));
return string.Join("", consonants);
}
string GetConsonants2(string input) =>
string.Join("", input.ToLower().Where(c => !"aeiuyo".Contains(c)));
Console.WriteLine("Exercise 3");
Console.WriteLine(GetConsonants("Hello"));
Console.WriteLine(GetConsonants("BBBBCCCC"));
Console.WriteLine(GetConsonants("aeae"));
Console.WriteLine(GetConsonants2("Hello"));
Console.WriteLine(GetConsonants2("BBBBCCCC"));
Console.WriteLine(GetConsonants2("aeae"));
}
void RunQ4()
{
List<int> GetLengths(List<string> texts) =>
(from text in texts select text.Length).ToList();
Console.WriteLine("Exercise 4");
Console.WriteLine(string.Join(", ", GetLengths(["I", "Love", "C#"])));
Console.WriteLine(string.Join(", ", GetLengths(["LINQ", "Rocks"])));
}
void RunQ5()
{
string ToCamelCaseName(string name)
{
var transformed = name.Select((c, index) => index == 0 || name[index - 1] == ' ' ? char.ToUpper(c) : c);
return string.Join("", transformed);
}
void PrintResults(List<Person> persons)
{
Console.WriteLine($"input list: {string.Join(",", persons)}");
var olderThan18 = persons.Where(p => p.Age > 18);
Console.WriteLine($"Older than 18: {string.Join(", ", olderThan18)}");
var startWithAPersons = from p in persons where p.Name.Length > 1 && p.Name[0] == 'A' select p;
Console.WriteLine($"Start with A: {string.Join(", ", startWithAPersons)}");
var camelCased = persons.Select(p => new Person(ToCamelCaseName(p.Name), p.Age));
Console.WriteLine($"Camel cased: {string.Join(", ", camelCased)}");
}
List<Person> persons = [new("Kakashi", 50), new("Arata", 23), new("j bap", 2)];
PrintResults(persons);
Random rng = new();
List<Person> randomPersons = Enumerable.Range(1, 5)
.Select(
i => new Person($"person number {i}", rng.Next(10, 30))
).ToList();
PrintResults(randomPersons);
}
RunQ1();
RunQ2();
RunQ3();
RunQ4();
RunQ5();
record Person(string Name, int Age);
Fichiers
- Utiliser les
StreamReader
et / ouStreamWriter
pour lire et un fichier et:- Afficher le nombre de caractères de chaque ligne de ce fichier
- Génère un fichier qui ajoute un point à la fin de chaque ligne du fichier d'origine si elle n'est pas déjà présente
- Génère un fichier qui contient la ligne qui a le plus de caractères dans le fichier lu
- Génère un fichier qui contient les lignes du fichier lu triés par ordre croissant le nombre de caractères de la ligne
- Génère un fichier qui contient les lignes du fichier lu triés par ordre croissant du dictionnaire
- Utiliser un
StreamWriter
pour écrire dans un fichier le contenu d'une chaîne de caractères au format pyramidal. Par exemple "Je-fais-des-exos-de-C#" donne le fichier (le dernier caractère sera ignoré car il ne permet pas de faire une pyramide): - Définir votre propose classe de journalisation (
Logger
) qui va servir à écrire des logs dans un fichier.- La classe prend en argument du constructeur le nom du fichier de logs
- La classe propose les méthodes:
Info(String message)
etWarn(String message)
. Chacune des méthodes ajoute une ligne au fichier avec le format:- Si c'est une Info:
{date et heure actuelle} ℹ️ {message}
- Si c'est un Warn:
{date et heure actuelle} ⚠️ {message}
- Si c'est une Info:
- ⚠️: Attention à bien fermer le fichier une fois l'écriture du log faite (pour le libérer)
- Créer une instance de la classe
Logger
et ajouter quelques logs - Ajouter les méthodes
Error(String message)
etDebug(String message)
avec un format adapté et basé sur le même principe que les méthodes définies plus haut. - Définir une méthode
ShowAllWarnings()
qui affiche tous les logs de typeWarn
présents dans le fichier de log. - Est-ce que vous voyez des inconvénients / contraintes avec cette méthode de journalisation ?
- Faire le problème 1 de advent of code 2023 en chargeant les données d'entrée depuis un fichier.
- Par exemple pour l'exercice 1 du problème, créer à la main (avec vscode ou l'explorateur) un fichier
input1.txt
avec le contenu ci-dessous et le lire avec un StreamReader pour résoudre le problème.
- Par exemple pour l'exercice 1 du problème, créer à la main (avec vscode ou l'explorateur) un fichier
Corrections
static void PrintCountPerLine(string filePath)
{
using StreamReader sr = new(filePath);
string? line = sr.ReadLine();
while (line != null)
{
Console.WriteLine(line.Length);
line = sr.ReadLine();
}
}
static void AddDotIfNotPresent(string filePath)
{
using StreamReader sr = new(filePath);
using StreamWriter sw = new("dotted_file.txt");
string? line = sr.ReadLine();
while (line != null)
{
if (!line.EndsWith('.'))
{
line += '.'; // autre façon: line = $"{line}.";
}
sw.WriteLine(line);
line = sr.ReadLine();
}
}
static void WriteLongestLine(string filePath)
{
using StreamReader sr = new(filePath);
string? line = sr.ReadLine();
string? longestLine = line;
while (line != null)
{
line = sr.ReadLine();
if (longestLine?.Length < line?.Length)
{
longestLine = line;
}
}
if (longestLine != null)
{
using StreamWriter sw = new("longest_line.txt");
sw.WriteLine(longestLine);
}
}
string filePath = "input_file.txt";
PrintCountPerLine(filePath);
AddDotIfNotPresent(filePath);
WriteLongestLine(filePath);
Série 2 (programmation asynchrone)
En C#, la méthode recommandée pour exécuter des traitements asynchrones (qui sont mis en oeuvre habituellement avec les threads et les process) consiste à utiliser “Task.Run(() => { // traitement async })”. On dit que c’est une programmation asynchrone basée sur les tâches.
- Créer deux tâches asynchrones (en faisant deux Task.Run)
- La première affiche un valeur qui s’incrémente de 1 à 1000 (une boucle for qui affiche i à chaque itération)
- La deuxième affiche un valeur qui va de -1 à -1000 (une boucle for de -1 à -1000 avec un writeline)
- Pour laisser le temps aux tâches concurrentes de finir avant la fin du thread principal, ajouter un await Task.Delay(1000); à la fin de la tâche principale
- Exécuter le programme plusieurs fois, que constatez vous ?
- Afficher
finished 1
juste à la fin de la première tâche (sans utiliserawait
etContinueWith
) - -> solution: utiliser une callback sous forme d’une fonction passée en paramètre
- En utilisant
ContinueWith
afficherfinished 1
juste après la fin de la première tâche - Remplacer chaque
Task.Run
parawait Task.Run
. Que constatez-vous ? - En utilisant
await
, comment afficher “finished 2” dès la fin de la deuxième tâche ?
- Dans la première tâche, ajouter une instruction ‘return “tartatin”;’ après la boucle for. Ensuite remplacer le premier
await Task.Run
par un varresult = await Task.Run
.- Quel est le type et la valeur de result ?
- Enlever await, c’est à dire remplacer
var result = await Task.Run
parvar result = Task.Run
- Quel est le type et la valeur de result ?
- A quoi sert
await
? Quel est sa relation avec le typeTask
?