Chaînes de caractères en C# : boîte à outils du type string

Le type string est un incontournable de n’importe quel langage de programmation. Présenter des données correctement, générer un texte à la volée, et même analyser un texte en entrée…

Si vous participez à des puzzle de code en ligne, par exemple, c’est généralement une réponse sous forme de chaîne de caractères qui est demandé. Il est donc indispensable d’être à l’aise avec la manipulation de ces chaînes.

Il existe de nombreux outils prêts à l’emploi dans C#, et les connaître apporte un gain de temps et de performances !

Création de chaîne de caractères

Le constructeur string

La façon la plus simple de déclarer une chaîne de caractères est de directement indiquer sa valeur. Par défaut, la valeur d’une chaîne de caractère est vide, un résultat qu’on peut assigner à une variable soit via string.Empty, soit avec "".

Attention, il s’agit bien d’une chaîne vide, pas d’une chaîne null. String est non Nullable, si nous voulions une chaîne Nullable il faudrait utiliser string?.

string name = "Texte pré-saisi";
string baseOuput = string.Empty;
string newOuput = "";

Le constructeur permet aussi de répéter un caractère plusieurs fois, avec comme argument un caractère et un entier :

string dots = new string('.', 10);
// Résultat : dots = ".........."

Enfin, une chaîne étant une série de caractères, le constructeur est capable de prendre un tableau de caractères char[] et d’en faire une chaîne.

Avec deux entiers (index et longueur), il est possible de n’avoir qu’une partie du tableau dans la chaîne résultante. Le snippet ci-dessous illustre l’utilisation d’un constructeur string avec un tableau de char vowels, de plusieurs manières.

char[] vowels = { 'A', 'E', 'I', 'O', 'U', 'Y' };
string vowelsText = new string(vowels);
// Contenu de la variable vowelsText = AEIOUY;
string vowelsTextThree = new string(vowels, 2, 3);
// Contenu de la variable vowelsTextThree = IOU;

Array.Reverse(vowels);   // On inverse le tableau de char

string vowelsTextInverted = new string(vowels);
// Contenu de la variable vowelsTextInverted = YUOIEA;
string goose = new string(vowels, 2, 3);
// Contenu de la variable goose = OIE;

Interpolation et échappement

L’interpolation permet de prévoir des places dans une chaîne et d’insérer des variables à cet endroit. Plutôt que de concaténer des chaînes et des valeurs avec l’opérateur de concaténation + :

string outputText = "Le total à payer est de " + amountDue + " Euros.";

Nous allons précéder la chaîne de caractères du symbole $, et mettre les variables à présenter entre accolades { et }. Cela donne des chaînes plus simples à manier et plus lisibles dans le code.

float amountDue = 12.34f + 43.21f;
Console.WriteLine($"Le total à payer est de {amountDue} Euros.");
// Sortie console : Le total à payer est de 55,55 Euros.

Il est aussi important de pouvoir échapper certains caractères, c’est à dire faire en sorte qu’ils ne soient pas interprétés. Il y a deux manières de le faire.

La première méthode, c’est de précéder les caractères spéciaux par un \ :

string quote = "Ouvrez les \"guillemets\".";
Console.WriteLine(quote);
// Sortie console : Ouvrez les "guillemets".

L’autre méthode, c’est d’utiliser le caractère @ (identificateur de chaîne textuelle). Lorsqu’il est placé avant les guillemets ouvrants d’une chaîne, il permet d’interpréter la chaine de caractère telle qu’elle, sans avoir besoin de caractères d’échappement.

Dans ce cas de figure, seul le caractère " a besoin d’échappement, ce qui se fait en le répétant deux fois.

string quote = @"Ouvrez les ""guillemets"".";
Console.WriteLine(quote);
// Sortie console : Ouvrez les "guillemets".

Typiquement, le symbole @ sera utilisé pour les chemins de répertoire, les adresses web et les expressions régulières.

string websiteUrl = @"https://www.gamecodeclub.com/chaines-de-caracteres-en-csharp-boite-a-outils-du-type-string/";
// L'URL est stockée dans websiteUrl sans échappement.
string regexPatternMaj = @"([A-Z])\w+";
// Cette expression régulière capturera tous les mots qui commencent par une majuscule.	

Assemblage sous forme de chaîne d’un tableau ou d’une liste de chaînes

string contient une méthode Join() qui permet de retourner tous les éléments d’un tableau ou d’une liste de chaînes, séparé par un caractère ou une chaîne spécifique.

Voici un exemple d’utilisation de cette méthode, en utilisant la syntaxe string.Join(séparateur, collection);

string[] siPrefixes = new string[]
{
	 "nano", "micro", "milli", "", "kilo", "mega", "giga"
};
Console.WriteLine(string.Join('|',siPrefixes));
// Sortie console : nano|micro|milli||kilo|mega|giga

List<string> lengthUnits = new List<string>();
foreach(string prefix in siPrefixes)
{
	lengthUnits.Add(prefix + "meter");
}
Console.WriteLine(string.Join(", ", lengthUnits));
// Sortie console : nanometer, micrometer, millimeter, meter, kilometer, megameter, gigameter

Le caractère utilisé pour séparer chaque élément de la chaîne peut être un caractère spécial, par exemple le caractère de retour à la ligne \n, ce qui permet de présenter les données chacune à la ligne.

Manipulations de chaîne de caractère

Inverser une chaîne / analyser chaque caractère un par un

Comme vu plus haut, une chaîne est un tableau de caractères. Donc on peut itérer sur ces caractères a l’aide d’une boucle.

Ci-dessous, la bouche foreach itère sur tous les caractères, et compte le nombre de voyelle et de consoles. On illustre aussi comment inverser une chaîne de caractères, pour l’exemple, même si la méthode Array.Reverse() est plus directe et à privilégier.

string sentenceToReverse = ".emordnilap a ton si sihT";
int vowelsCount = 0;
int consonantsCount = 0;
string reversedSentence = "";
foreach(char letter in sentenceToReverse)
{
	reversedSentence = letter + reversedSentence;
	if(char.IsLetter(letter))
	{
		if(vowels.Contains(char.ToUpper(letter)))
		{
			vowelsCount++;
		}
		else
		{
			consonantsCount++;
		}
	}
}
Console.WriteLine(reversedSentence);
// Sortie console : This is not a palindrome.
Console.WriteLine($"{vowelsCount} voyelles et {consonantsCount} consonnes.");
// Sortie console : 8 voyelles et 12 consonnes.

Récupérer une sous-chaîne (Substring et Split)

La méthode substring(int index, int len) sur un objet chaîne permet de retourner les derniers caractères à partir de l’index

string ColorsLine = "Rouge, Vert, Bleu";
Console.WriteLine(ColorsLine.Substring(13));
// Sortie console : Bleu
Console.WriteLine(ColorsLine.Substring(7, 4));
// Sortie console : Vert

Si vous ne savez pas l’index exact du séparateur dans la chaîne, vous pouvez utiliser la méthode « IndexOf() » sur cette chaîne, qui retourne le premier index où le caractère est présent. On utilise toujours le principe qu’une chaîne est un tableau de caractères.

string ArrivalLine = "Destination=Clermont-Ferrand";
int separatorIndex = ArrivalLine.IndexOf("=");
Console.WriteLine(ArrivalLine.Substring(separatorIndex + 1));
// Sortie console : Clermont-Ferrand

Une autre manière de faire, notamment quand une chaîne est formatée avec des séparateurs placés régulièrement, c’est d’utiliser la méthode Split(). Elle retourne un tableau de string après avoir séparé selon le caractère ou la chaîne spécifiée en paramètre.

string ColorsLine = "Rouge, Vert, Bleu";
string[] Colors = ColorsLine.Split(", ");
Console.WriteLine(Colors[1]);   // Sortie : Vert
Console.WriteLine(Colors[2]);   // Sortie : Bleu
Console.WriteLine(Colors[0]);   // Sortie : Rouge

Majuscules et minuscules

Une chaîne de caractère dispose des méthodes ToLower() et ToUpper(), qui permettent de changer la case de la chaîne, tout en minuscules ou tout en minuscules.

string smallAnimal = "MouSe";
string bigAnimal = "Elephant";
Console.WriteLine(smallAnimal.ToLower());
// Sortie console : mouse
Console.WriteLine(bigAnimal.ToUpper());
// Sortie console : ELEPHANT

Pour mettre le premier caractère d’une chaîne en majuscule (pour un nom propre, typiquement), on peut utiliser l’aspect « tableau » de la chaîne de caractère, en mettant en majuscule le premier caractère et en minuscule les caractères suivants.

string cityName = "tigerpolis";
cityName = char.ToUpper(cityName[0]) + cityName.Substring(1).ToLower();
Console.WriteLine(cityName);
// Sortie console : Tigerpolis

C’est un début d’implémentation, qui ne prend pas en compte les espaces, par exemple. Une manière plus « propre » et plus standard de mettre en majuscule la première lettre de chaque mot, c’est d’utiliser des méthodes du namespace System.Globalization, qui gère les infos locales de langue.

using System.Globalization;

Nous créons un objet TextInfo via la classe CultureInfo. Ci-dessous on utilise le paramètre local en-US, mais on pourrait utiliser fr-FR. Une fois l’objet créé, nous pouvons utiliser sa méthode « ToTitleCase() » qui met en majuscule la première lettre de chaque mot.

string founder = "ALaN tUrInG";
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
Console.WriteLine(textInfo.ToTitleCase(founder.ToLower()));
// Sortie console : Alan Turing

À noter que la méthode ne passe pas en minuscule les lettres qui sont en majuscule, c’est pourquoi on passe d’abord toute la chaîne en minuscule !

Remplacement

La méthode Replace(A, B) sur un objet string permet de remplacer dans cet objet toutes les occurrences d’une chaîne de caractères A par une chaîne de caractère B. (A et B sont du même type et peuvent être un caractère unique ou une chaîne de caractères).

string sentenceToTranslate = "Bonjour tout le monde, allez-vous bien ?";
string translatedSentence = sentenceToTranslate.Replace("a", "4");
translatedSentence = translatedSentence.Replace("e", "3");
translatedSentence = translatedSentence.Replace("i", "1");
translatedSentence = translatedSentence.Replace("o", "0");
Console.WriteLine(translatedSentence);
// Sortie console : B0nj0ur t0ut l3 m0nd3, 4ll3z-v0us b13n ?
Console.WriteLine(sentenceToTranslate);
// Sortie console : Bonjour tout le monde, allez-vous bien ?

Notez que Replace retourne la chaîne de caractère modifiée, mais n’affecte pas la chaîne de caractère d’origine, c’est pour ça que sur l’exemple, on stocke toujours la valeur modifiée dans une variable dédiée.

Formatage et alignement de la chaîne de caractère

La méthode string.Format(), associée à des notes de formatage, permet de présenter une chaîne de caractère au format voulu (pourcentage, monétaire, dates…). Je ne vais pas plus l’approfondir dans cet article car c’est un domaine vaste, mais voici un exemple de formatage de pourcentage où on spécifie le nombre de chiffres après la virgule :

double discount = 0.30;
Console.Write(string.Format("Remise de {0:0.0 %}", discount));
// Sortie console : Remise de 30,0 %
discount = 0.5432;
Console.Write(string.Format("Remise de {0:0.0 %}", discount));
// Sortie console : Remise de 54,3 %

Que signifie {0:0.0 %} ?, on spécifie que la variable passée en argument à l’index 0 (discount) doit être au format décimal, arrondie à un seul chiffre après la virgule (0.0) et traduite en pourcentage %. C’est le réglage local de Windows qui fait que la valeur vue dans la console est présentée avec une virgule et non un point, si on est sur un système en français.

Ce type de schéma de formatage peut être comme argument de la méthode ToString() appliquée à la variable (dans ce cas, on n’a pas besoin de l’indication 0: initiale, puisqu’on est directement sur la variable à formater. Voici un exemple qui l’illustre, avec cette fois deux décimales (et qui montre aussi qu’il s’agit bien d’un arrondi, les décimales ne sont pas juste tronquées).

double rate = 0.96129;
Console.Write("Taux : "+ rate.ToString("0.00 %"));
// Sortie console : Remise : 96,13 %

Enfin, les méthodes PadRight et PadLeft permettent d’aligner la chaîne de caractères en ajoutant un caractère au début et à la fin jusqu’à atteindre une longueur voulue. Par défaut, les méthodes ajouteront des espaces, mais ça peut être n’importe quel caractère de votre choix, afin que la ligne fasse une longueur donnée.

Ça peut être utile pour la mise en forme, pour de l’ASCII Art, dans un système où il est impératif qu’une chaîne respecte une longueur donnée pour être reconnue, etc.

string[] textToPad =
{
	"Ces mots doivent",
	"être alignés",
	"à droite."
};
foreach(string textLine in textToPad)
{
	Console.Write(textLine.PadLeft(20) + '\n');
}
// Sortie console : 
//    Ces mots doivent
//        être alignés
//           à droite.

string[] symbolsToComplete = { "000", "AAA", "!!!   ", "    loin du bord !", "Cette chaîne dépasse les 20 caractères." };
foreach (string symbolLine in symbolsToComplete)
{
	Console.Write(symbolLine.PadRight(22, '#') + '\n');
}
// Sortie console :
// 000###################
// AAA###################
// !!!   ################
//     loin du bord !####
// Cette chaîne dépasse les 22 caractères.

StringBuilder, pour construire une chaîne au fur et à mesure

Construire une chaîne peut se faire par concaténations successives, avec l’opérateur d’addition :

string Character = string.Empty;
Character += "Super";
Character += "Hero";
Console.WriteLine(Character);
// Sortie console : SuperHero

Ça convient pour les tas simples, mais ça présente un défaut :

Cela vient du fait que l’objet de type string est immutable, c’est à dire que son état ne peut être modifié après sa création. En somme, à chaque addition avec l’opérateur +=, nous re-créons un nouvel objet string qui remplace l’ancien, plutôt que d’ajouter quelque chose à un objet existant.

Donc, pour 5 à 6 concaténations, ça va assez vite, mais sur un programme plus vaste, dans lequel la concaténation est dans une boucle, la perte en temps d’exécution est visible.

Il existe un objet spécial pour remédier à cette perte de performances : le StringBuilder.

Utilisation simple d’un StringBuilder

Pour pouvoir l’utiliser, il faut utiliser l’espace de noms System.Text.

using System.Text;

Vous définissez ensuite un nouveau StringBuilder. Son constructeur peut être sans argument pour commencer avec une chaîne vide, ou alors comporter directement une chaîne de départ.

Voici un exemple typique, où nous ajoutons des éléments sur notre objet avec la méthode Append(string text), puis nous le présentons dans la console avec la méthode ToString();

StringBuilder blogTitle = new StringBuilder();

blogTitle.Append("Game");
blogTitle.Append("Code");
blogTitle.Append("Club");

Console.WriteLine(blogTitle.ToString());
// Sortie console : GameCodeClub

Un objet StringBuilder dispose d’une propriété Capacity, correspondant au nombre maximum de caractères de la chaîne finale. Elle peut être fournie directement à la construction de l’objet, ou assignée.

Nous disposons de la méthode EnsureCapacity(int capacité); qui permet de confirmer si l’objet StringBuilder contient la capacité suffisante.

Fonctions avancées du StringBuilder

StringBuilder dispose d’autres méthodes, permettant de manipuler les objets de diverses manières :

  1. Append() ajoute des informations à la fin de l’objet
  2. AppendFormat() ajoute des informations à la fin de l’objet, avec un format spécifié
  3. Insert() ajoute le texte à la position spécifiée par l’indice
  4. Remove() enlève des caractères dans l’objet (paramètres : indice du premier caractère et nombre de caractères à enlever)
  5. Replace() remplace les occurrences d’un caractère ou d’une chaîne dans l’objet (même méthode que le Replace() du string.

Voici un exemple d’utilisation de chacune des fonctions, dans une séquence où nous créons le début d’un alphabet grec classique :

StringBuilder greekAlphabet = new StringBuilder("Alpha, ");

greekAlphabet.Append("Gamma, ");
greekAlphabet.Append("Placeholder, ");
// Contenu de greekAlphabet = Alpha, Gamma, Placeholder,  

greekAlphabet.Insert(7, "Bêta, ");
// Contenu de greekAlphabet = Alpha, Bêta, Gamma, Placeholder,  

string greekLetterZ = "Epsilon";
greekAlphabet.AppendFormat("{0}, ", greekLetterZ);

// Contenu de greekAlphabet = Alpha, Bêta, Gamma, Placeholder, Epsilon,  

greekAlphabet.Append("Zêta, ");
// Contenu de greekAlphabet = Alpha, Bêta, Gamma, Placeholder, Epsilon, Zêta,  

greekAlphabet.Replace("Placeholder", "Delta");
// Contenu de greekAlphabet = Alpha, Bêta, Gamma, Delta, Epsilon, Zêta,  

greekAlphabet.Remove(greekAlphabet.Length - 2, 2);
// Contenu de greekAlphabet = Alpha, Bêta, Gamma, Delta, Epsilon, Zêta

Publié dans CodeTag(s) :

One thought on “Chaînes de caractères en C# : boîte à outils du type string

Commentaires désactivés