package algds;

import java.io.*;
import java.util.Vector;

/**
 * Die Klasse <b>Utils</b> beinhaltet Methoden, die die Ein- und Ausgabe von Werten vereinfachen.
 * <p>
 * <b>Update</b>: die Eingabe-Methoden geben nach einem Fehler nicht mehr 0
 * zurueck, sondern warten auf eine neue Eingabe, bis kein Fehler mehr
 * auftritt. Eine Handvoll Methoden f&uuml;r andere primitive Datentypen hinzugef&uuml;gt.<br>
 * Christian Semrau (<a href=mailto:Christian.Semrau@Student.uni-magdeburg.de>Christian.Semrau@Student.uni-magdeburg.de</a>)<br>
 * Eingabemethode int[] readIntArray(String) hinzugef&uuml;gt. (kus)
 * Eingabemethode String[] readStringArray(String) hinzugef&uuml;gt. (ChS, 12.12.1999)
 *
 * @author Kai-Uwe Sattler (<a href=mailto:kus@iti.cs.uni-magdeburg.de>kus@iti.cs.uni-magdeburg.de</a>)
 * @version 1.1
 */
public class IOUtils {

/**
 * Liest ein Zeichen von der Standardeingabe und gibt
 * dieses als Ergebnis zur&uuml;ck.
 *
 * @return das gelesene Zeichen als <code>char</code>-Wert
 */
public static char readChar () {
  char result = '\u0000'; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = (char)reader.read ();
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest einen <code>double</code>-Wert von der Standardeingabe und gibt
 * diesen als Ergebnis zur&uuml;ck.
 *
 * @return der gelesene <code>double</code>-Wert
 */
public static double readDouble () {
  double result = 0; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = new Double (reader.readLine ()).doubleValue ();
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
	catch (NumberFormatException e) {
	  System.err.println ("Format Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest einen <code>float</code>-Wert von der Standardeingabe und gibt
 * diesen als Ergebnis zur&uuml;ck.
 *
 * @return der gelesene <code>float</code>-Wert
 */
public static float readFloat () {
  float result = 0; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = new Float (reader.readLine ()).floatValue ();
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
	catch (NumberFormatException e) {
	  System.err.println ("Format Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest einen <code>int</code>-Wert von der Standardeingabe und gibt
 * diesen als Ergebnis zur&uuml;ck.<br>
 * Beispiel:<br>
 * <code>int i = IOUtils.readInt ();</code>
 *
 * @return der gelesene <code>int</code>-Wert
 */
public static int readInt () {
  int result = 0; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = Integer.parseInt (reader.readLine ());
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
	catch (NumberFormatException e) {
	  System.err.println ("Format Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest ein Folge von Integer-Werten aus der angegebenen Datei
 * und gibt diese in einem Feld zur&uuml;ck.
 * Im Fehlerfall wird <code>null</code> geliefert.
 *
 * @param filename Der Name (inkl. Pfad) der einzulesenden Datei
 * @return das <code>int</code>-Feld mit den Werten
 */
public static int[] readIntArray (String filename) {
  int[] result = null;

  Vector values = new Vector ();
  try {
	BufferedReader reader =
	  new BufferedReader (new FileReader (filename));
	while (reader.ready ()) {
	  Integer value = Integer.valueOf (reader.readLine ());
	  values.addElement (value);
	}
	reader.close ();
	result = new int[values.size ()];
	for (int i = 0; i < values.size (); i++)
	  result[i] = ((Integer) values.elementAt (i)).intValue ();
  }
  catch (IOException e) {
	System.err.println ("I/O Error: " + e.getMessage ());
  }

  return result;
}
/**
 * Liest einen <code>long</code>-Wert von der Standardeingabe und gibt
 * diesen als Ergebnis zur&uuml;ck.<br>
 *
 * @return der gelesene <code>long</code>-Wert
 */
public static long readLong () {
  long result = 0; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = Long.parseLong (reader.readLine ());
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
	catch (NumberFormatException e) {
	  System.err.println ("Format Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest eine Zeichenkette von der Standardeingabe und gibt
 * diese als Ergebnis zur&uuml;ck.
 * Beispiel:<br>
 * <code>String s = IOUtils.readString ();</code>
 *
 * @return die gelesene Zeichenkette als <code>String</code>-Objekt
 */
public static String readString () {
  String result = null; boolean err;
  BufferedReader reader =
	new BufferedReader (new InputStreamReader (System.in));
  do { err=false;
	try {
	  result = reader.readLine ();
	}
	catch (IOException e) {
	  System.err.println ("I/O Error: " + e.getMessage ());
	  err=true;
	}
  } while (err);
  return result;
}
/**
 * Liest eine angegebene Textdatei ein
 * und gibt diese in einem String-Feld zur&uuml;ck.
 * Im Fehlerfall wird <code>null</code> geliefert.
 *
 * @param filename Der Name (inkl. Pfad) der einzulesenden Datei
 * @return das <code>String</code>-Feld mit den Werten
 */
public static String[] readStringArray (String filename) {
  String[] result = null;
  Vector values = new Vector ();
  try {
	BufferedReader reader =
	  new BufferedReader (new FileReader (filename));
	while (reader.ready ()) {
	  String value = reader.readLine ();
	  values.addElement (value);
	}
	reader.close ();
	result = new String[values.size ()];
	for (int i = 0; i < values.size (); i++)
	  result[i] = ((String) values.elementAt (i)).toString ();
  }
  catch (IOException e) {
	System.err.println ("I/O Error: " + e.getMessage ());
  }
  return result;
}
/**
 * Gibt einen rechtsb&uuml;ndig auf n Zeichen formatieren <code>String</code> zur&uuml;ck.
 * Beispiel f&uuml;r Zahlenausgabe:<br>
 * <code>System.out.print(IOUtils.right(""+i,n));</code><br>
 * (i soll ausgegeben werden, n ist die Stellenzahl)<br>
 * Ist der <code>String</code> s zu lang, wird er unver&auml;ndert zur&uuml;ckgegeben.<br>
 *
 * @return rechtsb&uuml;ndig formatierter String
 * @param s der zu formatierende String
 * @param n die Anzahl der Zeichen
 */
public static String right(String s, int n) {
  // Ich denke, diese Routine ist nicht besonders effizient, aber sie funktioniert.
  String s2 = "";
  for (int i=0; i<n-s.length(); i++) s2 = s2 + " ";
  return (s2 + s);
}
}
