3 Classes NET d'usage courant
3.2 Les chaînes de caractères
3.2.1
La classe System.String
1
2 3
4
La classe System.String est identique au type simple string. Elle présente de nombreuses propriétés et méthodes. En voici quelques-unes :
public int Length { get; } nombre de caractères de la chaîne
public bool EndsWith(string value) rend vrai si la chaîne se termine par value
public bool StartsWith(string value) rend vrai si la chaîne commence par value
public virtual bool Equals(object obj) rend vrai si la chaînes est égale à obj - équivalent chaîne==obj
public int IndexOf(string value, int startIndex) rend la première position dans la chaîne de la chaîne value - la recherche commence à partir du caractère n° startIndex
public int IndexOf(char value, int startIndex) idem mais pour le caractère value
public string Insert(int startIndex, string value) insère la chaîne value dans chaîne en position
startIndex
public static string Join(string separator,
string[] value) méthode de classe - rend une chaîne de caractères, résultat de la concaténation des valeurs du tableau
value avec le séparateur separator
public int LastIndexOf(char value, int startIndex,
int count)
public int LastIndexOf(string value, int
startIndex, int count)
idem indexOf mais rend la dernière position au lieu de la première
public string Replace(char oldChar, char newChar) rend une chaîne copie de la chaîne courante où le caractère oldChar a été remplacé par le caractère
newChar
public string[] Split(char[] separator) la chaîne est vue comme une suite de champs séparés par les caractères présents dans le tableau
separator. Le résultat est le tableau de ces champs
public string Substring(int startIndex, int length) sous-chaîne de la chaîne courante commençant à la position startIndex et ayant length caractères public string ToLower() rend la chaîne courante en minuscules
public string ToUpper() rend la chaîne courante en majuscules
public string Trim() rend la chaîne courante débarrassée de ses espaces de début et fin
On notera un point important : lorsqu'une méthode rend une chaîne de caractères, celle-ci est une chaîne différente de la chaîne sur laquelle a été appliquée la méthode. Ainsi S1.Trim() rend une chaîne S2, et S1 et S2 sont deux chaînes différentes.
Une chaîne C peut être considérée comme un tableau de caractères. Ainsi C[i] est le caractère i de C
C.Length est le nombre de caractères de C
Considérons l'exemple suivant : 1. using System; 2.
3. namespace Chap3 { 4. class Program {
5. static void Main(string[] args) {
6. string uneChaine = "l'oiseau vole au-dessus des nuages"; 7. affiche("uneChaine=" + uneChaine);
8. affiche("uneChaine.Length=" + uneChaine.Length); 9. affiche("chaine[10]=" + uneChaine[10]);
10. affiche("uneChaine.IndexOf(\"vole\")=" + uneChaine.IndexOf("vole")); 11. affiche("uneChaine.IndexOf(\"x\")=" + uneChaine.IndexOf("x")); 12. affiche("uneChaine.LastIndexOf('a')=" + uneChaine.LastIndexOf('a')); 13. affiche("uneChaine.LastIndexOf('x')=" + uneChaine.LastIndexOf('x')); 14. affiche("uneChaine.Substring(4,7)=" + uneChaine.Substring(4, 7)); 15. affiche("uneChaine.ToUpper()=" + uneChaine.ToUpper());
16. affiche("uneChaine.ToLower()=" + uneChaine.ToLower());
17. affiche("uneChaine.Replace('a','A')=" + uneChaine.Replace('a', 'A')); 18. string[] champs = uneChaine.Split(null);
19. for (int i = 0; i < champs.Length; i++) {
20. affiche("champs[" + i + "]=[" + champs[i] + "]");
21. }//for
23. affiche("(\" abc \").Trim()=[" + " abc ".Trim() + "]"); 24. }//Main
25.
26. public static void affiche(string msg) { 27. // affiche msg
28. Console.WriteLine(msg);
29. }//affiche 30. }//classe 31. }//namespace
L'exécution donne les résultats suivants :
1. uneChaine=l'oiseau vole au-dessus des nuages 2. uneChaine.Length=34 3. chaine[10]=o 4. uneChaine.IndexOf("vole")=9 5. uneChaine.IndexOf("x")=-1 6. uneChaine.LastIndexOf('a')=30 7. uneChaine.LastIndexOf('x')=-1 8. uneChaine.Substring(4,7)=seau vo
9. uneChaine.ToUpper()=L'OISEAU VOLE AU-DESSUS DES NUAGES 10. uneChaine.ToLower()=l'oiseau vole au-dessus des nuages 11. uneChaine.Replace('a','A')=l'oiseAu vole Au-dessus des nuAges 12. champs[0]=[l'oiseau] 13. champs[1]=[vole] 14. champs[2]=[au-dessus] 15. champs[3]=[des] 16. champs[4]=[nuages] 17. Join(":",champs)=l'oiseau:vole:au-dessus:des:nuages 18. (" abc ").Trim()=[abc]
Considérons un nouvel exemple : 1. using System; 2.
3. namespace Chap3 { 4. class Program {
5. static void Main(string[] args) { 6. // la ligne à analyser
7. string ligne = "un:deux::trois:"; 8. // les séparateurs de champs
9. char[] séparateurs = new char[] { ':' }; 10. // split
11. string[] champs = ligne.Split(séparateurs); 12. for (int i = 0; i < champs.Length; i++) {
13. Console.WriteLine("Champs[" + i + "]=" + champs[i]);
14. }
15. // join
16. Console.WriteLine("join=[" + System.String.Join(":", champs) + "]");
17. }
18. } 19. }
et les résultats d'exécution : 1. Champs[0]=un 2. Champs[1]=deux 3. Champs[2]= 4. Champs[3]=trois 5. Champs[4]= 6. join=[un:deux::trois:]
La méthode Split de la classe String permet de mettre dans un tableau des éléments d'une chaîne de caractères. La définition de la méthode Split utilisée ici est la suivante :
public string[] Split(char[] separator);
separator tableau de caractères. Ces caractères représentent les caractères utilisés pour séparer les champs de la chaîne de caractères. Ainsi si la chaîne est "champ1, champ2, champ3" on pourra utiliser separator=new char[] {','}. Si le séparateur est une suite d'espaces on utilisera separator=null.
résultat tableau de chaînes de caractères où chaque élément du tableau est un champ de la chaîne. La méthode Join est une méthode statique de la classe String :
public static string Join(string separator, string[] value); value tableau de chaînes de caractères
separator une chaîne de caractères qui servira de séparateur de champs
résultat une chaîne de caractères formée de la concaténation des éléments du tableau value séparés par la chaîne separator.
3.2.2
La classe System.Text.StringBuilder
Précédemment, nous avons dit que les méthodes de la classe String qui s'appliquaient à une chaîne de caractères S1 rendait une autre chaîne S2. La classe System.Text.StringBuilder permet de manipuler S1 sans avoir à créer une chaîne S2. Cela améliore les performances en évitant la multiplication de chaînes à durée de vie très limitée.
La classe admet divers constructeurs :
StringBuilder() constructeur par défaut
StringBuilder(String value) construction et initialisation avec value
StringBuilder(String value, int capacité) construction et initialisation avec value avec une taille de bloc de capacité caractères.
Un objet StringBuilder travaille avec des blocs de capacité caractères pour stocker la chaîne sous-jacente. Par défaut capacité vaut 16. Le 3ième constructeur ci-dessus permet de préciser la capacité des blocs. Le nombre de blocs de capacité caractères nécessaire pour stocker une chaîne S est ajusté automatiquement par la classe StringBuilder. Il existe des constructeurs pour fixer le nombre maximal de caractères dans un objet StringBuilder. Par défaut, cette capacité maximale est 2 147 483 647.
Voici un exemple illustrant cette notion de capacité : 1. using System.Text;
2. using System; 3. namespace Chap3 { 4. class Program {
5. static void Main(string[] args) {
6. // str
7. StringBuilder str = new StringBuilder("test");
8. Console.WriteLine("taille={0}, capacité={1}", str.Length, str.Capacity); 9. for (int i = 0; i < 10; i++) {
10. str.Append("test");
11. Console.WriteLine("taille={0}, capacité={1}", str.Length, str.Capacity);
12. }
13. // str2
14. StringBuilder str2 = new StringBuilder("test",10);
15. Console.WriteLine("taille={0}, capacité={1}", str2.Length, str2.Capacity); 16. for (int i = 0; i < 10; i++) {
17. str2.Append("test");
18. Console.WriteLine("taille={0}, capacité={1}", str2.Length, str2.Capacity);
19. }
20. }
21. } 22. }
• ligne 7 : création d'un objet StringBuilder avec une taille de bloc de 16 caractères
• ligne 8 : str.Length est le nombre actuel de caractères de la chaîne str. str.Capacity est le nombre de caractères que peut stocker la chaîne str actuelle avant réallocation d'un nouveau bloc.
• ligne 10 : str.Append(String S) permet de concaténer la chaîne S de type String à la chaîne str de type StringBuilder. • ligne 14 : création d'un objet StringBuilder avec une capacité de bloc de 10 caractères
Le résultat de l'exécution : 1. taille=4, capacité=16 2. taille=8, capacité=16 3. taille=12, capacité=16 4. taille=16, capacité=16 5. taille=20, capacité=32 6. taille=24, capacité=32 7. taille=28, capacité=32 8. taille=32, capacité=32 9. taille=36, capacité=64 10. taille=40, capacité=64 11. taille=44, capacité=64 12. taille=4, capacité=10 13. taille=8, capacité=10 14. taille=12, capacité=20 15. taille=16, capacité=20 16. taille=20, capacité=20 17. taille=24, capacité=40 18. taille=28, capacité=40 19. taille=32, capacité=40 20. taille=36, capacité=40 21. taille=40, capacité=40 22. taille=44, capacité=80
Ces résultats montrent que la classe suit un algorithme qui lui est propre pour allouer de nouveaux blocs lorsque sa capacité est insuffisante :
• lignes 4-5 : augmentation de la capacité de 16 caractères
• lignes 8-9 : augmentation de la capacité de 32 caractères alors que 16 auraient suffi. Voici quelques-unes des méthodes de la classe :
public StringBuilder Append(string value) ajoute la chaîne value à l'objet StringBuilder. Rend l'objet StringBuilder. Cette méthode est surchargée pour admettre différents types pour value : byte, int, float, double, decimal, ...
public StringBuilder Insert(int index, string
value) insère value à la position index. Cette méthode est surchargée comme la précédente pour accepter différents types pour value.
public StringBuilder Remove(int index, int length) supprime length caractères à partir de la position
index.
public StringBuilder Replace(string oldValue,
string newValue) remplace dans StringBuilder, la chaîne oldValue par la chaîne newValue. Il existe une version surchargée (char oldChar, char newChar).
public String ToString() convertit l'objet StringBuilder en un objet de type String. Voici un exemple : 1. using System.Text; 2. using System; 3. namespace Chap3 { 4. class Program {
5. static void Main(string[] args) {
7. StringBuilder str3 = new StringBuilder("test");
8. Console.WriteLine(str3.Append("abCD").Insert(2, "xyZT").Remove(0, 2).Replace("xy", "XY"));
9. } 10. } 11. } et ses résultats : XYZTstabCD
3.3 Les tableaux
Les tableaux dérivent de la classe Array :
La classe Array possède diverses méthodes pour trier un tableau, rechercher un élément dans un tableau, redimensionner un tableau, ... Nous présentons certaines propriétés et méthodes de cette classe. Elles sont quasiment toutes surchargées, c.a.d. qu'elles existent en différentes variantes. Tout tableau en hérite.
Propriétés
public int Length {get;} nombre total d'éléments du tableau, quelque soit son nombre de dimensions
public int Rank {get;} nombre total de dimensions du tableau
Méthodes
public static int BinarySearch<T>(T[] tableau,T
value) rend la position de value dans tableau.
public static int BinarySearch<T>(T[] tableau,int
index, int length, T value) idem mais cherche dans tableau à partir de la position index et sur length éléments
public static void Clear(Array tableau, int index,
int length) met les length éléments de tableau commençant au n° index à 0 si numériques, false si booléens, null si
références
public static void Copy(Array source, Array
destination, int length) copie length éléments de source dans destination
public int GetLength(int i) nombre d'éléments de la dimension n° i du tableau
public int GetLowerBound(int i) indice du 1er élément de la dimension n° i
public int GetUpperBound(int i) indice du dernier élément de la dimension n° i
public static int IndexOf<T>(T[] tableau, T valeur) rend la position de valeur dans tableau ou -1 si valeur n'est pas trouvée.
public static void Resize<T>(ref T[] tableau, int
n) redimensionne tableau à n éléments. Les éléments déjà présents sont conservés.
public static void Sort<T>(T[] tableau,
Le programme suivant illustre l'utilisation de certaines méthodes de la classe Array : 1. using System; 2. 3. namespace Chap3 { 4. class Program { 5. // type de recherche
6. enum TypeRecherche { linéaire, dichotomique }; 7.
8. // méthode principale
9. static void Main(string[] args) {
10. // lecture des éléments d'un tableau tapés au clavier 11. double[] éléments;
12. Saisie(out éléments);
13. // affichage tableau non trié
14. Affiche("Tableau non trié", éléments);
15. // Recherche linéaire dans le tableau non trié 16. Recherche(éléments, TypeRecherche.linéaire); 17. // tri du tableau
18. Array.Sort(éléments);
19. // affichage tableau trié
20. Affiche("Tableau trié", éléments);
21. // Recherche dichotomique dans le tableau trié 22. Recherche(éléments, TypeRecherche.dichotomique);
23. }
24.
25. // saisie des valeurs du tableau éléments
26. // éléments : référence sur tableau créé par la méthode 27. static void Saisie(out double[] éléments) {
28. bool terminé = false; 29. string réponse; 30. bool erreur; 31. double élément = 0; 32. int i = 0;
33. // au départ, le tableau n'existe pas 34. éléments = null;
35. // boucle de saisie des éléments du tableau 36. while (!terminé) {
37. // question
38. Console.Write("Elément (réel) " + i + " du tableau (rien pour terminer) : "); 39. // lecture de la réponse
40. réponse = Console.ReadLine().Trim(); 41. // fin de saisie si chaîne vide 42. if (réponse.Equals(""))
43. break;
44. // vérification saisie
45. try {
46. élément = Double.Parse(réponse); 47. erreur = false;
48. } catch {
49. Console.Error.WriteLine("Saisie incorrecte, recommencez");
50. erreur = true;
51. }//try-catch
52. // si pas d'erreur 53. if (!erreur) {
54. // un élément de plus dans le tableau
55. i += 1;
56. // redimensionnement tableau pour accueillir le nouvel élément
57. Array.Resize(ref éléments, i);
58. // insertion nouvel élément 59. éléments[i - 1] = élément;
60. }
61. }//while
62. }
63.
64. // méthode générique pour afficher les éléments d'un tableau 65. static void Affiche<T>(string texte, T[] éléments) {
66. Console.WriteLine(texte.PadRight(50, '-')); 67. foreach (T élément in éléments) {
68. Console.WriteLine(élément);
69. }
70. }
71.
72. // recherche d'un élément dans le tableau 73. // éléments : tableau de réels
75. static void Recherche(double[] éléments, TypeRecherche type) { 76. // Recherche
77. bool terminé = false; 78. string réponse = null; 79. double élément = 0; 80. bool erreur = false; 81. int i = 0;
82. while (!terminé) {
83. // question
84. Console.WriteLine("Elément cherché (rien pour arrêter) : "); 85. // lecture-vérification réponse
86. réponse = Console.ReadLine().Trim();
87. // fini ?
88. if (réponse.Equals(""))
89. break;
90. // vérification
91. try {
92. élément = Double.Parse(réponse); 93. erreur = false;
94. } catch {
95. Console.WriteLine("Erreur, recommencez...");
96. erreur = true;
97. }//try-catch
98. // si pas d'erreur 99. if (!erreur) {
100. // on cherche l'élément dans le tableau 101. if (type == TypeRecherche.dichotomique) 102. // recherche dichotomique
103. i = Array.BinarySearch(éléments, élément);
104. else
105. // recherche linéaire
106. i = Array.IndexOf(éléments, élément);
107. // Affichage réponse 108. if (i >= 0)
109. Console.WriteLine("Trouvé en position " + i);
110. else
111. Console.WriteLine("Pas dans le tableau");
112. }//if
113. }//while 114. }
115. } 116.}
• lignes 27-62 : la méthode Saisie saisit les éléments d'un tableau éléments tapés au clavier. Comme on ne peut dimensionner le tableau à priori (on ne connaît pas sa taille finale), on est obligés de le redimensionner à chaque nouvel élément (ligne 57). Un algorithme plus efficace aurait été d'allouer de la place au tableau par groupe de N éléments. Un tableau n'est cependant pas fait pour être redimensionné . Ce cas là est mieux traité avec une liste (ArrayList, List<T>).
• lignes 75-113 : la méthode Recherche permet de rechercher dans le tabeau éléments, un élément tapé au clavier. Le mode de recherche est différent selon que le tableau est trié ou non. Pour un tableau non trié, on fait une recherche linéaire avec la méthode IndexOf de la ligne 106. Pour un tableau trié, on fait une recherche dichotomique avec la méthode BinarySearch de la ligne 103.
• ligne 18 : on trie le tableau éléments. On utilise ici, une variante de Sort qui n'a qu'un paramètre : le tableau à trier. La relation d'ordre utilisée pour comparer les éléments du tableau est alors celle implicite de ces éléments. Ici, les éléments sont numériques. C'est l'ordre naturel des nombres qui est utilisé.
Les résultats écran sont les suivants :
1. Elément (réel) 0 du tableau (rien pour terminer) : 3,6 2. Elément (réel) 1 du tableau (rien pour terminer) : 7,4 3. Elément (réel) 2 du tableau (rien pour terminer) : -1,5 4. Elément (réel) 3 du tableau (rien pour terminer) : -7 5. Elément (réel) 4 du tableau (rien pour terminer) : 6. Tableau non trié--- 7. 3,6
8. 7,4 9. -1,5 10. -7
11. Elément cherché (rien pour arrêter) : 12. 7,4
13. Trouvé en position 1
14. Elément cherché (rien pour arrêter) : 15. 0
16. Pas dans le tableau
18. 19. Tableau trié--- 20. -7 21. -1,5 22. 3,6 23. 7,4
24. Elément cherché (rien pour arrêter) : 25. 7,4
26. Trouvé en position 3
27. Elément cherché (rien pour arrêter) : 28. 0
29. Pas dans le tableau
30. Elément cherché (rien pour arrêter) :