Section courante

A propos

Section administrative du site

Les entrées/sorties de la console

Dans cette page, nous allons nous familiariser avec la console en tant qu'outil d'entrée et de sortie de données. Nous expliquerons ce que c'est, quand et comment l'utiliser, et comment la plupart des langages de programmation accèdent à la console. Nous nous familiariserons avec certaines des fonctionnalités de C# pour l'interaction avec l'utilisateur : lecture de texte et de nombres à partir de la console et impression de texte et de nombres. Nous examinerons également les principaux flux pour les opérations d'entrée-sortie Console.In, Console.Out et Console.Error, la console et l'utilisation de chaînes de format pour afficher des données dans divers formats.

Qu'est-ce que la console ?

La console est une fenêtre du système d'exploitation à travers laquelle les utilisateurs peuvent interagir avec les programmes système du système d'exploitation ou avec d'autres applications de la console. L'interaction consiste en une saisie de texte à partir de l'entrée standard (généralement le clavier) ou en un affichage de texte sur la sortie standard (généralement sur l'écran de l'ordinateur). Ces actions sont également appelées opérations d'entrée-sortie. Le texte écrit sur la console apporte des informations et est une séquence de caractères envoyés par un ou plusieurs programmes.

Pour chaque application de la console, le système d'exploitation connecte des périphériques d'entrée et de sortie. Par défaut, il s'agit du clavier et de l'écran, mais ils peuvent être redirigés vers un fichier ou d'autres périphériques.

Communication entre l'utilisateur et le programme

De nombreux programmes communiquent d'une manière ou d'une autre avec l'utilisateur. Cela est nécessaire pour que l'utilisateur puisse leur donner des instructions. Les méthodes de communication modernes sont nombreuses et variées : elles peuvent se faire via une interface graphique ou Web, une console ou d'autres. Comme nous l'avons mentionné, l'un des outils de communication entre les programmes et les utilisateurs est la console, qui est de moins en moins utilisée. Cela est dû au fait que les concepts d'interface utilisateur modernes sont plus pratiques et intuitifs à utiliser, du point de vue de l'utilisateur.

Quand utiliser la console ?

Dans certains cas, la console reste un outil irremplaçable pour la communication avec l'utilisateur. L'un de ces cas est celui de l'écriture de petits programmes simples où il est nécessaire de concentrer l'attention sur le problème spécifique à résoudre, plutôt que sur la représentation élégante du résultat pour l'utilisateur. On utilise alors une solution simple pour saisir ou afficher un résultat, comme la console d'entrée-sortie. Un autre cas d'utilisation est celui où nous voulons tester un petit morceau de code pour une application plus vaste. En raison de la simplicité du fonctionnement de l'application console, nous pouvons isoler cette partie du code facilement et confortablement sans avoir à passer par une interface utilisateur complexe et un certain nombre d'écrans pour accéder au code souhaité pour le test.

Comment lancer la console ?

Chaque système d'exploitation possède sa propre façon de lancer la console. Sous Windows par exemple, cela peut se faire de la manière suivante :

Après le démarrage de la console, un écran noir (cette couleur peut être modifiée) comme celui-ci devrait apparaître :

Lors du démarrage de la console, le répertoire personnel de l'utilisateur actuel (dans ce cas, le nom d'utilisateur est Sylvain Maltais) est utilisé comme répertoire courant et celui-ci est affiché comme guide pour l'utilisateur.

En savoir plus sur les consoles

La console système est la fenêtre noire illustrée ci-dessus affichant des informations textuelles. Elle peut afficher des chaînes de caractères de texte et dispose d'un curseur se déplaçant vers la droite après l'affichage de chaque caractère. Une fois que le curseur a traversé la dernière colonne de la console (elle en compte généralement 80), il se déplace au début de la ligne suivante. Si le curseur passe par la dernière ligne, la console fait défiler son contenu vers le haut et affiche une nouvelle ligne vide sous la dernière ligne.

Les programmes sous Windows peuvent être basés sur une console, basés sur un ordinateur de bureau, basés sur le Web et autres. Les programmes basés sur une console utilisent la console pour leurs entrées et sorties. Les programmes basés sur un ordinateur de bureau utilisent une interface utilisateur graphique (GUI). Les programmes basés sur le Web ont une interface utilisateur basée sur le Web. Dans cette page, nous écrirons presque tout le temps des programmes basés sur une console, de sorte que leurs entrées seront lues à partir du clavier et leurs sorties seront imprimées dans la console. Certains programmes basés sur une console attendent des utilisateurs qu'ils saisissent du texte, des chiffres et d'autres données, ce qui se fait généralement via le clavier.

La console de Windows est souvent associée à l'interpréteur de commandes du système, également appelé «invite de commande», «prompt de commande» ou «interpréteur de commande», étant un programme basé sur la console du système d'exploitation, permettant d'accéder aux commandes du système ainsi qu'à une large gamme de programmes, faisant partie du système d'exploitation ou qui y sont installés en plus.

Les interpréteur de commande du système d'exploitation peuvent être divisés en deux catégories principales selon le type d'interface qu'ils peuvent fournir au système d'exploitation :

Pour les deux types, le but principal de l'interpréteur de commande est d'exécuter d'autres programmes avec lesquels l'utilisateur travaille, bien que la plupart des interpréteurs prennent également en charge certaines fonctionnalités avancées telles que la possibilité d'examiner le contenu des répertoires contenant des fichiers.

Par exemple, lors du démarrage de la console Windows, nous exécutons l'interpréteur de commandes Windows (cmd.exe) exécutant les programmes et commandes système en mode interactif. Par exemple, la commande dir affiche les fichiers du répertoire courant :

Commandes de base de la console

Nous allons examiner certaines commandes de base du prompt de commande standard de Windows, étant utile pour rechercher et lancer des programmes.

Commandes de la console Windows

L'interpréteur de commandes exécuté dans la console est également appelé «Invite de commandes» ou «Invite MS-DOS» (dans les anciennes versions de Windows). Nous allons examiner certaines commandes de base de cet interpréteur :

Commande Description
dir Affiche le contenu du répertoire actuel.
cd nom du répertoire Modifie le répertoire actuel.
mkdir nom du répertoire Crée un nouveau répertoire dans le répertoire actuel.
rmdir nom du répertoire Supprime un répertoire existant.
type nom du fichier Affiche le contenu du fichier.
copy fichier-source fichier-destinataire Copie un fichier dans un autre.

Entrée-sortie standard

L'entrée-sortie standard, également connue sous le nom de «entrée/sortie standard», est un mécanisme d'entrée-sortie système créé depuis le développement des systèmes d'exploitation UNIX il y a de nombreuses années. Des périphériques spéciaux pour l'entrée et la sortie sont utilisés, à travers lesquels les données peuvent être entrées et sorties.

Lorsque le programme est en mode d'acceptation d'informations et attend une action de l'utilisateur, un curseur clignotant apparaît sur la console indiquant que le système attend la saisie de la commande.

Nous verrons plus tard comment nous pouvons écrire des programmes C# attendant que les données d'entrée soient saisies à partir de la console.

Affichage sur la console

Dans la plupart des langages de programmation, l'affichage et la lecture des informations depuis la console sont implémentées de manière similaire et la plupart des solutions sont basées sur le concept d'«entrée standard» et de «sortie standard».

Entrée standard et sortie standard

Le système d'exploitation doit définir des mécanismes d'entrée-sortie standard pour l'interaction utilisateur. Lors du démarrage d'un programme de console donné, le code système exécuté à l'initialisation du programme est responsable de l'ouverture (fermeture) des flux vers les mécanismes d'entrée-sortie alloués par le système d'exploitation. Ce code système initialise l'abstraction du programme pour l'interaction utilisateur intégrée dans le langage de programmation respectif. De cette manière, l'application démarrée peut automatiquement lire l'entrée d'utilisation à partir du flux d'entrée standard (en C#, il s'agit de Console.In), afficher des informations sur le flux de sortie standard (en C#, il s'agit de Console.Out) et peut signaler des situations problématiques dans le flux d'erreur standard (en C#, il s'agit de Console.Error).

Le concept des flux de données sera examiné plus en détail plus tard. Pour l'instant, nous allons nous concentrer sur les bases théoriques liées à l'entrée et à la sortie du programme en C#.

Périphériques d'entrée et de sortie de la console

Outre le clavier, les entrées d'une application peuvent provenir de nombreux autres emplacements, tels qu'un fichier, un microphone, un lecteur de codes-barres et autres. La sortie d'un programme peut se trouver sur la console (sur l'écran), ainsi que dans un fichier ou un autre périphérique de sortie, comme une imprimante :

Nous allons montrer un exemple de base illustrant l'affichage de texte sur la console via l'abstraction permettant d'accéder à l'entrée standard et à la sortie standard fournies par C# :

  1. Console.Out.WriteLine("Bonjour le monde");

Le résultat de l'exécution du code ci-dessus serait le suivant :

Bonjour le monde

Flux de données Console.Out

La classe System.Console possède différentes propriétés et méthodes étant utilisées pour lire et afficher du texte sur la console ainsi que son formatage. Parmi elles, il y a trois propriétés faisant impression et étant liées à la saisie et à l'affichage des données, à savoir Console.Out, Console.In et Console.Error. Elles donnent accès aux flux standard pour l'impression sur la console, pour la lecture depuis la console et au flux de rapport des messages d'erreur en conséquence. Bien que nous puissions les utiliser directement, les autres méthodes de System.Console nous offrent la commodité de travailler avec des opérations de console d'entrée-sortie et en fait, le plus souvent, ces propriétés sont ignorées. Cependant, il est bon de se rappeler que cette partie de la fonctionnalité de la console fonctionne sur ces flux. Si nécessaire, nous pouvons remplacer les flux d'entrée/sortie/erreur par défaut au moment de l'exécution en utilisant respectivement les méthodes Console.SetOut(...), Console.SetIn(...) et Console.SetError(...).

Nous allons maintenant examiner les méthodes les plus couramment utilisées pour l'affichage de texte sur la console.

Utilisation de Console.Write(...) et Console.WriteLine(...)

Travailler avec ces méthodes est facile car elles peuvent imprimer tous les types de base (chaînes de caractères, types numériques et types primitifs).

Voici quelques exemples d'impression de différents types de données :

  1. // Affiche de chaîne de caractères
  2. Console.WriteLine("Bonjour le monde");
  3. // Afficher un entier
  4. Console.WriteLine(5);
  5. // Afficher un nombre réel de double précision
  6. Console.WriteLine(3.14159265358979);     

Le résultat de l'exécution de ce code ressemble à ceci :

Bonjour le monde
5
3.14159265358979

Comme on le voit en utilisant Console.WriteLine(...) il est possible d'afficher différents types de données car pour chaque type il existe une version prédéfinie de la méthode WriteLine(...) dans la classe Console.

La différence entre Write(...) et WriteLine(...) est que la méthode Write(...) affiche sur la console ce qui est fourni entre les parenthèses mais ne fait rien de plus alors que la méthode WriteLine(...) signifie directement «écrire une ligne». Cette méthode fait ce que fait la méthode Write(...) mais en plus passe à une nouvelle ligne. En fait la méthode n'affiche pas de nouvelle ligne mais met simplement une «commande» pour déplacer le curseur à la position où la nouvelle ligne commence (cette commande se compose du caractère \r suivi de \n).

Voici un exemple illustrant la différence entre Write(...) et WriteLine(...) :

  1. Console.WriteLine("J'aime");
  2. Console.Write("le site ");
  3. Console.Write("gladir.com !");

Le résultat de cet exemple est :

J'aime
le site gladir.com !

Nous remarquons que la sortie de cet exemple est affichée sur deux lignes, même si le code est sur trois. Cela se produit parce que sur la première ligne de code, nous utilisons WriteLine(...) affichant «J'aime» puis passe à une nouvelle ligne. Dans les deux lignes suivantes, le code utilise la méthode Write(...), affichant sans passer à une nouvelle ligne et donc les mots «le site» et « gladir.com ! » restent sur la même ligne.

Concaténation de chaînes de caractères

En général, C# n'autorise pas l'utilisation d'opérateurs sur des objets de chaîne de caractères. La seule exception à cette règle est l'opération d'addition (+) concaténant (joint) deux chaînes de caractères et renvoie comme résultat une nouvelle chaîne de caractères. Cela permet d'enchaîner les opérations de concaténation (+) les unes après les autres dans une séquence. L'exemple suivant représente la concaténation de trois chaînes de caractères.

  1. string age = "cinquante et un";
  2. string text = "Il a " + age + " ans.";
  3. Console.WriteLine(text);

Le résultat de cette exécution de code est à nouveau une chaîne de caractères :

Il a cinquante et un ans.

Concaténation de types mixtes

Que se passe-t-il lorsque nous voulons afficher un texte plus grand et plus complexe, composé de différents types ? Jusqu'à présent, nous avons utilisé des versions de la méthode WriteLine(...) pour un type spécifique. Est-il nécessaire, lorsque nous voulons imprimer différents types à la fois, d'utiliser différentes versions de la méthode WriteLine(...) pour chacun de ces types ? La réponse à cette question est « non », car en C#, nous pouvons unir du texte et d'autres données (par exemple, numériques) en utilisant l'opérateur «+». L'exemple suivant est comme le précédent, mais dans celui-ci, les années (âge) sont de type entier :

  1. int age = 51;
  2. string text = "Il a " + age + " ans.";
  3. Console.WriteLine(text);

Dans l'exemple, la concaténation et l'affichage sur l'écran sont effectuées. Le résultat de l'exemple est le suivant :

Il a 51 ans.

Sur la deuxième ligne de l'exemple de code, nous voyons qu'une concaténation de la chaîne de caractères "Il est" et du type entier "âge" est effectuée. Nous essayons de combiner deux types différents. Cela est possible grâce à la présence de la règle importante suivante.

Lorsqu'une chaîne de caractères est impliquée dans la concaténation avec un autre type, le résultat est toujours une chaîne de caractères.

D'après la règle, il est clair que le résultat de "Il a " + âge est à nouveau une chaîne de caractères et le résultat est ensuite ajouté à la dernière partie de l'expression " ans ". Ainsi, après avoir appelé une chaîne d'opérateurs +, le résultat final est une chaîne et donc la version chaîne de caractères de la méthode WriteLine(...) est appelée.

Pour faire court, l'exemple ci-dessus peut être écrit comme suit :

  1. int age = 51;
  2. Console.WriteLine("Il a " + age + " ans.");

Quelques caractéristiques de la concaténation de chaînes de caractères

Il existe certaines situations intéressantes liées à la concaténation (addition) de chaînes que vous devez connaître et surveiller car elles entraînent des erreurs. L'exemple suivant représente un comportement surprenant du code :

  1. string s = "Quatre : " + 2 + 2;
  2. Console.WriteLine(s);
  3. // Quatre : 22
  4. string s1 = "Quatre : " + (2 + 2);
  5. Console.WriteLine(s1);
  6. // Quatre : 4

Comme le montre l'exemple, l'ordre d'exécution des opérateurs est d'une grande importance p;! Dans notre exemple, la concaténation de "Quatre : " à "2" est d'abord effectuée et le résultat de l'opération est une chaîne de caractères. Après cela, une autre concaténation avec le deuxième nombre est effectuée et le résultat inattendu obtenu est "Quatre : 22" au lieu du "Quatre : 4" attendu. Cela est dû au fait que les opérations sont effectuées de gauche à droite et dans ce scénario, une chaîne de caractères participe à chacune d'elles.

Afin d'éviter cette situation désagréable, nous pouvons utiliser des parenthèses modifiant l'ordre d'exécution des opérateurs et pouvant être utilisées pour obtenir le résultat souhaité. Les parenthèses sont des opérateurs ayant la priorité la plus élevée et font que l'exécution de l'opération "addition" des deux nombres se produit avant la concaténation avec la chaîne de gauche. Ainsi, l'addition des deux nombres est d'abord effectuée, puis ils sont concaténés avec la chaîne de caractères.

Cette erreur est très courante chez les programmeurs débutants car ils ne considèrent pas que la concaténation de chaînes de caractères s'effectue de gauche à droite car l'addition de nombres a la même priorité que la concaténation.

Sortie formatée avec Write(...) et WriteLine(...)

Pour afficher des séries longues et élaborées d'éléments, des options spéciales (également appelées surcharges) des méthodes Write(...) et WriteLine(...) ont été introduites. Ces options ont un concept complètement différent des méthodes standard d'affichage en C#. Leur idée principale est d'adopter une chaîne spéciale, formatée avec des caractères de formatage spéciaux et une liste de valeurs, devant être substituées à «les spécificateurs de format». Voici comment Write(...) est défini dans les bibliothèques C# standard :

  1. public static void Write(string format, object arg0, object arg1, object arg2, object arg3,...);

L'exemple suivant affiche deux fois la même chose mais de manière différente :

  1. string str = "Bonjour le monde!";
  2. // Afficher (de manière normale)
  3. Console.Write(str);
  4. // Afficher (via une chaîne de caractères formatage)
  5. Console.Write("{0}", str);

Le résultat de cet exemple d'exécution est :

Bonjour le monde!Bonjour le monde!

Nous voyons comme résultat "Bonjour le monde!" deux fois sur une ligne. C'est parce qu'il n'y a pas d'affichage de nouvelle ligne dans le programme.

Nous affichons d'abord la chaîne de caractères de manière bien connue afin de voir la différence avec l'autre approche. La deuxième affichage est la mise en forme Write(...) et le premier paramètre est la chaîne de format. Dans ce cas, {0} signifie mettre le premier paramètre après la chaîne de formatage à la place de {0}. L'expression {0} est appelée un espace réservé, c'est-à-dire un emplacement qui sera remplacé par une valeur spécifique lors de l'affichage.

L'exemple suivant expliquera plus en détail ce concept :

  1. string nom = "Sébastien";
  2. int age = 18;
  3. string ville = "Laval";
  4. Console.Write("{0} a {1} ans depuis {2} !\n", nom, age, ville);

Le résultat de cet exemple d'exécution est le suivant :

Sébastien a 18 ans depuis Laval !

À partir de la signature de cette version Write(...), nous avons vu que le premier paramètre est la chaîne de caractères de format. Voici une série de paramètres, étant placés là où nous avons un nombre entre accolades. L'expression {0} signifie mettre à sa place le premier des paramètres soumis après la chaîne de caractères de format (dans ce cas, le nom). Vient ensuite {1} qui signifie remplacer par le deuxième des paramètres (age). Le dernier espace réservé est {2}, qui signifie remplacer par le paramètre suivant (ville). Le dernier est \n, qui est un caractère spécial indiquant le passage à une nouvelle ligne.

Il convient de mentionner qu'en fait, la commande de nouvelle ligne sous Windows est \r\n, et sur les systèmes d'exploitation basés sur Unix - \n. Lorsque vous travaillez avec la console, il n'est pas important que nous utilisions uniquement \n car le flux d'entrée standard considère \n comme \r\n mais si nous écrivons dans un fichier, par exemple, utiliser uniquement \n est incorrect (sous Windows).

Formatage composite

Les méthodes de sortie formatée de la classe Console utilisent la fonction dite de formatage composite. Le formatage composite est utilisé pour l'affichage de la console ainsi que dans certaines opérations avec des chaînes de caractères. Nous avons examiné le formatage composite dans sa forme la plus simple dans l'exemple précédent, mais il a un potentiel bien plus grand que ce que nous avons vu jusqu'à présent. Fondamentalement, le formatage composite utilise deux choses : la chaîne de caractères de formatage composite et une série de paramètre, étant remplacés à certains endroits de la chaîne de caractères.

Chaîne de formatage composite

La chaîne de formatage composite est un mélange de texte normal et d'éléments de formatage. Lors du formatage, le texte normal reste le même que dans la chaîne de caractères et les emplacements des éléments de formatage sont remplacés par les valeurs des paramètres respectifs imprimés selon certaines règles. Ces règles sont spécifiées à l'aide de la syntaxe des éléments de formatage.

Éléments de formatage

Les éléments de formatage offrent la possibilité d'un contrôle puissant sur la valeur affichée et peuvent donc obtenir une forme très compliquée. Le schéma de formation suivant représente la syntaxe générale des éléments de formatage :

{index[,alignement][:formatChaine]}

Comme nous le remarquons, l'élément de formatage commence par une accolade ouvrante { et se termine par une accolade fermante }. Le contenu entre les accolades est divisé en trois composantes dont seul la composante index est obligatoire. Nous allons maintenant examiner chacun d'eux séparément.

Composante d'index

La composante d'index est un entier et indique la position du paramètre dans la liste des paramètres. Le premier paramètre est indiqué par "0", le second par "1",... La chaîne de caractères de formatage composite permet d'avoir plusieurs éléments de formatage liés à un seul et même paramètre. Dans ce cas, la composante d'index de ces éléments est un seul et même numéro. Il n'y a aucune restriction sur la séquence d'appel des paramètres. Par exemple, nous pourrions utiliser la chaîne de caractères de formatage suivante :

  1. Console.Write("{1} a {0} ans depuis {3} !", 18, "Sébastien", 0, "Laval");

Dans les cas où certains paramètres ne sont référencés par aucun des éléments de formatage, ces paramètres sont simplement ignorés et ne jouent aucun rôle. Cependant, il est préférable de supprimer ces paramètres de la liste des paramètres car ils introduisent une complexité inutile et peuvent prêter à confusion.

Dans le cas contraire, lorsqu'un élément de formatage fait référence à un paramètre n'existant pas dans la liste des paramètres, une exception est levée. Cela peut se produire, par exemple, si nous avons un espace réservé de formatage {4} et que nous avons soumis une liste de seulement deux paramètres.

Composante d'alignement

La composante d'alignement est facultatif et indique l'alignement de la chaîne de caractères. Il s'agit d'un entier positif ou négatif et les valeurs positives indiquent l'alignement à droite et les négatives - l'alignement à gauche. La valeur du nombre indique le nombre de positions sur lesquelles aligner le nombre. Si la chaîne de caractères que nous voulons représenter a une longueur supérieure ou égale à la valeur du nombre, alors ce nombre est ignoré. Si elle est inférieure, cependant, les positions non remplies sont remplies par des espaces.

Par exemple, essayons le formatage suivant :

  1. Console.WriteLine("{0,7}", 123);
  2. Console.WriteLine("{0,7}", 1234);
  3. Console.WriteLine("{0,7}", 12);
  4. Console.Write("{0,-7}", 123);
  5. Console.WriteLine("--fin");

Il affichera le résultat suivant :

    123
   1234
     12
123    --fin

Si nous décidons d'utiliser la composante d'alignement, nous devons le séparer du composant d'index par une virgule comme cela est fait dans l'exemple ci-dessus.

La composante "formatChaine"

Cette composante spécifie le formatage spécifique de la chaîne de caractères. Il varie en fonction du type de paramètre. Il existe trois principaux types de composantes formatChaine :

Composantes de chaîne de caractères de format pour les nombres

Cette composante de type formatChaine possède deux sous-types : les formats définis par défaut et les formats définis par l'utilisateur (chaînes de caractères de format personnalisées).

Formats standard pour les nombres

Ces formats sont définis par l'un des nombreux spécificateurs de format, qui sont des lettres d'une importance particulière. Après le spécificateur de format, il peut y avoir un entier positif appelé précision, ayant une signification différente pour les différents spécificateurs. Lorsqu'il affecte le nombre de décimales après la virgule, le résultat est arrondi. Le tableau suivant décrit les spécificateurs et leur signification en termes de précision :

Spécificateur Description
"C" ou "c" Indique la devise et le résultat sera affiché avec le symbole de devise pour la «culture» actuelle (par exemple, l'anglais). La précision indique le nombre de décimales après la virgule.
"D" ou "d" Un nombre entier. La précision indique le nombre minimum de caractères pour représenter la chaîne et, si nécessaire, des zéros sont ajoutés au début.
"E" ou "e" Notation exponentielle. La précision indique le nombre de décimales après la virgule.
"F" ou "f" Nombre entier ou décimal. La précision indique le nombre de signes après la virgule.
N" ou "n" Équivalent à «F» mais représente également le séparateur correspondant pour les milliers, les millions,... (par exemple, dans la langue anglaise, le nombre «1000» est souvent représenté par «1 000» - avec une virgule entre le chiffre 1 et les zéros).
"P" ou "p" Pourcentage : multiplie le nombre par 100 et affiche le caractère de pourcentage au début. La précision indique le nombre de signes après la virgule décimale.
"X" ou "x" Affiche le nombre dans le système numérique hexadécimal. Cela ne fonctionne que pour les nombres entiers. La précision indique le nombre minimum de signes pour afficher la chaîne de caractères, car ceux manquant sont complétés par des zéros au début.

Une partie du formatage est déterminée par les paramètres «culture» actuels, étant repris par défaut des paramètres régionaux du système d'exploitation. Les «cultures» sont un ensemble de règles valables pour une langue ou un pays donné et indiquant quel caractère doit être utilisé comme séparateur décimal, comment la devise est affichée,... Par exemple, pour la «culture» japonaise, la devise est affichée en ajoutant «¥» après le montant, tandis que pour la «culture» américaine, le caractère «$» est affiché avant le montant.

Voyons quelques exemples d'utilisation des spécificateurs représentés dans le tableau ci-dessus. Dans le code ci-dessous, nous supposons que les paramètres régionaux sont le Canada français, donc la devise sera affichée en canadien français, le séparateur décimal sera «,» et le séparateur de milliers sera un espace (les paramètres régionaux peuvent être modifiés à partir du Panneau de configuration de Windows) :

  1. class StandardNumericFormats {
  2.  static void Main() {
  3.   Console.WriteLine("{0:C2}", 123.456);
  4.   //Sortie : 123,46 $.
  5.   Console.WriteLine("{0:D6}", -1234);
  6.   //Sortie : -001234
  7.   Console.WriteLine("{0:E2}", 123);
  8.   //Sortie : 1,23E+002
  9.   Console.WriteLine("{0:F2}", -123.456);
  10.   //Sortie : -123,46
  11.   Console.WriteLine("{0:N2}", 1234567.8);
  12.   //Sortie : 1 234 567,80
  13.   Console.WriteLine("{0:P}", 0.456);
  14.   //Sortie : 45,60 %
  15.   Console.WriteLine("{0:X}", 254);
  16.   //Sortie : FE
  17.  }
  18. }

Si nous exécutons le même code avec la culture anglaise (États-Unis), le résultat sera le suivant :

$123.46
-001234
1.23E+002
-123.46
1,234,567.80
45.60 %
FE

Formats personnalisés pour les nombres

Tous les formats n'étant pas standard sont attribués aux formats utilisateur (personnalisés). Pour les formats personnalisés, un ensemble de spécificateurs est également défini et la différence avec les formats standard est qu'un certain nombre de spécificateurs peuvent être utilisés (dans les formats standard, un seul spécificateur est utilisé). Le tableau suivant répertorie les différents spécificateurs et leur signification :

Spécificateur Description
0 Indique un chiffre. Si à cette position du résultat il manque un chiffre, un zéro est écrit à la place.
# Indique un chiffre. N'affiche rien si à cette position dans le résultat il manque un chiffre.
. Séparateur décimal pour la «culture» respective.
, Séparateur de milliers pour la «culture» respective.
% Multiplie le résultat par 100 et imprime le caractère pour le pourcentage.
E0 ou E+0 ou E-0 Indique une notation exponentielle. Le nombre de zéros indique le nombre de signes de l'exposant. Le signe «+» signifie que nous voulons toujours représenter également le signe du nombre tandis que le signe moins signifie que le signe doit être affiché uniquement si la valeur est négative.

Il existe de nombreuses caractéristiques concernant l'utilisation de formats personnalisés pour les nombres, mais elles ne seront pas abordées ici. Vous pouvez trouver plus d'informations dans MSDN. Voici quelques exemples simples illustrant comment utiliser des chaînes de formatage personnalisées (le résultat est donné pour la culture américaine) :

  1. class CustomNumericFormats {
  2.  static void Main() {
  3.   Console.WriteLine("{0:0.00}", 1);
  4.   //Output: 1.00
  5.   Console.WriteLine("{0:#.##}", 0.234);
  6.   //Output: .23
  7.   Console.WriteLine("{0:#####}", 12345.77);
  8.   //Output: 12346
  9.   Console.WriteLine("{0:(0#) ### ## ##}", 27342525);
  10.   //Output: (02) 734 25 25
  11.   Console.WriteLine("{0:%##}", 0.234);
  12.   //Output: %23
  13.  }
  14. }

Composantes de chaîne de caractères de format pour les dates

Lors du formatage des dates, nous avons à nouveau une séparation entre les formats standard et personnalisés.

Formats de date définis par défaut

Étant donné que les formats définis par défaut sont nombreux, nous n'en citerons que quelques-uns. Le reste peut être facilement vérifié sur MSDN.

Spécificateur Format (pour la «culture» en anglais (États-Unis))
d 2/27/2012
D February 27, 2012
t 17:30 (heure)
T 17:30:22 (heure)
Y ou y February 2012 (uniquement le mois et l'année)

Formats de date personnalisés

Comme pour les formats personnalisés pour les nombres, nous avons ici plusieurs spécificateurs de format et nous pouvons en combiner plusieurs. Comme il existe de nombreux spécificateurs, nous n'en montrerons que quelques-uns, que nous utiliserons pour démontrer comment utiliser les formats personnalisés pour les dates. Considérez le tableau suivant :

Spécificateur Format (pour la «culture» en anglais (États-Unis))
d Jour - du 1 au 31
dd Journée - du 01 au 31
M Mois - de 1 à 12
MM Mois - de 01 à 12
yy Les deux derniers chiffres de l'année (de 00 à 99)
yyyy Année écrite en 4 chiffres (exemple : 2012)
hh Heure - de 00 à 11
HH Heure - de 00 à 23
m Minutes - de 0 à 59
mm Minutes - de 00 à 59
s Secondes - de 0 à 59
ss Secondes - de 00 à 59

En utilisant ces spécificateurs, nous pouvons insérer différents séparateurs entre les différentes parties de la date, comme «.» ou «/». Voici quelques exemples :

  1. DateTime d = new DateTime(2024, 02, 16, 22, 40, 00);
  2. Console.WriteLine("{0:dd/MM/yyyy HH:mm:ss}", d);
  3. Console.WriteLine("{0:d.MM.yy}", d);

L'exécution de ces exemples donne le résultat suivant pour la culture britannique :

16/02/2024 22:40:00
16.02.24

Notez que le résultat peut varier en fonction de la culture actuelle. Par exemple, si nous exécutons le même code dans la culture bulgare, le résultat sera différent :

16.02.2024 22:40:00
16.02.24

Composantes d'énumération de chaîne de caractères de format

Les énumérations (types répertoriés) sont des types de données pouvant prendre comme valeur l'une des nombreuses valeurs possibles prédéfinies (par exemple, les sept jours de la semaine).

Dans les énumérations, il y a très peu de choses à formater. Quatre spécificateurs de format standard sont définis comme ceci :

Spécificateur Format
G ou g Représente l'énumération sous forme de chaîne de caractères.
D ou d Représente l'énumération sous forme de nombre.
X ou x Représente l'énumération sous forme de nombre dans un système numérique hexadécimal et avec huit chiffres.

Voici quelques exemples :

  1. Console.WriteLine("{0:G}", DayOfWeek.Friday);
  2. Console.WriteLine("{0:D}", DayOfWeek.Friday);
  3. Console.WriteLine("{0:X}", DayOfWeek.Friday);

En exécutant le code ci-dessus, nous obtenons le résultat suivant :

Friday
5
00000005

Formatage des chaînes et localisation

Lors de l'utilisation de chaînes de caractères de format, il est possible qu'un même programme affiche différentes valeurs en fonction des paramètres de localisation du système d'exploitation. Par exemple, lors de l'affichage du mois à partir d'une date donnée si la localisation actuelle est en anglais, il s'affichera en anglais, par exemple «August», tandis que si la localisation est en français, il s'affiche en français, par exemple «Août». Lors du lancement d'une application console, elle récupère automatiquement la localisation du système d'exploitation (paramètres de culture) et l'utilise pour lire et écrire des données formatées (comme des nombres, des dates, des devises,...).

La localisation dans .NET est également appelée «culture» ??et peut être modifiée manuellement par la classe System.Globalization.CultureInfo. Voici un exemple dans lequel nous imprimons un nombre et une date selon la localisation américain et canadienne française :

  1. using System;
  2. using System.Threading;
  3. using System.Globalization;
  4. class CultureInfoExample {
  5.     static void Main() {
  6.         DateTime d = new DateTime(2024, 02, 16, 22, 40, 0);
  7.         Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
  8.         Console.WriteLine("{0:N}", 1234.56);
  9.         Console.WriteLine("{0:D}", d);
  10.         Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fr-CA");
  11.         Console.WriteLine("{0:N}", 1234.56);
  12.         Console.WriteLine("{0:D}", d);
  13.     }
  14. }

Au démarrage de l'exemple, le résultat suivant est obtenu :

1,234.560
Friday, February 16, 2024
1 234,560
vendredi 16 février 2024

Entrée de la console

Comme nous l'avons expliqué au début de cette page, la communication par console est la plus adaptée aux petites applications car elle est la plus simple à mettre en oeuvre. Le périphérique d'entrée standard est la partie du système d'exploitation contrôlant l'endroit où le programme recevra ses données d'entrée. Par défaut, le «périphérique d'entrée standard» lit son entrée à partir d'un pilote «attaché» au clavier. Cela peut être modifié et l'entrée standard peut être redirigée vers un autre emplacement, par exemple vers un fichier, mais cela se fait rarement.

Chaque langage de programmation dispose d'un mécanisme de lecture et d'écriture sur la console. L'objet contrôlant le flux d'entrée standard en C# est Console.In.

Depuis la console, nous pouvons lire différentes données :

En fait, pour lire le flux d'entrée standard, Console.In est rarement utilisé directement. La classe Console fournit deux méthodes Console.Read() et Console.ReadLine() s'exécutant sur ce flux et effectuant généralement la lecture depuis la console.

Lecture via Console.ReadLine()

La méthode Console.ReadLine() offre une grande commodité pour la lecture depuis la console. Comment fonctionne-t-elle ? Lorsque cette méthode est appelée, le programme arrête son travail et attend une entrée de la console. L'utilisateur saisit une chaîne de caractères sur la console et appuie sur la touche Enter. À ce moment, la console comprend que l'utilisateur a terminé la saisie et lit la chaîne de caractères. La méthode Console.ReadLine() renvoie comme résultat la chaîne saisie par l'utilisateur. Maintenant, il est peut-être clair pourquoi cette méthode porte ce nom.

L'exemple suivant illustre le fonctionnement de Console.ReadLine() :

  1. class ExempleReadLine {
  2.  static void Main() {
  3.   Console.Write("Veuillez entrer votre prénom :");
  4.   string firstName = Console.ReadLine();
  5.   Console.Write("Veuillez entrer votre nom de famille :");
  6.   string lastName = Console.ReadLine();
  7.   Console.WriteLine("Bonjour, {0} {1}!", firstName, lastName);
  8.  }
  9. }
  10.  
  11. // Output: Veuillez entrer votre prénom : Sylvain
  12. // Veuillez entrer votre nom de famille : Maltais
  13. // Bonjour, Sylvain Maltais !

Nous voyons à quel point il est facile de lire du texte depuis la console en utilisant la méthode Console.ReadLine() :

Lecture via Console.Read()

La méthode Read() se comporte légèrement différemment de ReadLine(). Au début, elle ne lit qu'un seul caractère et non la ligne entière. L'autre différence significative est que la méthode ne renvoie pas directement le caractère lu mais son code. Si nous voulons utiliser le résultat comme un caractère, nous devons le convertir en caractère ou utiliser la méthode Convert.ToChar() sur celui-ci. Il y a une caractéristique importante : le caractère n'est lu que lorsque la touche Enter est enfoncée. Ensuite, la chaîne entière écrite sur la console est transférée dans le tampon de la chaîne d'entrée standard et la méthode Read() en lit le premier caractère. Lors des appelles suivantes de la méthode, si le tampon n'est pas vide (c'est-à-dire qu'il y a déjà des caractères saisis mais toujours non lus), l'exécution du programme ne s'arrêtera pas et n'attendra pas, mais lira directement le caractère suivant du tampon et ainsi jusqu'à ce que le tampon soit vide. Ce n'est qu'à ce moment-là que le programme attendra à nouveau une saisie utilisateur si Read() est à nouveau appelé. Voici un exemple :

  1. class UsingRead {
  2.  static void Main() {
  3.   int codeRead = 0;
  4.   do {
  5.    codeRead = Console.Read();
  6.    if (codeRead != 0) {
  7.     Console.Write((char)codeRead);
  8.    }
  9.   } while (codeRead != 10);
  10.  }
  11. }

Ce programme lit une ligne saisie par l'utilisateur et l'affiche caractère par caractère. Cela est possible grâce à une petite astuce : nous savons déjà que la touche Enter saisit en fait deux caractères dans le tampon. Il s'agit du code "retour chariot" (Unicode 13) suivi du code "saut de ligne" (Unicode 10). Pour comprendre qu'une ligne est terminée, nous recherchons un caractère avec le code 10 dans la table Unicode. Ainsi, le programme ne lit qu'une seule ligne et sort de la boucle.

Il convient de mentionner que la méthode Console.Read() est rarement utilisée dans la pratique s'il existe une alternative à l'utilisation de Console.ReadLine(). La raison en est que la possibilité de se tromper avec Console.Read() est bien plus grande que si nous choisissons une approche alternative et le code sera très probablement inutilement compliqué.

Lecture de nombres

La lecture de nombres depuis la console en C# ne se fait pas directement. Pour lire un nombre, nous devons au préalable avoir lu l'entrée sous forme de chaîne (en utilisant ReadLine()) puis convertir cette chaîne en nombre. L'opération de conversion d'une chaîne en un autre type est appelée analyse. Tous les types primitifs ont des méthodes d'analyse. Nous allons donner un exemple simple de lecture et d'analyse de nombres :

  1. class ReadingNumbers
  2. {
  3.     static void Main()
  4.     {
  5.         Console.Write("x = ");
  6.         int x = int.Parse(Console.ReadLine());
  7.         Console.Write("y = ");
  8.         int y = int.Parse(Console.ReadLine());
  9.         Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
  10.         Console.WriteLine("{0} * {1} = {2}", x, y, x * y);
  11.         Console.Write("f - ");
  12.         double f = double.Parse(Console.ReadLine());
  13.         Console.WriteLine("{0} * {1} / {2} = {3}", x, y, f, x * y / f);
  14.     }
  15. }

Le résultat de l'exécution du programme pourrait être le suivant (à condition que nous saisissions 5, 6 et 7,5 en entrée) :

x = 3
y = 7
3 + 7 = 10
3 * 7 = 21
f - 3,7
3 * 7 / 3,7 = 5,675675675675675

Dans cet exemple particulier, la particularité est que nous utilisons des méthodes d'analyse de types numériques et lorsqu'un résultat erroné est transmis (comme du texte), cela provoquera une erreur (exception) System.FormatException. Cela est particulièrement vrai lors de la lecture de nombres réels, car le délimiteur utilisé entre la partie entière et la partie fractionnaire est différent dans diverses cultures et dépend des paramètres régionaux du système d'exploitation.

Le séparateur des nombres à virgule flottante dépend des paramètres de langue actuels du système d'exploitation (Options régionales et linguistiques dans Windows). Sur certains systèmes, la virgule peut être utilisée comme séparateur, sur d'autres, le point. La saisie d'un point au lieu d'une virgule provoquera une exception System.FormatException lorsque les paramètres de langue actuels utilisent une virgule.

Pour l'instant, vous pouvez considérer que lorsque le programme génère une erreur, celle-ci est associée à l'apparition d'une exception affichant des informations détaillées sur l'erreur sur la console. Par exemple, supposons que les paramètres régionaux de l'ordinateur soient canadien français et que nous exécutions le code suivant :

  1. Console.Write("Entrez un nombre à virgule flottante : ");
  2. string ligne = Console.ReadLine();
  3. double nombre = double.Parse(ligne);
  4. Console.WriteLine("Vous avez saisi : {0}", nombre);

Si nous saisissons le nombre «3.14» (avec un séparateur décimal incorrect pour les paramètres canadiens français), nous obtiendrons l'exception suivante (message d'erreur) :

System.FormatException
  HResult=0x80131537
  Message=The input string '3.14' was not in a correct format.
  Source=System.Private.CoreLib
  Arborescence des appels de procédure :
   à System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
   à System.Double.Parse(String s)
   à ReadingNumbers.Main() dans C:\Users\Sylvain Maltais\source\repos\ReadingNumbers\ReadingNumbers\Program.cs :ligne 12

Analyse conditionnelle des nombres

Lors de l'analyse d'une chaîne en un nombre à l'aide de la méthode Int32.Parse(string) ou de Convert.ToInt32(string), si la chaîne de caractères soumise n'est pas un nombre, nous obtenons une exception. Il est parfois nécessaire d'intercepter l'échec de l'analyse et d'imprimer un message d'erreur ou de demander à l'utilisateur de saisir une nouvelle valeur.

L'interception d'un nombre saisi de manière incorrecte lors de l'analyse d'une chaîne de caractères peut être effectuée de deux manières :

Considérons l'analyse conditionnelle des nombres dans .NET Framework. La méthode Int32.TryParse(...) accepte deux paramètres : une chaîne de caractères d'analyse et une variable pour enregistrer le résultat de l'analyse. Si l'analyse réussit, la méthode renvoie la valeur true. Pour plus de clarté, considérons un exemple :

  1. string str = Console.ReadLine();
  2. int maValeur;
  3. bool parseSuccess = Int32.TryParse(str, out maValeur);
  4. Console.WriteLine(parseSuccess ? "Le carré du nombre est " + maValeur * maValeur + "." : "Numéro invalide !");

Dans l'exemple, l'analyse conditionnelle d'une chaîne de caractères saisie depuis la console dans le type entier Int32 est effectuée. Si nous saisissons comme entrée "3", l'analyse sera réussie, donc le résultat de TryParse() sera vrai, et le nombre analysé sera enregistré dans la variable intValue et sur la console le nombre au carré sera affiché :

Le carré du nombre est 9 !

Si nous essayons d'analyser un numéro invalide tel que «xyz», TryParse() renverra un résultat faux et l'utilisateur sera averti qu'il a saisi un numéro invalide :

Numéro invalide !

Notez que la méthode TryParse(), en tant que résultat de son travail, renvoie simultanément deux valeurs : le nombre analysé (en tant que paramètre de sortie) et une valeur booléenne en tant que résultat de l'invocation de la méthode. Le renvoi de plusieurs valeurs à la fois est possible car l'une des valeurs est renvoyée en tant que paramètre de sortie (paramètre out). Les paramètres de sortie renvoient une valeur dans une variable prédéfinie à cet effet qui coïncide avec leur type. Lors de l'appel d'une méthode, les paramètres de sortie doivent être précédés du mot-clef out.

Lecture par Console.ReadKey()

La méthode Console.ReadKey() attend que la touche soit enfoncée sur la console et lit son équivalent en caractères sans qu'il soit nécessaire d'appuyer sur Enter. Le résultat de l'appel de ReadKey() est une information sur la touche enfoncée (ou plus précisément une combinaison de touches) sous la forme d'un objet de type ConsoleKeyInfo. L'objet obtenu contient le caractère saisi par la combinaison de touches enfoncée (propriété KeyChar) ainsi que des informations sur les touches Shift, Ctrl et Alt (propriété Modifiers). Par exemple, si nous appuyons sur Shift+A, nous lirons une lettre majuscule 'A' tandis que dans la propriété Modifiers, nous aurons l'indicateur Shift. Voici un exemple :

  1. ConsoleKeyInfo key = Console.ReadKey();
  2. Console.WriteLine();
  3. Console.WriteLine("Caractère saisi :" + key.KeyChar);
  4. Console.WriteLine("Touches spéciales : " + key.Modifiers);

Si nous exécutons le programme et appuyons sur Shift+A, nous obtiendrons le résultat suivant :

A
Caractère saisi : A
Touches spéciales : Shift

Nous allons considérer quelques exemples supplémentaires d'entrée et de sortie de console qui nous montreront quelques techniques intéressantes.

Affichage d'une lettre

Voici un exemple pratique représentant l'entrée de la console et le texte formaté sous la forme d'une lettre :

  1. class PrintingLetter {
  2.  static void Main() {
  3.   Console.Write("Entrez le nom de la personne :");
  4.   string person = Console.ReadLine();
  5.   Console.Write("Entrez le nom du livre : ");
  6.   string book = Console.ReadLine();
  7.   string from = "Équipe d'auteurs";
  8.   Console.WriteLine(" Cher {0},", person);
  9.   Console.Write("Nous sommes heureux de vous informer que \"{1}\" est le meilleur livre canadien. {2}" + 
  10.                 "Les auteurs du livre vous souhaitent bonne chance {0}!{2}",person, book, Environment.NewLine);
  11.   Console.WriteLine(" Le vôtre,");
  12.   Console.WriteLine(" {0}", from);
  13.  }
  14. }

Le résultat de l'exécution du programme ci-dessus pourrait être le suivant :

Entrez le nom de la personne : Sylvain
Entrez le nom du livre : Programmation avec C#
Chers lecteurs,
Nous sommes heureux de vous informer que «Programmation avec C#» est le meilleur livre canadien.
Les auteurs du livre vous souhaitent bonne chance Sylvain !
Cordialement,
L'équipe des auteurs

Dans cet exemple, nous avons un modèle de lettre. Le programme «pose» quelques questions à l'utilisateur et lit depuis la console les informations nécessaires à l'impression de la lettre en remplaçant les spécificateurs de formatage par les données renseignées par l'utilisateur.

Aire d'un rectangle ou d'un triangle

Nous allons considérer un autre exemple : le calcul d'une aire d'un rectangle ou d'un triangle :

  1. class CalculatingRectangleArea {
  2.  static void Main() {
  3.   Console.WriteLine("Ce programme calcule l'aire d'un rectangle ou d'un triangle");
  4.   Console.WriteLine("Entrez a et b (pour rectangle) ou a et h (pour triangle) : ");
  5.   int a = int.Parse(Console.ReadLine());
  6.   int b = int.Parse(Console.ReadLine());
  7.   Console.WriteLine("Entrez 1 pour un rectangle ou 2 pour un triangle :");
  8.   int choice = int.Parse(Console.ReadLine());
  9.   double area = (double) (a * b) / choice;
  10.   Console.WriteLine("La surface de votre figure est " + area);
  11.  }
  12. }

Le résultat de l'exécution de l'exemple ci-dessus est le suivant :

Ce programme calcule l'aire d'un rectangle ou d'un triangle
Entrez a et b (pour rectangle) ou a et h (pour triangle) :
7
3
Entrez 1 pour un rectangle ou 2 pour un triangle :
2
La surface de votre figure est 10,5


Dernière mise à jour : Samedi, le 21 décembre 2024