Ein einfaches Exit

powerofcan

Grünschnabel
Hi Leute,

ich hoffe ihr könnt mir helfen.
Ich sitze jetzt schon über sechs Stunden hier und versuche ein einfaches exit einzubauen und das mit wenig Erfolg.

Code:
import java.io.*;

public class Port
{

       public static void main(String args[]) throws IOException
       {
              BufferedReader in = new BufferedReader( new InputStreamReader(System.in));
              int port;
              String exit = "";
              
              do
              {
                  do
                  {
                          System.out.println("Bitte geben Sie eine Portnummer ein: ");
                          port = Integer.parseInt(in.readLine());
                          exit = in.readLine();

                  }while (port <0 || port >65535);

                  switch(exit)
                  {
                              case "exit": System.exit(0);
                              break;
                  }
                  
                  
                  if(port >= 0 && port <= 1023)
                  {
                          switch(port)
                          {
                                      case 21: System.out.println("FTP " + ("- (well-known port)"));
                                      break;
                                      case 23: System.out.println("Telnet " + ("- (well-known port)"));
                                      break;
                                      case 25: System.out.println("SMTP " + ("- (well-known port)"));
                                      break;
                                      case 80: System.out.println("HTTP " + ("- (well-known port)"));
                                      break;
                                      case 143: System.out.println("IMAP  " + ("- (well-known port)"));
                                      break;
                                      default: System.out.println("Sonstiger Dienst " + ("- (well-known port)"));
                                      break;
                          }
                  }
                  
                  if(port >= 1024 && port <= 49151)
                  {
                          System.out.println("registered port");
                  }
                  
                  if(port >= 49152 && port <=65535)
                  {
                          System.out.println("dymanic port");
                  }
                  
              }while(port >= 0 || port < 65535);
       }

}

Und zwar geht es um folgendes. Das Programm ist ziemlich schlicht.
Es werden Integer Zahlen eingelesen und dann etwas bestimmtes ausgegeben.
Nun möchte ich, dass wenn ich "exit" eingebe das Programm sich beendet. Das macht es zwar gerade, indem ich einen String benutze und eine zweite Zeile einlese und wenn diese "exit" lautet, dann beendet sich das Programm. Doch ich möchte ich, dass das in einer Zeile passiert. Also wenn die Aufforderung zum einlesen kommt, dann gebe ich eine Zahl oder eben "exit" ein. Ist es eine Zahl läuft das Programm ganz einfach weiter und wenn es "exit" ist beendet es sich.
Ich hoffe mir kann jemand helfen.

Mit freundlichen Grüßen
POC
 
Wie ich sehe, verwendest du bereits Eigenarten von Java7. Ich habe in meinem Code nur Java6 verwendet, da Java7 noch nicht so weit verbreitet ist. Also wenn du deinen Tools weitergeben oder vielleicht sogar auf verschiedenen Rechner verwenden willst (erst recht, wenn es nicht deine eigenen Rechner sind), dann solltest du für's erste auf Java7 Features verzichten.

Dein Programm befindet sich in jedem Fall in einer Endlosschleife und kann nur mit dem Befehl exit abgebrochen werden. Das heißt, dass deine äußere do-while-Schleife eigentlich keinen Sinn macht, denn die wird ausgeführt, solange der Port gültig ist und der wiederum ist immer gültig, dadurch dass deine innere Schleife nur gültige Ports zulässt. Also kann man einfach eine simple Endlosschleife
Java:
while(true) {}
nehmen. Und wenn du schon in der äußeren Schleife auf einen gültigen Port prüfst, dann bitte richtig ^^ Die Oder-Verknüpfung ist in dem Fall nämlich falsch, da muss eine Und-Verknüpfung hin. In der inneren Schleife ist die Oder-Verknüpfung richtig.

So, nun aber Schluss mit dem Palaber, ich poste mal das Ergebnis.
Java:
package de.tutorials.forum.help.powerofcan.commands;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Port {
	private enum Commands {
		EXIT, HELP
	}

	public static void main(String args[]) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		/* PROGRAMM WIEDERHOLUNG */
		while(true) {
			int port = -1;
			Commands command = null;

			/* EINGABE WIEDERHOLUNG */
			while(true) {
				System.out.print("Bitte geben Sie eine Portnummer ein: ");
				String input = in.readLine();

				// Prüfen, ob ein Port eingegeben wurde
				try {
					port = Integer.parseInt(input);
					if(port >= 0 && port <= 65535) {
						break;
					}
				} catch(NumberFormatException e) {}

				// Prüfen, ob ein Befehl eingegeben wurde
				try {
					command = Commands.valueOf(input.toUpperCase());
					break;
				} catch(IllegalArgumentException e) {}
			}

			/* COMMANDS */
			if(command != null) {
				switch(command) {
					case EXIT:
						System.exit(0);
					case HELP:
						printHelp();
						continue;
				}
			}

			/* WELL KNOWN PORTS */
			if(port >= 0 && port <= 1023) {
				switch(port) {
					case 21:
						System.out.println("FTP - (well-known port)");
						break;
					case 23:
						System.out.println("Telnet - (well-known port)");
						break;
					case 25:
						System.out.println("SMTP - (well-known port)");
						break;
					case 80:
						System.out.println("HTTP - (well-known port)");
						break;
					case 143:
						System.out.println("IMAP  - (well-known port)");
						break;
					default:
						System.out.println("Sonstiger Dienst - (well-known port)");
						break;
				}
			}

			/* REGISTERED PORTS */
			if(port >= 1024 && port <= 49151) {
				System.out.println("registered port");
			}

			/* DYNAMIC PORTS */
			if(port >= 49152 && port <= 65535) {
				System.out.println("dymanic port");
			}
		}
	}

	private static void printHelp() {
		System.out.println("===================================");
		System.out.println("= " + Port.class.getSimpleName() + " Hilfe");
		System.out.println("===================================");
		System.out.println();
		System.out.println("Das Programm liefert Informationen zu Ports.");
		System.out.println();
		System.out.println("Mögliche Eingaben:");
		System.out.println("\thelp\tRuft diese Hilfe auf");
		System.out.println("\texit\tBeendet das Programm");
		System.out.println("\t<Port>\tEine Portnummer (0 - 65535)");
		System.out.println();
	}
}

Habe mir noch erlaubt einen weiteren Befehl help einzuführen, damit der Benutzer auch die Möglichkeit hat, Informationen über die Benutzung des Programms zu erfahren. Das Ausgeben der Hilfe bei jeder falschen Eingabe habe ich mir mal gespart, da das vielleicht doch zu nervig sein könnte.

Achso, da wär noch was. Ich finde diese doppelte Prüfaktion eher unnötig. Ich persönlich würde lieber nur mit Befehlen arbeiten und für den entsprechenden Befehl eben auch die nötigen Parameter übergeben, welche auch erst dann mit dem Befehl ausgewertet werden. Für die Porteingabe z.B. würde ich einfach einen Befehl port mit der Portnummer als Parameter verwenden. Das wäre ersichtlicher und gleich in der Bedienung. Im Moment hast du son Mischmasch in der Eingabe von Befehlen oder Portnummern. Daher ist auch der Ausgabe Bitte geben Sie eine Portnummer ein: sehr verwirrend, wenn man nebenher noch Befehle eingeben kann.

Und das nächste mal bitte statt den code-Tags [code][/code] lieber die java-Tags [code=java][/code] verwenden, damit das Syntax-Highlighting aktiviert wird und der Code besser lesbar ist.
 
Zuletzt bearbeitet:
Super vielen Dank,

wenn du mir noch vielleicht ein paar Dinge erklären könntest?

Java:
private enum Commands
    {
        EXIT, HELP
    }

-> Hier erschaffst du eigene Befehlsnamen? Aber was bedeutet dieses "enum"?

Java:
Commands command = null;

-> Was genau passiert hier?


Java:
try
                {
                    port = Integer.parseInt(input);
                    if(port >= 0 && port <= 65535)
                    {
                        break;
                    }
                }catch(NumberFormatException e) {}

-> Hier wird überprüft ob es sich bei der Eingabe um eine Zahl aus diesen Bereich befindet? Was genau macht dieses "catch" am Ende?

Java:
try
                {
                    command = Commands.valueOf(input.toUpperCase());
                    break;
                } catch(IllegalArgumentException e) {}

-> Könntest du mir hier bitte Zeile für Zeile erklären, was es mit den Befehlen auf sich hat?

So das wäre alles. Würde die Sachen gerne wissen, weil der Laborassistent in der Uni, mich sicher danach fragen wird. Wäre dir also nochmals sehr verbunden^^.

Vielen Dank und
mit freundlichen Grüßen
POC
 
Achso, du kannst Java also nich gar nicht so wirklich... Dann war das Benutzen des switch-case mit Strings also wohl nur Zufall. Und ich dachte, du benutzt gezielt Java7-Features, demzufolge bin ich davon ausgegangen, dass du Java an sich bereits beherrschst.

Naja, ist kein Problem. Dann erklär ich das mal.

1. Hier Deklariere ich einen neuen enum-Datentyp namens Commands. Unter enums kannst du dir vorstellen, dass es im Grunde einfach nur eine Sammlung von Konstanten ist. Das Tolle dabei ist, dass enums auch für swich-case-Anweisungen verwendet werden können und man somit z.B. solche Befehle sehr gut und bequem abarbeiten kann und sich nicht mit tausend if-else-Konstrukten prügeln muss. Man kann noch mehr Sachen mit enums machen, aber das ist an dieser Stelle nicht von Bedeutung ist generell eher selten der Fall. Ab Java7 kannst du auch Strings für eine switch-case-Anweisung verwenden, aber wie gesagt, würde ich im Moment noch nicht tun, da vermutlich die wenigsten Rechner diese Version installiert haben. Weitere Informationen zu enums findest du hier.

2. Hier wird einfach eine Variable vom enum-Typ Commands deklariert, an sicht nichts interessantes. Solchen Variablen kann man nur Werte des jeweiligen enum-Typs zuweisen.

Beispiel:
Java:
Commands command = Commands.EXIT;

3. Da wird versucht aus der Eingabe eine Zahl zu parsen. Sollte aber der Eingabestring keine Zahl sein, wird es knalln und eine NumberFormatException von der Methode parseInt() der Klasse Integer geworden. Das kann man sich zu nutze machen. Solche Exceptions kann man mit einem try-catch-Block abfangen, wenn nötig. In dem Anweisungsblock von try wird dabei versucht alle Anweisungen auszuführen. Sollte eine der Anweisungen eine Exception werfen, so wird der try-Block sofort verlassen (alle folgenden Anweisungen im Block werden also nicht mehr ausgeführt) und ein entsprechender catch-Block macht weiter. Man kann mehrere catch-Blöcke an einen try-Block anhängen und somit mehrere Exceptions abfangen und je nach Exception unterschiedlich reagieren. Mehr zum Exceptionhandling hier.

So, also wenn das Parsen einer Zahl fehlschlägt, dann wird die if-Abfrage übersprungen. Macht ja auch Sinn, denn es macht ja keinen Sinn etwas zu prüfen, das nicht funktioniert hat. Klappt das Parsen einer Zahl aber, dann wird als nächstes geprüft, ob die Zahl ein gültiger Portbereich ist und wenn ja, dann wird mit break die innere Schleife verlassen und die Anwendung kann loslegen. Dabei wird auch das Prüfen auf einen Befehl übersprungen, da es ja keinen Sinn macht auf einen Befehl zu prüfen, wenn schon feststeht, dass es sich um einen Port handelt.

4. Eigentlich vom Prinzip her das Gleiche wie Punkt 3. Allerdings wird ja geguckt, ob die Eingabe ein Befehl war, denn wenn das Programm an die Stelle gelangt ist, dann war es dank der vorangegangenen Prüferei auf einen Port schonmal kein Port.

Hier mache ich mir eine Besonderheit von enums zu nutzen. Die Methode valueOf(String) (es gibt noch eine andere mit dem Namen) kann anhand des String-Parameters versuchen herauszufinden, um welche Konstante es sich handelt. Auf diese Weise spart man sich ein ellenlanges if-else-Konstrukt. Wenn das klappt, dann bekommt man die entsprechende Konstante geliefert und die variable command wird damit initialisiert und man verlässt die innere Schleife wieder mit einem break. Sollte das aber nicht klappen, weil keine Konstante mit dem Stringwert existiert, wird eine IllegalArgumentException geworfen, das break wird nicht angerührt und die innere Schleife macht eine weitere Runde.

Dazu sei noch gesagt: An der Stelle wird an valueOf() nicht die Originaleingabe übergeben, sondern sie wird zuvor durch toUpperCase() komplett groß gemacht (alle Zeichen groß). Das hat den Grund, dass valueOf() wirklich den genauen String braucht und auch darauf prüft. Sollten sich der zu prüfende Wert und eine mögliche Konstante auch nur einem einzigen Zeichen unterscheiden (und sei es nur Unterscheidung zwischen groß und klein), wird das schon nicht hinhauen. Das ist hier so gemacht, weil Konstanten (egal ob in enums oder die "normalen" Konstanten) immer groß geschrieben werden. Allerdings hat diese Variante in dem Fall einen Nachteil, denn dadurch wird nicht auf die korrekte Schreibweise des Befehls geachtet. Wenn auch das beachtet werden soll, dann müsste man das toUpperCase() entfernen und die Konstanten eben komplett klein schreiben oder umgekehrt die Befehle komplett groß schreiben oder wie auch immer man das handhaben möchte.
 
Zuletzt bearbeitet:
Vielen Dank,

also ich kann nur das in Java, was ich in der Oberstufe und gerade im Studium gelernt habe. Also nicht besonders viel. Switch Case war aber kein Zufall, sondern haben wir so behandelt und hat gepasst.
Danke noch einmal für die ausführliche Erklärung

POC
 
Hi vielleicht kannst du mir bitte noch einmal helfen?

Ich hab gerade gesehen, dass wir eine Zusatzaufgabe haben... Und zwar sollen die letzten drei Werte (ports) die eingegeben worden sind, gespeichert und ausgegeben werden.

Also
d1: älteste
d2: letzte
d3: neueste
beim ersten einlesen wird der Wert z.B. 80 in Variable int d3 gespeichert;
beim zweiten einlesen wird d3 in d2 verschoben und dann der neue Wert in d3 gespeichert;
beim dritten einlesen wird d2 in d1 verschoben und d3 in d2 und d3 neu gespeichert;
also eigentlich reicht die dritte Variante:
leider klapp das bei mir nicht...

wenn ich (d3 d2 d1 sind intialisiert)

Java:
d1 = d2;
d2  = d3;
d3 = port;

dann klappt das leider nicht...
Ist es so kompliziert das zu machen?

Mit freundlichen Grüßen
POC
 
Nein, das ist nicht kompliziert. Wo werden denn deine drei Variablen deklariert und wo findet dann der Tauschvorgang statt? Vielleicht liegts daran.
 
So sieht der Code nun aus:

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Port2
{
    private enum Commands
    {
        EXIT
    }

    public static void main(String args[]) throws IOException
    {
           BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
           System.out.println("Wenn Ende gewünscht, bitte 'exit' eingeben");

        while(true)
        {
            int port = -1;
            Commands command = null;
            int d1 = 0;
            int d2 = 0;
            int d3 = 0;

            while(true)
            {
                System.out.print("Bitte geben Sie eine Portnummer ein: ");
                String input = in.readLine();


                try
                {
                    port = Integer.parseInt(input);
                    if(port >= 0 && port <= 65535)
                    {

                        d1 = d2;
                        d2  = d3;
                        d3 = port;

                        System.out.println("Erster Wert: " + d3);
                        System.out.println("Zweiter Wert: " + d2);
                        System.out.println("Dritter Wert: " + d1);
                        break;
                    }
                }catch(NumberFormatException e) {}

                try
                {
                    command = Commands.valueOf(input.toUpperCase());
                    break;
                }catch(IllegalArgumentException e) {}
            }

            if(command != null)
            {
                switch(command)
                {
                    case EXIT: System.exit(0);
                }
            }

            if(port >= 0 && port <= 1023)
            {
                switch(port)
                {
                    case 21: System.out.println("FTP - (well-known port)");
                    break;
                    case 23: System.out.println("Telnet - (well-known port)");
                    break;
                    case 25: System.out.println("SMTP - (well-known port)");
                    break;
                    case 80: System.out.println("HTTP - (well-known port)");
                    break;
                    case 143: System.out.println("IMAP  - (well-known port)");
                    break;
                    default: System.out.println("Sonstiger Dienst - (well-known port)");
                    break;
                }
            }

            if(port >= 1024 && port <= 49151)
            {
                System.out.println("registered port");
            }

            if(port >= 49152 && port <= 65535)
            {
                System.out.println("dymanic port");
            }
        }
    }
}

Help musste ich leider rausnehmen, da der Laborasistent nichts davon hällt, wenn wir Programme verändern bzw erweitern...

Vielen Dank

POC
 
Ja, immer die selbe Leier: "Du tust, was ich sage und nix anderes!"

Ja, sowas hab ich mir schon gedacht. Der Scope ist das Problem. Du deklarierst die Variablen in der äußeren Schleife. Das Problem dabei ist, dass diese Schleife ja dazu dient, dass das Programm immer wieder ausgeführt wird und bei jedem neuen Durchlauf werden diese dann eben neu deklariert und mit 0 inistialisiert, daher wird bei dir auch nix gespeichert. Um das zu lösen, musst du die drei Variablen d1, d2 und d3 nur außerhalb der Schleife deklarieren, z.B. nach deiner Ausgabe Wenn Ende gewünscht, bitte 'exit' eingeben. Dann sollte das eigentlich gehen, außer ich hab grad noch was anderes übersehen ^^

EDIT:
Ich hab da mal noch ne Frage oder besser gesagt, nen Vorschlag. Müssen das wirklich nur drei Ports in der Historie sein bzw. müssen das Variablen sein oder kann man das auch anders machen? Ich frage eben wegen deinem Laborassistenten.

Für die Port-Historie würde ich nicht zu Variablen greifen, sondern lieber zu einem Array, da es eine feste Größe hat (bei Listen müsste man noch zusätzlich kontrollieren). Ein Array lässt sich leicht erweitern oder verkleinern, je nach Bedarf eben, und der Rest läuft weiter völlig automatisiert und ohne jegliche Anpassungen. Bei Variablen ist das nicht so leicht, denn man muss neue Variablen deklarieren, was zu mehr Code und Arbeit führt und dann kommt noch das Tauschen, das ebenfalls mehr Arbeit erfordert. Mit Variablen hast du also in jedem Fall einen Mehraufwand zu bewältigen, sobald sich die Gegebenheiten ändern. Bei drei Werten würde ich bereits zum Array greifen und die Variablen übern Haufen werfen. Ich kann dir das auch gern posten, wenn du willst.
 
Zuletzt bearbeitet:
Vielen herzlichen Dank,

hab das mit der Schleife übersehen^^.
Also das mit den Array hab ich mir auch schon angeguckt, aber wir hatten noch keine arrays und ich sollte nicht zu viele Sachen einbauen die wir nicht kennen, sonst meint er am Ende eh das ich das alles jemand anderen schreiben lassen habe, ohne eigenarbeit.

Aber dennoch vielen vielen Dank
und Fröhliche Weinachten

POC
 
Zurück