# Einschränkung von Benutzereingaben



## Sinfony (9. Jan 2014)

Hallo,

ich benötige einen kleinen Denkanstoß für mein Problem, bei meinem Programm muss der Benutzer eine rationale Zahl inform z/n eingeben. Um sicher zu stellen, dass keine Buchstaben oder ganze Zahlen eingegebenen werden, habe ich dies bereits durch Exceptions abgefangen, nun würde ich aber auch gerne noch die Eingabe der 0 im Nenner unterbinden wollen (bei der Division wird dieser Fehler ohnehin abgefangen, aber der "Quatsch" soll eben erst gar nicht in den Speicher gelangen). Allerdings bin ich bisher auf keine passable Lösung gestoßen, wie ich die 0 unterbinden könnte.
Habe es bereits mit (eingabe.matches("\\d+/\\d+")) und  (eingabe.matches("\\d+/0")) versucht.
Allerdings funktioniert nur eines von beiden, mit  (eingabe.matches("\\d+/0")) klappt es zwar die 0 im Nenner auszugrenzen, allerdings habe ich dann eine Endlosschleife für richtige Eingaben im Programm, da (eingabe.matches("\\d+/\\d+")) alle dezimale Zahlen zulässt und ich somit eine NullPointerException erhalte 
Wäre demnach über Hilfe sehr dankbar


----------



## Gucky (9. Jan 2014)

Du bereinigst die Eingabe mithilfe eines .replaceAll("^0-9/"); Das halte ich für eleganter als es mit Exceptions zu machen. Danach splittest du die Eingabe um den Schrägstrich (.split("/"); ) und guckst in dem daraus resultierenden Array nur die beiden ersten Einträge an. Ist der Nenner (Index 1) 0, so kannst du entsprechend reagieren.


Auch möglich wäre es, in dem Objekt, welches den Bruch beschreibt eine Exception zu werfen, wenn der Nenner null ist. Oder machst du das ohne Bruchobjekt?


----------



## Sinfony (11. Jan 2014)

Erstmal danke, hatte das in der Zwischenzeit nun auch so gemacht, dass ich nach dem Split die Stelle des Arrays überprüfe an dem der Nenner ist. Verstehe den Sinn von .replaceAll ja im Grunde, aber weiß nicht, wie ich das implementiere sollte. Habe hier mal den Code meiner jetztigen Methode. Würde das denn so in Ordnung gehen?


```
public void eingabeRatioZahl(){
		String eingabe;
		int[] zahl;
		
		
		do{
			System.out.println("Bitte rationale Zahl eingeben in der Form z/n"); 
			
			eingabe = scan.nextLine();
			zahl = new int[2];
			
			try{
			String[] RatioZahl = new String[2];
			RatioZahl[0] = eingabe.substring(0, eingabe.indexOf("/"));
			RatioZahl[1] = eingabe.substring(eingabe.indexOf("/")+1);		
			
			for(int i=0; i<2; i++){
				zahl[i] = Integer.parseInt(RatioZahl[i]);
			}
				if(Integer.parseInt(RatioZahl[1]) != 0){
					ratioZahl = new Ratio(zahl[0],zahl[1]);
					break;
				}
					else{
						System.out.println("Nenner darf nicht den Wert 0 haben!");
					}
		}
			catch(StringIndexOutOfBoundsException iex){
			System.out.print("Ungültige Eingabe!\n");
			}
		}while(true);
	} //End of eingabeRatioZahl()
```


----------



## Gucky (11. Jan 2014)

Ich habe spontan keinen Fehler gefunden aber warum splittest du die Eingabe nicht mit .split()? Das wäre IMHO wesentlich leichter und fehlerunanfälliger.


----------



## Sinfony (11. Jan 2014)

Hab es nun über eingabe.split("/") gemacht, hattest schon Recht ist natürlich kürzer. Hatte es zu Beginn so versucht gehabt, aber irgendwie nen Fehler drinnen und es dann verworfen, aber nun klappt es. Ist soweit auch komplett fertig das Programm. Nochmal vielen Dank.
Jetzt muss ich nur noch den Fehler finden, dass mein Programm nicht mehr weiter arbeitet, wenn der 2. Bruch z.B. 0/3 ist und ich dividieren möchte, allerdings wirft es mir auch keine Exception oder sonstiges, sondern macht einfach gar nichts mehr


----------



## Gucky (12. Jan 2014)

Poste doch bitte den Code des BruchObjektes und der Hauptklasse. Dann kann ich dir auch helfen


----------



## Sinfony (12. Jan 2014)

So hab hier mal meinen Code angehangen. Ich danke dir schonmal für dein Angebot, dass du dir den Code durchsiehst 



Spoiler





```
public class Engine {
	
	//Attribute
	String op;
	Ratio ratioZahl;
	static int berechnungen = 0;
	
	/** Der Speicher (4 dimensionales Array) speichert in jeder Zeile die eingegebenen
	 *  rationalen Zahlen, den Operator und das Ergebnis - somit sind 1500 Berechnungen
	 *  möglich, eine Array-Liste wäre hierfür variabler, aber nicht in der Aufgabenstellung
	 *  vorgesehen
	 */
	String[][] speicher = new String[1500][4];

	
	//Initialisierung des Scanners zur Benutzereingabe
	Scanner scan = new Scanner(System.in);
	
	/**Eingabemethode für eine rationale Zahl in Form z/n - Eingabe wird anschließend am
	 * Bruchstrich gesplitted
	 * Dies wird so lange wiederholt, bis der Benutzer eine sinnvolle Eingabe gemacht hat
	 * Exception fängt dabei fehlerhafte Eingaben des Benutzers ab
	 */
	public void eingabeRatioZahl(){
		
		String eingabe;
		int[] zahl;		
		
		do{
			System.out.println("Bitte rationale Zahl eingeben in der Form z/n"); 
			
			eingabe = scan.nextLine();
			String [] splitted = eingabe.split("/");
			
			zahl = new int[2];
			
			try{
			zahl[0] = Integer.parseInt(splitted[0]);
			zahl[1] = Integer.parseInt(splitted[1]);
			
				if(Integer.parseInt(splitted[1]) == 0){
				System.out.println("Fehler: Die 0 im Nenner ist nicht erlaubt!\n");
				}
					else{
						ratioZahl = new Ratio(zahl[0],zahl[1]);
						break;
					}
			}
				catch(Exception ex){
					System.out.print("Fehler: Ungültige Eingabe!\n");
				}
		}while(true);
	} //End of eingabeRatioZahl()
	
	/**  Sichert die rationale Zahl in Stringform in den Speicher (Array), sofern an
	 * dieser Stelle des Arrays nicht schon eine Zahl im Speicher ist.
	 */
	public void saveRatioZahl(Ratio r){
		for(int speicherIndex = 0; speicherIndex < 1500; speicherIndex++){
			if(speicher[speicherIndex][0] == null){
				speicher[speicherIndex][0] = r.toString();
				break;
			}
			if(speicher[speicherIndex][2] == null){
				speicher[speicherIndex][2] = r.toString();
				break;
			}
			if(speicher[speicherIndex][3] == null){
				speicher[speicherIndex][3] = r.toString();
				break;
			}
			if (speicherIndex==1500) {
				System.out.println("Kein Speicherplatz mehr verfügbar.");
			}
		}
	} //End of saveRatioZahl()
	
	/**Eingabemethode für einen Opperator 
	 * wird wiederholt bis vom Benutzer eine übereinstimmende Eingabe getätigt wurde
	 * sollte dies nicht der Fall sein, wird der Nutzer auf die falsche Eingabe hingewiesen
	 */
	public void eingabeOperator(){
		
		do {
			System.out.println("Bitte Operator eingeben [+-*/]"); 
			op = scan.nextLine();
			
				if (op.equals("+") || op.equals("-") || op.equals("*") || op.equals("/")) {
					break;
				}
			
				else {
					System.out.print("Ungültige Eingabe!\n\n");
				}
			
		}while (true);

	}
	

	 /** sichert den Operator als String in den Speicher (Array),
	  * sofern an der zu speichernden Stelle nicht bereits ein Operator gespeichert wurde
	  */
	public void saveOperator(String op){
		for(int speicherIndex = 0; speicherIndex < 1500; speicherIndex++){
				if(speicher[speicherIndex][1] == null){
					speicher[speicherIndex][1] = op.toString();
					break;
				}
					if (speicherIndex==1500) {
						System.out.println("Kein Speicherplatz mehr verfügbar.");
					}
		}
	}
	
	/**
     * gibt einen String aus dem Speicher zurück
     * @param zeilenIndex - die Position (Zeile) des String im Speicher (Array)
     * @param spaltenIndex - die Position (Spalte) des Strings im Speicher (Array)
     * @return String - Der Ausgabestring gibt den Zeilenindex und Spaltenindex der
     * 					gespeicherten Zahl zurück
     */
	public String restore(int zeilenIndex, int spaltenIndex){
		String ausgabeString;
		ausgabeString = speicher[zeilenIndex][spaltenIndex];
		return ausgabeString;
	}
	
	 /**
     * Konvertiert einen String in eine rationale Zahl
     * @param str - enthält die rationale Zahl in Stringform z.B "2/3"
     * @return neueRatioZahl - gibt die Zahl als rationale Zahl zurück
     */
	private Ratio string2ratio(String str){

		int zaehler;
		int nenner;
		
		String[] split = new String[2];
        
        split = str.split("/");
       
        zaehler=Integer.parseInt(split[0]);
        nenner=Integer.parseInt(split[1]);
       
        Ratio neueRatio = new Ratio(zaehler, nenner);
         
        neueRatio.setZaehler(zaehler);
        neueRatio.setNenner(nenner);
       
        return neueRatio;
		
	} //Ende string2ratio()
	
	/**
	 * Methode die abfragt, ob das Programm beendet werden oder
	 * eine erneute Eingabe/Berechnung stattfindet soll
	 * @return
	 */
	private boolean weiter() {
		
		System.out.println("weiter? (j/n)");
		String eingabe = scan.nextLine();

		if (eingabe.equals("n")) {
			return true;
		}
		else {
			return false;
		}
	} //Ende weiter()
	
	/**
	 * Die Ausgabe-Methode stellt nach Beendigung des Programmes alles ausgeführten
	 * Berechnungen des Nutzers in sortierter und übersichtlicher Form dar,
	 * hierfür werden die gespeicherten Arrays wieder hergestellt
	 */
	public void ausgabe () {
		
		System.out.println("\n-------------- berechnet wurde: -----------------\n");
			for(int i=0; i<berechnungen;i++){
				System.out.println("\t" + restore(i,0) + " " + restore(i,1) + " " + restore(i,2) 
					+ " = "  + restore(i,3));	
			}
	} //Ende ausgabe()
	
	//Die Methode logehts()
	public void losgehts(){
		
		Ratio zahl1;
		Ratio zahl2;
		Ratio ergebnis = new Ratio();
		
			
			do{
				eingabeRatioZahl();
				saveRatioZahl(ratioZahl);
				eingabeRatioZahl();
				saveRatioZahl(ratioZahl);
				eingabeOperator();
				saveOperator(op);
				
				zahl1 = string2ratio(restore(berechnungen, 0));
				zahl2 = string2ratio(restore(berechnungen, 2));
			
				try {
					switch(op){
					case "+":
						ergebnis = zahl1.addiere(zahl2);
						System.out.println(ergebnis.toString());
						break;
					case "-":
						ergebnis = zahl1.subtrahiere(zahl2);
						System.out.println(ergebnis.toString());
						break;
					case "*":
						ergebnis = zahl1.multipliziere(zahl2);
						System.out.println(ergebnis.toString());
						break;
					case "/":
						ergebnis = zahl1.dividiere(zahl2);
						System.out.println(ergebnis.toString());
						break;	
					default:
						System.out.println("Fehlerhafte Eingabe\n");
					}
				} 
					catch(ArithmeticException ex){
						System.out.println("Fehler: Division durch 0 ist nicht erlaubt!\n");
					}
				
				saveRatioZahl(ergebnis);

				berechnungen++;
				
					if (weiter()) {
						break;
					}
			}while(true);
			
			ausgabe();
		scan.close();
	} //Ende losgehts()
	
		
} //End of Class
```


```
public class Ratio implements IRatio{

	
	//Attribute
	
	private int zaehler;
	private int nenner;
	
	//////////////////
	// Getter & Setter
	//////////////////
	
	public int getZaehler() {
		return zaehler;
	}

	public void setZaehler(int zaehler) {
		this.zaehler = zaehler;
	}

	public int getNenner() {
		return nenner;
	}

	public void setNenner(int nenner) {
		this.nenner = nenner;
	}
	
	/* 
	 * toString-Methode
	 */
	public String toString() {
		return "" + zaehler + "/" + nenner;
	}

	/**
	 * Kontruktor mit Parametern
	 * @param zaehler - Zähler
	 * @param nenner - Nenner
	 */
	 public Ratio(int zaehler, int nenner) {
	 	this.zaehler = zaehler;
	 	this.nenner = nenner;
	 }
	 /**
	  * Default - Konstruktor - Initialisiert den Zähler mit "0" und den Nenner mit "1"
	  */
	 public Ratio() {
		 this.zaehler = 0;
		 this.nenner = 1;
	 }
	/**
	 * Mathematische Methoden
	 */
	 
	 /**
	  * Addition von zwei rationalen Zahlen, das Ergebnis wird
	  * in gekürzter Form zurück gegeben.
	  */
	public Ratio addiere(Ratio zahl2) {
		
		Ratio ergebnis = new Ratio();
		
		ergebnis.zaehler = this.getZaehler() * zahl2.getNenner() + this.getNenner() * zahl2.getZaehler();
		ergebnis.nenner= this.getNenner() * zahl2.getNenner();
		
		return ergebnis.kuerze();
	}

	/**
     * Subtraktion zweier rationalen Zahlen, das Ergebnis wird
     * in gekürzer Form zurück gegeben.
     */
	public Ratio subtrahiere(Ratio zahl2) {
		
		 Ratio ergebnis = new Ratio();
         
         ergebnis.zaehler = this.getZaehler() * zahl2.getNenner() - zahl2.getZaehler() * this.getNenner();
         ergebnis.nenner  = this.getNenner() * zahl2.getNenner();
  
        return ergebnis.kuerze();
	}

	/**
     * Multiplikation zweier rationalen Zahlen, das Ergebnis wird
     * in gekürzer Form zurück gegeben.
     */
	public Ratio multipliziere(Ratio zahl2) {
		
		 Ratio ergebnis = new Ratio();
         
         ergebnis.zaehler = this.getZaehler() * zahl2.getZaehler();
         ergebnis.nenner  = this.getNenner() * zahl2.getNenner();
              
         return ergebnis.kuerze();
	}

	/**
     * Division zweier rationalen Zahlen, das Ergebnis wird
     * in gekürzer Form zurück gegeben. 
     * Die Exception fängt dabei den Fehler ab, falls es zu einer
     * Division durch 0 kommen sollte, da dies in der Mathematik
     * nicht definiert ist
     */
	public Ratio dividiere(Ratio zahl2) throws ArithmeticException {
		Ratio ergebnis = new Ratio();
		
        try {                 
            ergebnis.zaehler = this.getZaehler() * zahl2.getNenner();
            ergebnis.nenner  = this.getNenner() * zahl2.getZaehler();
        }
        	catch(ArithmeticException ex){           
        		System.out.println("Fehler: Division durch 0 nicht möglich\n");
        	}              
        return ergebnis.kuerze();
	}

	/**
     * Diese Methode dient zum kürzen des Ergebnisses und liefert
     * das gekürzte Ergebnis zurück.
     */
	public Ratio kuerze() {
		 int i,
         n= Math.abs(nenner),
         z= Math.abs(zaehler);

        while (z > 0){
            if( z < n ){
                i= n;
                n= z;
                z= i;
            }
            z= z - n;
        }
        nenner= nenner / n;
        zaehler= zaehler / n;
        return this;
	}

		/** Vergleichsmethode
		 * vergleicht zwei Objekte miteinander, in diesem Fall zwei Bruchobjekte, ob sie
		 * gleichwertig sind
		 */
		public boolean equals(Object obj) {
				
			if(this.zaehler == ((Ratio) obj).getZaehler() && this.nenner ==  ((Ratio) obj).getNenner()){      
             return true;             
			}
				else{
					return false;
				}
		}
} //End of class
```


----------



## Gucky (12. Jan 2014)

Die null solltest du von vornherein abfangen und gesondert behandeln. Eine null im Zähler setzt zum Beispiel auch den Nenner auf null oder setzt einen entsprechenden boolean auf true oder false und eine, von außen gesettete null im Nenner führt zu irgendwas anderem. Z. B. einer eigens von dir dafür kreierten Exception (z. B. NennerNullException). Damit ließe sich mit diesen beiden Fällen besser umgehen.

Wenn in dividiere eine Exception geworfen wird (was nie passiert, da es bei Mulitplikationen rein Mathematisch egal ist, ob ein Faktor 0 ist oder nicht, dann gibst du den gekürzten Bruch 0/1 zurück.
BTW kannst du die throws Anweisung entfernen, da du die Exception abfängst.
Bei 3/4 durch 0/3 kämen 9/0 raus. Dann wird dieser Bruch gekürzt. Ich habe mich nicht durch die Kürzmethode gekämpft aber dabei kann es zu Problemen kommen. Fang mal diesen Fall gesondert ab, dass eines von beiden 0 ist.


----------



## Sinfony (12. Jan 2014)

Naja die 0 abfangen, war ja das Problem in meiner Ausgangsituation, mit (eingabe.matches("\\d+/0")) hatte das ja nicht geklappt 
Die throws Anweisung war teil der Vorgabe, genauso wie die Kürzen-Methode von meiner Professorin vorgegeben wurde (sollte also hoffentlich keine Probleme machen )
Wenn ich 3/4 durch 0/3 teile, dann macht das Programm, nach der Eingabe des "/" durch den Nutzer gar nichts mehr, also weder liefert es ein Ergebnis, noch wirft es eine Exception oder gibt eine Fehlermeldung aus 

Edit:
Achso, klar die 0 im Zähler kann ich ja nach dem Split vom Array auslesen, so hatte ich es ja auch mit dem Nenner gemacht :bloed:


----------



## Gucky (13. Jan 2014)

Die throws Anweisung ist trotzdem unnötig, so wie du es tust. Ich glaube, deine Professorin wollte, dass du eine ArithmeticException wirfst, wenn der Nutzer versucht durch 0(/irgendwas) zu teilen. Mach das mal. Das sieht bestimmt gut aus. 
Außerdem kann bei dem Code nie eine ArithmeticException geworfen werden, weil du nie durch null teilst. Es ist gar kein Teiloperator vorhanden 

EDIT: Ich denke, du hast eine Endlosschleife im Kürzen gebaut. Wenn du den Fall der 0 im Nenner oder im Zähler behandelst und etwas entsprechendes, was du dir noch ausdenken musst, zurückgibst, dann müsste die Endlosschleife verhindert sein.


----------

