Posts Tagged ‘console’

Des cadres en ligne de commande

Wednesday, April 21st, 2010

Pour avoir de beaux cadres dans un programme Windows en mode console, voici les caractères à utiliser :

// cadre simple
std::cout << "ÚÄÂÄ¿\n";
std::cout << "³ ³ ³\n";
std::cout << "ÃÄÅÄ´\n";
std::cout << "³ ³ ³\n";
std::cout << "ÀÄÁÄÙ\n";

// cadre double
std::cout << "ÉÍËÍ»\n";
std::cout << "º º º\n";
std::cout << "ÌÍÎ͹\n";
std::cout << "º º º\n";
std::cout << "ÈÍÊͼ\n";

Ce qui affichera de zolis cadres !

Attention : cette façon de faire n’est pas portable, car elle dépend complètement du jeu de caractères utilisé par la ligne de commande.

cin et les erreurs

Wednesday, April 21st, 2010

Dans une application console, c’est l’objet cin qui est utilisé pour saisir une valeur au clavier. La valeur saisie est envoyée au moyen de l’opérateur de flux entrant (>>) vers la variable qui recevra la saisie clavier. Le type de la variable déterminera le type de donnée à saisir au clavier.

// Saisie d’un nombre entier
int NombreEntier = 0;
std::cin >> NombreEntier;

// Saisie d’un nombre réel
float NombreReel = 0.;
std::cin >> NombreReel;

// Saisie d’un caractère
char Caractere = 0;
std::cin >> Caractere;

Si l’utilisateur saisi autre chose que ce qui est attendu, cin passe en état d’échec.

Cela signifie que si l’utilisateur saisi une lettre alors que c’est un nombre entier qui est attendu, cin se met en état d’échec (failed state). Voici un exemple très simple qui démontre le problème :

#include <iostream>

int main() {
   int Nombre1 = 12345;
   int Nombre2 = 999;

   std::cout << "Entrez un premier nombre entier : ";
   std::cin >> Nombre1;
   std::cout << "Entrez un second nombre entier : ";
   std::cin >> Nombre2;

   std::cout << "Vous avez saisi les nombres " << Nombre1
             << " et " << Nombre2 << "\n";
   return 0;
}

Si ce qui est saisi ne ressemble pas à un nombre entier, le flux cin passe en état d’échec (ligne 8 ) et toutes les demandes de saisie ultérieures (ligne 10) rendront immédiatement la main au programme sans que rien ne se passe.

Si l’appel à cin est fait au sein d’une boucle (par exemple pour vérifier si le nombre saisi est compris dans un intervalle donné) et que cin passe en état d’échec, le programme tournera en boucle infinie.

#include <iostream>

int main() {
   int Nombre = 0;

   while (true) {
      std::cout << "Entrez un nombre compris entre 1 et 100 : ";
      std::cin >> Nombre;
      if ((Nombre >= 1) && (Nombre <= 100))
         break;
   }
   std::cout << "Vous avez saisi le nombre " << Nombre << "\n";
   return 0;
}

Pour éviter ce problème, il faut tester la valeur de retour du flux cin. Si celle-ci est fausse, c’est qu’une erreur s’est produite et que cin est en état d’échec. Il faut alors rétablir le flux cin en purgeant tout ce qu’il contient.

#include <iostream>
#include <limits>

int main() {
   int Nombre = 0;

   while (true) {
      std::cout << "Entrez un nombre compris entre 1 et 100 : ";
      if (!(std::cin >> Nombre)) {
         // Purge du flux cin
         std::cin.clear();
         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      }

      if ((Nombre >= 1) && (Nombre <= 100))
         break;
   }
   std::cout << "Vous avez saisi le nombre " << Nombre << "\n";
   return 0;
}

Voici l’exemple précédent réécrit pour tenir compte de saisies erronées. Les lignes 11 et 12 se chargent de purger le flux cin et de le remettre dans un état valide.

Bien sûr, il serait malvenu d’écrire tout ce code supplémentaire chaque fois que le flux cin est utilisé. Pour éviter ces répétitions, il suffit d’écrire une fonction de saisie d’un nombre entier, qui se charge de traiter l’état d’erreur du flux cin.

Selon les besoins, cette fonction pourra être plus ou moins complexe. Voici une version minimale :

// Fonction de saisie d'un nombre entier au clavier
//@return le nombre entier saisi, ou zéro en cas de saisie invalide.
int getInteger() {
   int Nombre = 0;
   if (!(std::cin >> Nombre)) {
      // Purge du flux cin
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   }
   return Nombre;
}

Voici le premier programme de cette annexe réécrit de façon à utiliser la fonction ci-dessus :

#include <iostream>
#include <limits>

// Fonction de saisie d'un nombre entier au clavier
//@return le nombre entier saisi, ou zéro en cas de saisie invalide.
int getInteger() {
   int Nombre = 0;
   if (!(std::cin >> Nombre)) {
      // Purge du flux cin
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   }
   return Nombre;
}

// Programme principal
int main() {
   int Nombre1 = 12345;
   int Nombre2 = 999;

   std::cout << "Entrez un premier nombre entier : ";
   Nombre1 = getInteger();
   std::cout << "Entrez un second nombre entier : ";
   Nombre2 = getInteger();

   std::cout << "Vous avez saisi les nombres " << Nombre1
             << " et " << Nombre2 << "\n";
   return 0;
}

Programme en mode console avec Qt Creator

Thursday, February 4th, 2010

Lorsqu’on souhaite développer une application en mode console avec Qt Creator (1.3.1) qui soit multi-plateforme Mac et Windows, il y a quelques problèmes à régler.

Comme exemple, nous allons essayer de faire fonctionner correctement le petit programme suivant :

#include <iostream>

int main() {
   std::cout << "Quel est ton nom : ";
   std::string Nom;
   std::cin >> Nom;
   std::cout << "Salut " << Nom << " !\n";
   return 0;
}

Mac OS X

ur Mac OS X, avec la configuration par défaut, la sortie standard est dirigée sur l’onglet Sortie de l'application de Qt Creator. Cela pose néanmoins un problème de taille : cet onglet ne gère pas l’entrée standard. Notre programme simple ne fonctionnera donc pas.

Pour résoudre ce problème, il faut forcer l’exécution de notre programme dans un terminal.

Pour ce faire, il faut modifier les paramètres d’exécution du projet. Afficher les détails et cocher la case Exécuter dans un terminal.

Malheureusement, cette façon de faire amène encore un petit problème à résoudre.
Sur Mac OS X, c’est un terminal XTerm qui sera utilisé, mais dans la configuration standard de Qt Creator, l’application XTerm n’est pas trouvable. Il faut en fait préciser le chemin complet de l’application.

Ouvrir les préférences de Qt Creator et aller dans la configuration Environnement : Général.

Dans la zone Terminal, indiquer le chemin complet :

/usr/x11/bin/xterm -e

Windows

Sur Windows, la configuration par défaut démarre une fenêtre de commande, dans laquelle s’affiche la sortie standard. L’entrée standard est correctement gérée.

Par contre, il subsiste deux problèmes :

  • Lorsque le programme est terminé, la fenêtre de commande disparaît immédiatement, ce qui empêche de voir la sortie finale du programme.
  • Si l’on souhaite déboguer notre programme, la fenêtre de commande n’est plus ouverte et la sortie standard s’affiche dans l’onglet Sortie de l'application de Qt Creator. L’entrée standard n’est pas gérée.

Pour résoudre ces problèmes, il faut forcer l’exécution de notre programme dans un terminal.

Pour ce faire, il faut modifier les paramètres d’exécution du projet. Afficher les détails et cocher la case Exécuter dans un terminal.

Les deux

Notre programme fonctionne maintenant correctement, aussi bien en ce qui concerne la sortie standard que l’entrée standard. Le déboguage se fait également au travers du terminal.

Reste le problème des accents concernant la phrase automatique Appuyez sur ENTRÉE pour fermer cette fenêtre.

Pour se débarrasser de ces caractères cabalistiques, la solution la plus simple est de démarrer Qt Creator en anglais.