• Aucun résultat trouvé

IFT 1179 : Programmation en C#

N/A
N/A
Protected

Academic year: 2022

Partager "IFT 1179 : Programmation en C#"

Copied!
19
0
0

Texte intégral

(1)

IFT 1179 : Programmation en C#

A) System.Array :

On a déjà travaillé avec les tableaux à un seul indice. En C#, le type System.Array est considéré comme une classe parente de tous les types tableaux vus jusqu’à date.

L’idée fondamentale est de permettre aux tableaux de profiter des méthodes toutes faites dans System.Array :

Méthodes «static(s)» :

BinarySearch() Recherche binaire (dichotomique) dans un tableau à un seul indice qui est déjà trié.

Clear() Mettre le rang (rank) à zéro ou la référence nulle.

Copy() Copier une partie d’un tableau à un autre tableau.

IndexOf() Recherche séquentielle afin de retourner l’indice de la première occurrence

rencontrée dans le tableau ou une partie d’un tableau.

LastIndexOf() Recherche séquentielle afin de retourner l’indice de la dernière occurrence

rencontrée dans le tableau ou une partie d’un tableau.

Reverse() Renverser l’ordre des éléments

(2)

Méthodes publics appliquées sur les objets :

CopyTo() Copier tous les éléments d’un tableau à une seule dimension à partir d’un indice donné.

GetLength() Retourne la longueur etc

Exemple 1 (cas de tableaux assez « simples ») :

/* Fichier Array1.cs

* Exemple de tri et de recherche avec System.Array *

* Cas des vrais tableaux d'objets : à venir plus tard *

* Par LVN pour IFT 1179 *

*/

using System;

class Array1 {

static void Afficher(string[] tableau, string message) {

Console.WriteLine("Les journees de la semaine " + message + " : ");

for (int i = 0; i < tableau.Length; i++)

Console.WriteLine("{0, 5:D} {1, 15}", i, tableau[i]);

Console.WriteLine();

}

static void Demo2() {

Console.WriteLine("\nDemo 2 : Tableau des string(s):\n");

string[] journee = {"Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"};

Afficher(journee, "avant le tri");

Array.Sort(journee);

Afficher(journee, "apres le tri");

int indice = Array.BinarySearch(journee, "Samedi");

Console.WriteLine("On trouve Samedi a l'indice : " + indice);

indice = Array.BinarySearch(journee, "Lunch");

Console.WriteLine("L'indice de Lunch est : " + indice);

Console.WriteLine("L'indice de Mars est : " +

(3)

Array.BinarySearch(journee, "Mars"));

Console.WriteLine();

}

static void Afficher(double[] tableau, string message) {

Console.WriteLine("Les poids " + message + " : ");

for (int i = 0; i < tableau.Length; i++)

Console.WriteLine("{0, 5:D} {1, 15:F2}", i, tableau[i]);

Console.WriteLine();

}

static void Demo1() {

Console.WriteLine("Demo 1 : Tableau des double(s):\n");

double[] poids = { 123.45, 65.2, 67.9, 98.4, 75.2, 90.5 };

Afficher(poids, "avant le tri");

Array.Sort(poids);

Afficher(poids, "apres le tri");

int indice = Array.BinarySearch(poids, 67.9);

Console.WriteLine("On trouve ce poids 67.9 a l'indice : " + indice);

indice = Array.BinarySearch(poids, 567.89);

Console.WriteLine("L'indice de 567.89 est : " + indice);

Console.WriteLine();

}

static void Main(string[] args) {

Demo1();

Demo2();

} }

/* Execution:

Demo 1 : Tableau des double(s):

Les poids avant le tri : 0 123,45 1 65,20 2 67,90 3 98,40 4 75,20 5 90,50

Les poids apres le tri : 0 65,20 1 67,90 2 75,20 3 90,50 4 98,40 5 123,45

(4)

On trouve ce poids 67.9 a l'indice : 1 L'indice de 567.89 est : -7

Demo 2 : Tableau des string(s):

Les journees de la semaine avant le tri : 0 Lundi

1 Mardi 2 Mercredi 3 Jeudi 4 Vendredi 5 Samedi 6 Dimanche

Les journees de la semaine apres le tri : 0 Dimanche

1 Jeudi 2 Lundi 3 Mardi 4 Mercredi 5 Samedi 6 Vendredi

On trouve Samedi a l'indice : 5 L'indice de Lunch est : -3 L'indice de Mars est : -5

Press any key to continue

*/

Exemple 2 (cas de tableau d’objets (ici des stations) :

/* Fichier Array2.cs (deuxième exemple sur System.Array) * Cas d'un tableau de stations de métro

* redéfinition de Equals et la recherche séquentielle *

*/

using System;

using System.IO;

class Station {

private string nom; // nom de la station private int rang2003, // rang en 2003

freq2004; // nb. de passagers aux tourniquets en 2004

// un constructeur possible

public Station(string nom, int rang, int freq2004) {

this.nom = nom;

rang2003 = rang;

this.freq2004 = freq2004;

}

(5)

// un autre constructeur possible public Station(string chaine)

{

char[] separateurs = new char[] {'(', ')'};

string[] infosMetro = chaine.Split(separateurs, 3);

nom = infosMetro[0];

rang2003 = int.Parse(infosMetro[1]);

freq2004 = int.Parse(infosMetro[2]);

}

// un constructeur sans paramètre public Station()

{ }

// afficher les infos d'une station public void Afficher(string message) {

Console.WriteLine(message + "{0, -20:S} {1,4:D} {2, 12:N0}", nom, rang2003, freq2004 );

}

// propriétés : public int Rang {

get { return rang2003; } set { rang2003 = value; } }

public string Nom {

get { return nom; }

set { nom = value.ToUpper(); } }

public int Freq {

get { return freq2004; } set { freq2004 = value; } }

public override bool Equals (object obj) { Station autre = (Station) obj;

return nom.ToUpper().Equals(autre.nom.ToUpper());

}

}

class Array2 {

static void LireRemplir(string nomFichier, Station[] stat, out int n) {

n = 0; // compteur du nombre de dtations lues

StreamReader aLire = File.OpenText(nomFichier);

(6)

string ligneLue = null;

while ( (ligneLue = aLire.ReadLine()) != null) stat[n++] = new Station(ligneLue);

aLire.Close();

Console.WriteLine("\nOn vient de creer un tableau de " + n + " stations");

}

static void Main(string[] args) {

const int MAX_STAT = 70; // au maximum, 70 stations de métro Station[] stat = new Station[MAX_STAT];

int nbStat;

LireRemplir("R:\\metro.txt", stat, out nbStat);

int indice = Array.IndexOf(stat,

new Station("Plamondon", 0, 0));

Console.WriteLine("Indice de Plamondon : " + indice);

indice = Array.LastIndexOf(stat,

new Station("Plamondon", 0, 0));

Console.WriteLine("Indice de Plamondon : " + indice);

indice = Array.IndexOf(stat, new Station("LAVAL", 0, 0));

Console.WriteLine("Indice de Laval : " + indice);

}

}

/* Exécution:

On vient de creer un tableau de 65 stations Indice de Plamondon : 23

Indice de Plamondon : 23 Indice de Laval : -1 Press any key to continue

*/

/* Fichier Array3.cs *

* Par LVN pour IFT 1179 *

*/

using System;

class Array3 {

static void Afficher(double[] tableau, string message) {

Console.WriteLine("Les poids " + message + " : ");

(7)

for (int i = 0; i < tableau.Length; i++)

Console.WriteLine("{0, 5:D} {1, 15:F2}", i, tableau[i]);

Console.WriteLine();

}

static void Main(string[] args) {

double[] poids = { 123.45, 65.2, 67.9, 98.4, 75.2, 90.5 };

Afficher(poids, "au debut");

double[] copie = new Double[10];

Array.Copy(poids, 0, copie, 0, poids.Length);

copie[poids.Length] = 66.6;

copie[poids.Length+1] = 77.7;

copie[8] = 210.0;

copie[9] = 88.8;

Afficher(copie, "apres cette copie et quelques ajouts");

Array.Reverse(copie);

Afficher(copie, "apres avoir mis a l'envers ses elements");

Console.WriteLine();

Console.WriteLine(poids.GetLength(0));

Console.WriteLine(copie.GetLength(0));

} }

/* Execution:

Les poids au debut : 0 123,45 1 65,20 2 67,90 3 98,40 4 75,20 5 90,50

Les poids apres cette copie et quelques ajouts : 0 123,45

1 65,20 2 67,90 3 98,40 4 75,20 5 90,50 6 66,60 7 77,70 8 210,00 9 88,80

Les poids apres avoir mis a l'envers ses elements :

(8)

0 88,80 1 210,00 2 77,70 3 66,60 4 90,50 5 75,20 6 98,40 7 67,90 8 65,20 9 123,45

6 10

Press any key to continue

*/

Exemple 3 (quelques autres méthodes de Array):

/* Fichier Array3.cs *

* Par LVN pour IFT 1179 *

*/

using System;

class Array3 {

static void Afficher(double[] tableau, string message) {

Console.WriteLine("Les poids " + message + " : ");

for (int i = 0; i < tableau.Length; i++)

Console.WriteLine("{0, 5:D} {1, 15:F2}", i, tableau[i]);

Console.WriteLine();

}

static void Main(string[] args) {

double[] poids = { 123.45, 65.2, 67.9, 98.4, 75.2, 90.5 };

Afficher(poids, "au debut");

double[] copie = new Double[10];

Array.Copy(poids, 0, copie, 0, poids.Length);

copie[poids.Length] = 66.6;

copie[poids.Length+1] = 77.7;

copie[8] = 210.0;

copie[9] = 88.8;

Afficher(copie, "apres cette copie et quelques ajouts");

Array.Reverse(copie);

(9)

Afficher(copie, "apres avoir mis a l'envers ses elements");

Console.WriteLine();

Console.WriteLine(poids.GetLength(0));

Console.WriteLine(copie.GetLength(0));

} }

/* Execution:

Les poids au debut : 0 123,45 1 65,20 2 67,90 3 98,40 4 75,20 5 90,50

Les poids apres cette copie et quelques ajouts : 0 123,45

1 65,20 2 67,90 3 98,40 4 75,20 5 90,50 6 66,60 7 77,70 8 210,00 9 88,80

Les poids apres avoir mis a l'envers ses elements : 0 88,80

1 210,00 2 77,70 3 66,60 4 90,50 5 75,20 6 98,40 7 67,90 8 65,20 9 123,45

6 10

Press any key to continue

*/

(10)

B) Surcharge des opérateurs :

Le Java ne permet pas la surcharge des opérateurs.

Le C#, comme le C++, permet cette surcharge dont le but théorique est d’utiliser certains opérateurs comme +, *,

<, >, etc ... entre les objets.

En pratique, on aimerait étendre le codage des

algorithmes de base (le tri, la recherche, ...) qui utilise des opérateurs traditionnels dans le cas des objets.

Veuillez noter que C# utilise des méthodes static pour surcharger des opérateurs. De plus, les opérateurs de comparaison

(relationnels) sont surchargés en paire :

Surcharger == et !=

Surcharger < et >

Surcharger <= et >=

Dans le cas de surcharger l’opérateur ==, le C# attend qu’on redéfinit aussi la méthode Equals.

Le C++ utilise la surcharge des opérateurs < (pour le tri avec des structures de données avancées), == (pour la recherche).

Ce n’est pas du tout le cas de C# qui utilise Equals pour la recherche séquentielle, l’implémentation de CompareTo pour

Le tri et la recherche dichotomique (on s’en parlera plus tard dans le cours).

Exemple 1 (cas un peu théorique) :

Dans cet exemple, un vecteur est représenté par ses trois composants x, y et z de type réels. On réalisera la

surcharge des opérateurs suivants :

L’addition de 2 vecteurs est un vecteur :

<1.5, 2.7, 3.0>

+

<1.4, 3.3, 5.2> est le vecteur <2.9, 6.0, 8.2>

Le produit scalaire entre deux vecteurs est un scalaire (1 réel) :

<1.5, 2.0, 3.0> * <3.0, 1.8, 2.1> est 1.5 *3 + 2.0 * 1.6 + 3 * 2.1 qui est 4.5 + 3.2 + 6.3 = 13.8

Le produit entre un vecteur et un scalaire est un vecteur ( on multiplie chaque composant par le scalaire ). Comme le symbole * a été utilisé, on peut inventer un autre symbole, par exemple % pour représenter ce produit.

(11)

Note : attention au saut de ligne de Word :

/* Fichier Operateurs1.cs (1er exemple sur la surcharge des opérateurs) *

* IFT 1179, mercredi 2 novembre */

using System;

class Vecteur {

private double x, y, z;

public Vecteur(double x, double y, double z) {

this.x = x;

this.y = y;

this.z = z;

}

// une utilisation possible de this (appel un autre constructeur) public Vecteur() : this(0, 0, 0)

{ }

// cette définition est mathématique (comme la longueur d'un // vecteur)

public double Norme() {

return Math.Sqrt(x*x + y*y + z*z);

}

// redéfinition de ToString() public override string ToString() {

return string.Format("<x = {0, 6:F2}, y = {1, 6:F2}, z = {2, 6:F2}, norme : {3, 6:F2}>",

x, y, z, Norme());

}

// surcharger l'opérateur +

public static Vecteur operator + (Vecteur a, Vecteur b) {

return new Vecteur(a.x + b.x, a.y+ b.y, a.z + b.z);

}

// surcharger l'opérateur * (produit scalaire)

public static double operator * (Vecteur a, Vecteur b) {

return a.x * b.x + a.y * b.y + a.z * b.z;

}

(12)

// un autre modèle vs la surcharge de +

public static Vecteur operator % (double m, Vecteur a) {

Vecteur produit = new Vecteur();

produit.x = m* a.x;

produit.y = m* a.y;

produit.z = m* a.z;

return produit;

}

// réutiliser le codage pour surcharger %

public static Vecteur operator % ( Vecteur a, double m) {

return m % a;

}

// surcharge (par paire) des opérateurs de comparaison public static bool operator < (Vecteur a, Vecteur b) {

return a.Norme() < b.Norme();

}

public static bool operator > (Vecteur a, Vecteur b) {

return a.Norme() > b.Norme();

} }

class Operateurs1 {

static void Main(string[] args) {

Vecteur v1 = new Vecteur(3, 4.6, 1.2), v2 = new Vecteur(1.8, 3.0, 5.1);

Console.WriteLine("Infos du vecteur v1 : " + v1);

Console.WriteLine("Infos du vecteur v2 : " + v2);

Console.WriteLine("Infos du vecteur v1+v2 : " + (v1+v2) );

Console.WriteLine("Produit scalaire entre v1 et v2 : " + (v1 * v2) );

Console.WriteLine("Produit avec un scalaire : " + (2.5 % v2));

Console.WriteLine("Produit avec un scalaire : " + (v2 % 2.5));

Console.WriteLine("v1 < v2 vaut : " + (v1 < v2) );

} }

/* Exécution:

Infos du vecteur v1 : <x = 3,00, y = 4,60, z = 1,20, norme : 5,62>

Infos du vecteur v2 : <x = 1,80, y = 3,00, z = 5,10, norme : 6,18>

(13)

Infos du vecteur v1+v2 : <x = 4,80, y = 7,60, z = 6,30, norme : 10,98>

Produit scalaire entre v1 et v2 : 25,32

Produit avec un scalaire : <x = 4,50, y = 7,50, z = 12,75, norme : 15,46>

Produit avec un scalaire : <x = 4,50, y = 7,50, z = 12,75, norme : 15,46>

v1 < v2 vaut : True

Press any key to continue

*/

Exemple 2 (cas pratique : le tri rapide des stations) :

On a déjà programmé le tri rapide d’un tableau des entiers.

Peut-on adapter le codage de ce tri dans le cas des stations de métro ?

- Oui, il suffit d’observer des opérateurs utilisés dans le cas du tableau d’entiers et de surcharger ces

opérateurs du cas des stations (à parler en classe).

/* Fichier Operateurs2.cs

* On surcharge certains opérateurs pour

* programmer le TRI RAPIDE des stations de métro *

* */

using System;

using System.IO;

class Station {

private string nom; // nom de la station private int rang2003, // rang en 2003

freq2004; // nb. de passagers aux tourniquets en 2004

// un constructeur possible

public Station(string nom, int rang, int freq2004) {

this.nom = nom;

rang2003 = rang;

this.freq2004 = freq2004;

}

// un autre constructeur possible public Station(string chaine)

{

char[] separateurs = new char[] {'(', ')'};

string[] infosMetro = chaine.Split(separateurs, 3);

nom = infosMetro[0];

rang2003 = int.Parse(infosMetro[1]);

freq2004 = int.Parse(infosMetro[2]);

(14)

}

// un constructeur sans paramètre public Station()

{ }

// afficher les infos d'une station public void Afficher(string message) {

Console.WriteLine(message + "{0, -35:S} {1,4:D} {2, 12:N0}", nom, rang2003, freq2004 );

}

// propriétés : public int Rang {

get { return rang2003; } set { rang2003 = value; } }

public string Nom {

get { return nom; }

set { nom = value.ToUpper(); } }

public int Freq {

get { return freq2004; } set { freq2004 = value; } }

public override bool Equals(object obj) {

return nom.ToUpper().Equals( ((Station) obj).nom.ToUpper());

}

// la surcharge des opérateurs pour Quick Sort:

public static bool operator <= (Station st1, Station st2) {

return st1.nom.CompareTo(st2.nom) <= 0;

}

public static bool operator >= (Station st1, Station st2) {

return st1.nom.CompareTo(st2.nom) >= 0;

} }

(15)

class Operateurs2 {

static void Permuter(ref Station a, ref Station b) {

Station tempo = a;

a = b;

b = tempo;

}

static int Partitionner(Station[] T, int debut, int fin) {

int g = debut, d = fin;

Station valPivot = T[debut];

do {

while (g <= d && T[g] <= valPivot) g++;

while (! (T[d] <= valPivot)) d--;

if (g < d) Permuter(ref T[g],ref T[d]);

}

while (g <= d);

Permuter(ref T[debut],ref T[d]);

return d;

}

static void QuickSort(Station[] T, int gauche, int droite) {

if (droite > gauche)

/* au moins 2 éléments */

{

int indPivot = Partitionner(T, gauche, droite);

QuickSort(T, gauche, indPivot - 1);

QuickSort(T, indPivot + 1, droite);

} }

static void LireRemplir(string nomFichier, Station[] stat, out int n)

{

n = 0; // compteur du nombre de dtations lues

StreamReader aLire = File.OpenText(nomFichier);

string ligneLue = null;

while ( (ligneLue = aLire.ReadLine()) != null) stat[n++] = new Station(ligneLue);

aLire.Close();

Console.WriteLine("\nOn vient de creer un tableau de "

+ n + " stations");

}

(16)

static void Afficher(Station[] stat, int nbStat, int debut, int fin, string message)

{

Console.WriteLine("\nAffichage partiel du tableau des stations " + message);

for (int i = 0; i < nbStat; i++)

if (i < debut || i >= nbStat - fin) {

Console.Write("{0,6:D}) ", i);

stat[i].Afficher("");

}

else if (i == debut+1)

Console.WriteLine("etc .... ");

Console.WriteLine();

}

static void Main(string[] args) {

const int MAX_STAT = 70;

Station[] stat = new Station[MAX_STAT];

int nbStat;

LireRemplir("R:\\metro.txt", stat, out nbStat);

Afficher(stat, nbStat, 7, 4, "avant le tri");

QuickSort(stat, 0,nbStat-1);

Afficher(stat, nbStat, 3, 5, "apres le tri rapide");

} }

/* Exécution:

On vient de creer un tableau de 65 stations

Affichage partiel du tableau des stations avant le tri

0) MC-GILL 1 11 333 531 1) BERRI-UQAM 2 11 067 519 2) LONGUEUIL-UNIVERSITE-DE-SHERBROOKE 5 7 375 439 3) GUY-CONCORDIA 4 7 077 669 4) ATWATER 6 6 535 564 5) COTE-VERTU 9 6 387 345 6) PEEL 8 6 273 357 etc ....

61) ASSOMPTION 62 973 051 62) ACADIE 63 936 535 63) GEORGES-VANIER 64 695 482 64) DE LA SAVANE 65 690 673

Affichage partiel du tableau des stations apres le tri rapide 0) ACADIE 63 936 535 1) ANGRIGNON 15 4 493 057

(17)

2) ASSOMPTION 62 973 051 etc ....

60) UNIVERSITE-DE-MONTREAL 38 2 610 922 61) VENDOME 12 4 889 583 62) VERDUN 51 1 529 707 63) VIAU 34 2 617 979 64) VILLA-MARIA 33 2 753 590

Press any key to continue

*/

Exemple 3 (cas pratique : algorithme Min-Max) :

/* Fichier Operateurs3.cs *

*/

using System;

using System.IO;

class Rectangle {

private double longueur, largeur;

public Rectangle(double longueur, double largeur) {

this.longueur = longueur;

this.largeur = largeur;

}

public Rectangle(double cote): this(cote, cote) {

}

public Rectangle() {

}

public double Surface() {

return longueur * largeur ; }

public double Perimetre() {

return 2 * (longueur + largeur);

}

public static bool operator < (Rectangle rect1, Rectangle rect2) {

return rect1.Surface() < rect2.Surface();

}

public static bool operator > (Rectangle rect1, Rectangle rect2) {

return rect1.Surface() > rect2.Surface();

(18)

}

public override string ToString() {

return string.Format("{0, 6:F2} {1, 8:F2} {2, 10:F3} {3, 10:F3}",longueur, largeur, Perimetre(), Surface());

} }

class Operateurs3 {

static void Afficher(Rectangle[] rect, int nbRect)

{ Console.WriteLine("Contenu du tableau des rectangles :");

Console.WriteLine("Rang Longueur Largeur Perimetre Suface");

for (int i = 0; i < nbRect; i++)

Console.WriteLine("{0, 3}) {1, 40}", i, rect[i]);

Console.WriteLine();

}

static void DeterminerMinMax(Rectangle[] rect, int nbRect) {

int indMin = 0, indMax = 0;

for (int i = 1; i < nbRect ; i++)

{ if (rect[i] < rect[indMin]) indMin = i;

if (rect[i] > rect[indMax]) indMax = i;

}

Console.WriteLine("Rectangle ayant :");

Console.WriteLine(" - la plus petite surface: {0}", rect[indMin]);

Console.WriteLine(" - la plus grande surface: {0}", rect[indMax]);

Console.WriteLine();

}

static void Main(string[] args) {

Rectangle[] rect = { new Rectangle(12.5, 8.6), new Rectangle( 6.8, 5.2),

new Rectangle(18.3,15.2), new Rectangle(10.4)};

int nbRect = rect.Length;

Afficher(rect, nbRect);

DeterminerMinMax(rect, nbRect);

} }

/* Exécution:

Contenu du tableau des rectangles :

Rang Longueur Largeur Perimetre Suface 0) 12,50 8,60 42,200 107,500 1) 6,80 5,20 24,000 35,360 2) 18,30 15,20 67,000 278,160 3) 10,40 10,40 41,600 108,160

(19)

Rectangle ayant :

- la plus petite surface: 6,80 5,20 24,000 35,360 - la plus grande surface: 18,30 15,20 67,000 278,160 Press any key to continue

*/

Références

Documents relatifs

Jeune femme 23 ans ; découverte d'une masse abdominale lors d'une consultation pour début d'une

Les m´ethodes que nous voulons impl´ementer sont un constructeur (ayant un param`etre entier donnant la valeur de max, l’ensemble ´etant initialis´e ` a l’ensemble vide),

/* cette méthode permet de déterminer et de retourner le cercle ayant le rayon le plus grand entre le cercle courant et un autre cercle */. public Cercle plusGrand

Dans object, cette méthode compare selon la référence car les auteurs de cette méthode ne savent rien sur les classes créées plus tard pour comparter le contenu de deux objets.

le constructeur de la classe RectangleVisible appelle le constructeur à deux paramètres de sa classe de base (Rectangle) pour construire un rectangle visible, d’abord comme

Par contre, un rectangle est une figure géométrique dont le calcul du périmètre et de la surface est connu, on peut alors implémenter ces méthodes qui sont très concrètes (pas

On a aussi trié un tableau des stations de métro (classe Station) avec Array.Sort(. .) Cette méthode fonctionne car Station a implémenté l’interface IComparable2. Une fois que

Quand la valeur de Capacity est explicitement définie, le tableau interne est aussi réalloué pour prendre en compte la capacité spécifiée.. Si la valeur zéro est