import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;


/**
 * ITI1520 (Automne 2002-2007)
 * <P>
 * Cette classe offre des méthodes utiles pour lire
 * des valeurs à partir du clavier. À placer dans le
 * même répertoire que vos programmes Java.
 * <P>
 * Trois ensembles de méthodes de lectures sont offertes:
 * <UL>
 * <LI><CODE>readInt</CODE>, <CODE>readDouble</CODE>, 
 * <CODE>readChar</CODE> et <CODE>readBoolean</CODE>: 
 * Lit une valeur simple.</LI>
 * <LI><CODE>readIntLine</CODE>, <CODE>readDoubleLine</CODE>, 
 * <CODE>readCharLine</CODE>: Lit toutes les valeurs sur une 
 * ligne et les place dans un tableau d'une longueur appropriée.</LI>
 * <LI><CODE>readString</CODE>: 
 * Lit une chaîne de caractères.</LI>
 * </UL>
 * <P>
 * Aucune de ces méthodes ne permet de lire des valeurs de types
 * différents à partir d'une même ligne.
 * <P>
 * Prières d'utiliser <B>ITI1520.class</B> dans vos devoirs, et non 
 * <B>Lire.class</B> tel qu'utilisé dans le manuel.
 * <P>
 * <I>SVP: NE PAS ME MODIFIER!</I> Merci. 
 *  
 * @author      Alan Williams
 * @author      Daniel Amyot
 * @author      Amy Felty
 * @author      Stéphane Somé
 * @version     2007
 */
public class ITI1520
{
	private static final BufferedReader keyboard = new BufferedReader(
			new InputStreamReader( System.in ) );


 /**
  * Ce constructeur privé indique qu'aucune instance de cette classe ne peut
  * être créée.
  */

	private ITI1520( )
	{
	}


 
 /**
  * Pour lire un <b>nombre entier</b> de type <CODE>int</CODE> à partir du 
  * clavier.<P>
  * Si l'utilisateur entre une valeur qui n'est pas un <CODE>int</CODE>,
  * une exception {@link NumberFormatException} sera lancée et le programme
  * terminera. Appuyer sur "Enter" sans entrer de valeur produira le
  * même résultat.
  * <P>
  * Notez bien que cette méthode ne permet pas de + avant l'entier. Par 
  * exemple, <CODE>+123</CODE> n'est pas valide.
  * 
  * @return Un entier (<CODE>int</CODE>) lu au clavier.
  * @throws NumberFormatException
  *             si ce qui est entré n'est pas un entier.
  */

	public static int readInt( )
	{
		String inputString = getInput( );

		return Integer.parseInt( inputString );
	}



 /**
  * Pour lire un <b>nombre réel</b> de type <CODE>double</CODE> à partir du 
  * clavier.
  * <P>
  * Si l'utilisateur entre une valeur qui n'est pas un <CODE>double</CODE>,
  * une exception {@link NumberFormatException} sera lancée et le programme
  * terminera. Appuyer sur "Enter" sans entrer de valeur produira le
  * même résultat.
  * <P>
  * Notez aussi que la lecture d'un réel ne nécessite pas de 0 avant
  * le point. Par exemple: <CODE>-.2</CODE> est valide.
  * 
  * @return Un nombre réel (<CODE>double</CODE>) lu au clavier.
  * @throws NumberFormatException
  *             si ce qui est entré n'est pas un nombre réel.
  */

	public static double readDouble( )
	{
		String inputString = getInput( );

		return Double.parseDouble( inputString );
	}


 /**
  * Pour lire un <B>caractère</B> simple
  * de type <code>char</coDE> à partir du clavier.
  * <P>
  * Si aucun caractère n'est fourni, l'exception 
  * {@link StringIndexOutOfBoundsException} sera générée et le programme 
  * terminera. Sinon, le premier caractère de la chaîne lue sera
  * retourné.
  * <P>
  *  
  * @return Un <B>caractère</B> de type <CODE>char</CODE>
  *         lu au clavier.
  */


	public static char readChar( )
	{
		String inputString = getInput( );

		// Retourne le premier caractère de la chaîne lue.

		return inputString.charAt( 0 );
	}
	

 /**
  * Pour lire une valeur <B>booléenne</B> simple
  * de type <code>boolean</coDE> à partir du clavier.
  * <P>
  * Retourne <i>true</i> si la chaîne "true" (en majuscule, minuscule ou 
  * cases mélangées) est fournie au clavier, sinon retourne <i>false</i>.
  * <P>
  *  
  * @return Un <B>booléen</B> de type <CODE>boolean</CODE>
  *         lu au clavier.
  */


	public static boolean readBoolean( )
	{
		String inputString = getInput( );

		// Converti la chaîne à un booléen.
		return Boolean.valueOf( inputString ).booleanValue( );
	}

	
 /**
  * Pour lire un <B>tableau</B> de nombres réels de type 
  * <CODE>double</CODE> à partir du clavier.
  * <P>
  * Les nombre réels doivent être séparés par au moins un espace.
  * <P>
  * Si l'utilisateur entre une valeur qui n'est pas un <CODE>double</CODE>,
  * une exception {@link NumberFormatException} sera lancée et le programme
  * terminera.
  * <P>
  * Si toutes les valeurs entrées sont des <CODE>double</CODE> valides, 
  * alors un nouveau tableau est créé. La longueur du tableau correspond
  * au nombre de valeurs entrées. Les valeurs sont placées dans le
  * tableau dans l'ordre utilisé lors de leur entrée.
  *  
  * @return Un <B>tableau</B> de nombres réels de type <CODE>double</CODE>
  *         contenant les valeurs lues au clavier.
  * @throws NumberFormatException
  */

	public static double[] readDoubleLine( )
	{
		String inputString = getInput( );

		// StringTokenizer sépare la chaîne aux espaces blancs.

		StringTokenizer st = new StringTokenizer( inputString );

		// Combien de valeurs entrées?

		int numberOfValues = st.countTokens( );

		// Crée le tableau.

		double[] values = new double[numberOfValues];

		// Chaque morceau (token) est de type String et doit être 
		// converti en double.

		for ( int index = 0; index < numberOfValues; index = index + 1 )
		{
			String stringValue = st.nextToken( );

			values[index] = Double.parseDouble( stringValue );
		}
		return values;
	}



 /**
  * Pour lire un <B>tableau</B> de nombres entiers de type 
  * <CODE>int</CODE> à partir du clavier.
  * <P>
  * Les nombre entiers doivent être séparés par au moins un espace.
  * <P>
  * Si l'utilisateur entre une valeur qui n'est pas un <CODE>int</CODE>,
  * une exception {@link NumberFormatException} sera lancée et le programme
  * terminera.
  * <P>
  * Si toutes les valeurs entrées sont des <CODE>int</CODE> valides, 
  * alors un nouveau tableau est créé. La longueur du tableau correspond
  * au nombre de valeurs entrées. Les valeurs sont placées dans le
  * tableau dans l'ordre utilisé lors de leur entrée.
  *  
  * @return Un <B>tableau</B> de nombres entiers de type <CODE>int</CODE>
  *         contenant les valeurs lues au clavier.
  * @throws NumberFormatException
  */
	
	public static int[] readIntLine( )
	{
		String inputString = getInput( );

		// StringTokenizer sépare la chaîne aux espaces blancs.

		StringTokenizer st = new StringTokenizer( inputString );

		// Combien de valeurs entrées?

		int numberOfValues = st.countTokens( );

		// Crée le tableau.

		int[] values = new int[numberOfValues];

		// Chaque morceau (token) est de type String et doit être 
		// converti en int.

		for ( int index = 0; index < numberOfValues; index = index + 1 )
		{
			String stringValue = st.nextToken( );

			values[index] = Integer.parseInt( stringValue );
		}
		return values;
	}



 /**
  * Pour lire un <B>tableau</B> de caractères de type 
  * <CODE>char</CODE> à partir du clavier.
  * <P>
  * L'utilisateur entre une chaîne de caractères et appuie sur "Enter" pour 
  * retourner à la méthode invocatrice. <B>Tous les caractères, espaces 
  * inclus, sont placés dans le tableau.</B>
  * <P>
  * La chaîne de caractères entrée est convertie en un tableau de
  * caractères de longueur appropriée.
  *  
  * @return Un <B>tableau</B> de caractères de type <CODE>char</CODE>
  *         contenant les caractères lus au clavier.
  */

	public static char[] readCharLine( )
	{
		String inputString = getInput( );

		// Converti la chaîne en tableau de caractères

		return inputString.toCharArray( );
	}


 /**
  * Pour lire une <B>chaîne de caractères</B>
  * de type <code>String</coDE> à partir du clavier.
  * <P>
  * L'utilisateur entre une chaîne de caractères et appuie sur "Enter" pour 
  * retourner à la méthode invocatrice. <B>Tous les caractères, espaces 
  * inclus, sont placés dans le tableau.</B>
  * <P>
  *  
  * @return Une <B>chaîne de caractères</B> de type <CODE>String</CODE>
  *         contenant les caractères lus au clavier.
  */


	public static String readString( )
	{
		String inputString = getInput( );

		return inputString;
	}
		

/**
 * Cette méthode privée lit l'entrée au clavier comme un String.
 * <p>
 * Son intention est de gérer les exceptions {@link IOException} possibles
 * qui pourraient être générées par la méthode <code>readline()</code> afin
 * que la méthode <code>main()</code> n'ait pas à déclarer qu'elle doive
 * gérer cette exception.
 * <p>
 * Si l'exception survient, alors la pile des appels est affichée et le 
 * termine.
 * 
 * @return Un {@link String} contenant l'entrée fournie au clavier.
 */
	private static String getInput( )
	{
		String inputString = null;
		try
		{
			inputString = keyboard.readLine( );
		}
		catch ( IOException e )
		{
			e.printStackTrace( );
			
			// Ceci pourrait ne pas fonctionner avec DrJava
			
			System.exit( 0 );
		}
		return inputString;
	}
 
}
