import java.lang.String;
import java.io.*;
import java.util.*;
/**
 * La classe <code>Keyboard</code> facilite la lecture de données
 * tapées sur le clavier. Par exemple,
 * <code> int i = Keyboard.readInt()</code> permet de lire un entier
 * sur le clavier et de ranger sa valeur dans i.
 * Les données qui peuvent être lues sont les 
 * <code>int, char, long, double, String</code>
 * Plusieurs données sur une même ligne sont séparées par au moins un
 * espace. Les fonctions viennent en plusieurs formes; avec ou sans prompt,
 * et avec vérification d'appartenance à un intervalle. Par exemple
<pre>
Keyboard.readChar("Donnez un caractère entre a et f ", 'a', 'f'))
</pre>
 * affiche d'abord l'invite, puis boucle jusqu'à l'obtention d'un caractère
 * entre 'a' et 'f' (y compris 'a' et f')
 */
public class Keyboard {
/*
  String readString(String prompt)
  String readString() 
  int readInt() 
  int readInt(String prompt) 
  int readInt(int minimale, int maximale) 
  int readInt(String prompt, int minimale, int maximale) 
  long readLong() 
  long readLong(String prompt) 
  long readLong(long minimale, long maximale) 
  long readLong(String prompt, long minimale, long maximale)
  double readDouble() 
  double readDouble(String prompt) 
  double readDouble(double minimale, double maximale) 
  double readDouble(String prompt, double minimale, double maximale)
  char readChar() 
  char readChar(String prompt) 
  char readChar(char minimale, char maximale) 
  char readChar(String prompt, char minimale, char maximale)
*/

  private static BufferedReader in =
    new BufferedReader(new InputStreamReader(System.in));
  private static StringTokenizer epelleur = new StringTokenizer("");
  private static void prompter(String prompt) {
    if (prompt != null) {
      System.out.print(prompt);
      System.out.flush();
    }
  }
  private Keyboard() {}
  private static String getString() {
    try {
      return in.readLine();
    }
    catch(IOException e) {
      return "";
    }
  }
  private static void miseAJourEpelleur() {
    while (0 == epelleur.countTokens()) 
      epelleur = new StringTokenizer(getString());
  }
  /**
   * Retourne une chaîne entrée au clavier. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * @param prompt l'invite affichée
   * @return la chaîne lue
   * @see #readString()
   */
  public static String readString(String prompt) {
    prompter(prompt);
    return readString();
  }
  /**
   * Retourne une chaîne entrée au clavier. 
   * @return la chaîne lue
   * @see #readString(String)
   */
  public static String readString() {
    miseAJourEpelleur();
    try {
      return epelleur.nextToken();
    }
    catch(NoSuchElementException exc) {
      return "";
    }
  }
  /**
   * Retourne un entier entré au clavier. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @param prompt l'invite affichée
   * @return l'entier lu
   * @see #readInt()
   */
  public static int readInt(String prompt) {
    return (int) readLong(prompt);
  }
  /**
   * Retourne un entier entré au clavier. 
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @return l'entier lu
   * @see #readInt(String)
   * @see #readInt(int, int)
   * @see #readInt(String, int, int)
   */
  public static int readInt() {
    return (int) readLong();
  }
  /**
   * Retourne un entier entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param minimale valeur minimale pour l'entier à lire
   * @param maximale valeur maximale pour l'entier à lire
   * @return l'entier lu
   * @see #readInt()
   * @see #readInt(String)
   * @see #readInt(String, int, int)
   */
  public static int readInt(int minimale, int maximale) {
    return (int) readLong( minimale, maximale);
  }
  /**
   * Retourne un entier entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour l'entier à lire
   * @param maximale valeur maximale pour l'entier à lire
   * @return l'entier lu
   * @see #readInt()
   * @see #readInt(String)
   * @see #readInt(int, int)
   */
  public static int readInt(String prompt, int minimale, int maximale) {
	return (int) readLong(prompt, minimale, maximale);
    }
  /**
   * Retourne un entier long entré au clavier. 
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @return l'entier long lu
   * @see #readLong(String)
   * @see #readLong(long, long)
   * @see #readLong(String, long, long)
   */
  public static long readLong() {
    return readLong(null);
  }
  /**
   * Retourne un entier long entré au clavier. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @return l'entier long lu
   * @see #readLong()
   * @see #readLong(long, long)
   * @see #readLong(String, long, long)
   */
  public static long readLong(String prompt) {
    try {
      return Long.parseLong(readString(prompt));
    }
    catch(NumberFormatException exception) {
      System.out.println("Erreur. Donnez un entier : ");
      return  readLong();
    }
  }
  /**
   * Retourne un entier long entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour l'entier long à lire
   * @param maximale valeur maximale pour l'entier long à lire
   * @return l'entier long lu
   * @see #readLong()
   * @see #readLong(String)
   * @see #readLong(String, long, long)
   */
  public static long readLong(long minimale, long maximale) {
    return readLong(null, minimale, maximale);
  }
  /**
   * Retourne un entier long entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour l'entier long à lire
   * @param maximale valeur maximale pour l'entier long à lire
   * @return l'entier long lu
   * @see #readLong()
   * @see #readLong(String)
   * @see #readLong(long, long)
   */
  public static long readLong(String prompt, long minimale, long maximale) {
    long valeur = readLong(prompt);
    if (minimale <= valeur && valeur <= maximale)
      return valeur;
    System.out.println("Erreur. Donnez une valeur entre "
		       + minimale + " et " + maximale + " :");
    return readLong(minimale, maximale);
  }
  /**
   * Retourne un double entré au clavier. 
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @return le double lu
   * @see #readDouble(String)
   * @see #readDouble(double, double)
   * @see #readDouble(String, double, double)
   */
  public static double readDouble() {
    return readDouble(null);
  }
  /**
   * Retourne un double entré au clavier. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * @param prompt l'invite affichée
   * @return le double lu
   * @see #readDouble()
   * @see #readDouble(double, double)
   * @see #readDouble(String, double, double)
   */
  public static double readDouble(String prompt) {
    try {
      return Double.parseDouble(readString(prompt));
    }
    catch(NumberFormatException exception) {
      System.out.println("Erreur. Donnez un double : ");
      return readDouble();
    }
  }
  /**
   * Retourne un double entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour le double à lire
   * @param maximale valeur maximale pour le double à lire
   * @return le double lu
   * @see #readDouble()
   * @see #readDouble(String)
   * @see #readDouble(String, double, double)
   */
  public static double readDouble(double minimale, double maximale) {
    return readDouble(null, minimale, maximale);
  }
  /**
   * Retourne un double entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée erronée (par exemple un caractère), affiche
   * un message d'erreur et demande de recommencer.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour le double à lire
   * @param maximale valeur maximale pour le double à lire
   * @return le double lu
   * @see #readDouble()
   * @see #readDouble(String)
   * @see #readDouble(double, double)
   */
  public static double readDouble(String prompt, 
				  double minimale, double maximale)
  {
    double valeur = readDouble(prompt);
    if (minimale <= valeur && valeur <= maximale)
      return valeur;
    System.out.println("Erreur. Donnez une valeur entre "
		       + minimale + " et " + maximale + " :");
    return readDouble(minimale, maximale);
  }

  /**
   * Retourne un caractère entré au clavier. 
   * En cas d'entrée d'une chaîne de caractères, seul le premier
   * est pris en compte.
   * @return le char lu
   * @see #readChar(String)
   * @see #readChar(char, char)
   * @see #readChar(String, char, char)
   */
  public static char readChar() {
    return readChar(null);
  }
  /**
   * Retourne un caractère entré au clavier. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée d'une chaîne de caractères, seul le premier
   * est pris en compte.
   * @param prompt l'invite affichée
   * @return le char lu
   * @see #readChar()
   * @see #readChar(char, char)
   * @see #readChar(String, char, char)
   */
  public static char readChar(String prompt) {	
    return readString(prompt).charAt(0);
  }
  /**
   * Retourne un caractère entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * En cas d'entrée d'une chaîne de caractères, seul le premier
   * est pris en compte.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param minimale valeur minimale pour le caractère à lire
   * @param maximale valeur maximale pour le caractère à lire
   * @return le char lu
   * @see #readChar()
   * @see #readChar(String)
   * @see #readChar(String, char, char)
   */
  public static char readChar(char minimale, char maximale) {
    return readChar(null, minimale, maximale);
  }
  /**
   * Retourne un caractère entré au clavier, entre les valeurs 
   * <tt>minimale</tt> et <tt>maximale</tt>. 
   * Affiche d'abord la chaîne <tt>prompt</tt>.
   * En cas d'entrée d'une chaîne de caractères, seul le premier
   * est pris en compte.
   * En cas d'entrée en dehors des limites, affiche
   * un message et invite à recommencer.
   * @param prompt l'invite affichée
   * @param minimale valeur minimale pour le caractère à lire
   * @param maximale valeur maximale pour le caractère à lire
   * @return le char lu
   * @see #readChar()
   * @see #readChar(String)
   * @see #readChar(char, char)
   */
  public static char readChar(String prompt, char minimale, char maximale) {
    char valeur = readChar(prompt);
    if (minimale <= valeur && valeur <= maximale)
      return valeur;
    System.out.println("Erreur. Donnez une valeur entre "
		       + minimale + " et " + maximale + " :");
	return 	readChar(minimale, maximale);
  }

}

