313373n3wb33
(Themenstarter)
Anmeldungsdatum: 7. November 2012
Beiträge: 71
|
Vergesst es mir ist die Lust vergangen. Danke dass ihr mir versucht hab den richtigen Weg zu zeigen, aber ohne Lösung bringt mir das ganze hier gar nichts. Ich mach einfach etwas anderes. Es ist ja nicht so als müsste ich diesen Physikrechner fertig Programmieren der war eigentlich nur als Übung da die mir jetz mehr oder weniger nichts gebracht hat. Sry an Google Benutzer.
|
snafu1
Anmeldungsdatum: 5. September 2007
Beiträge: 2133
Wohnort: Gelsenkirchen
|
@313373n3wb33: Eingaben (etwa aus CSV-Files) können z.B. auch so aussehen:
Dann würde bei jedem nextInt() die jeweils nächste Zahl ausgeliefert werden. Das macht auch durchaus Sinn, da der Scanner eben nicht auf Eingaben vom Terminal spezialisiert ist, sondern allgemein für das Lesen aus Datenströmen angewendet werden kann. Stell dir hier einfach einen Cursor vor, der nach jedem Lesen an die Stelle direkt hinter dem zuletzt ausgelieferten Datensatz (hier: die jeweilige Zahl) rutscht. Eine Zahleneingabe durch den Nutzer über System.in besteht nun aus folgenden Bestandteilen:
Nach dem Aufruf von nextInt() rutscht der Cursor also an die Stelle zwischen Zahl und Newline . Jetzt wird es nötig, nextLine() aufzurufen. Diese Methode hat die Aufgabe, all das, was zwischen der aktuellen Cursorposition und dem nächsten Newline-Zeichen steht, auszugeben (in deinem Fall: leerer String). Nach Aufruf dieser Methode steht die Cursorposition am Anfang der nächsten Zeile. Aus diesem Grund musst du den für dich als unnötig empfundenen zusätzlichen Aufruf von nextLine() dazwischen quetschen, damit der dann folgende nextLine() -Aufruf den von dir erwarteten Text ausliefern kann. Vielleicht ist es ja jetzt klarer geworden, was meine Vorposter von dir wollen... 😉 Im Übrigen ist es bei Nutzereingaben, oftmals einfacher, anstatt nextInt() lieber ein Integer.valueOf(scanner.nextLine()) anzuwenden. Das tut eher das, was man eigentlich haben möchte (durch den Nutzer eingetippte *Zeile* als Integer interpretieren) und ist dementsprechend auch weniger fehleranfällig.
|
xabbuh
Anmeldungsdatum: 25. Mai 2006
Beiträge: 6411
|
313373n3wb33 schrieb: Vergesst es mir ist die Lust vergangen. Danke dass ihr mir versucht hab den richtigen Weg zu zeigen, aber ohne Lösung bringt mir das ganze hier gar nichts.
Du hattest die Lösung doch?! Das einzige, was Du bei Dir verändern kannst, ist, auf die Zuweisung des Rückgabewertes zur Variablen blind zu verzichten.
|
313373n3wb33
(Themenstarter)
Anmeldungsdatum: 7. November 2012
Beiträge: 71
|
Eingabestreams: String-→ Streckeneinheit: M *Unsichtbarer-Nächste-Zeile-beginn-code-der-automatisch-nach-string-eingabe-hierher-geschrieben-wird* Int-→ Streckenwert: 8 *Kein-Nächste-Zeile-beginn-code-der-automatisch-hierher-geschrieben-wird-da-es-um-die-Zahlen-und-nicht-um-die-Int-geht* String-→ Zeiteinheit: *Versteckter-Nächste-Zeile-Beginn-Code-da-!Letzter-Eingabestream-noch-in-dieser-Zeile-ist!-und-weil-scan-diese-line-wird-scann-abgebrochen* Int-→ Zeitwert: 2 *wieder-kein-versteckter-code* Auf gut Deutsch man kann nach einem Int einen String nicht direkt einlesen, sondern muss den Eingabestream von Int zuerst beenden. In meinem Fall wurde er also durch den 2ten String beendet.
|
snafu1
Anmeldungsdatum: 5. September 2007
Beiträge: 2133
Wohnort: Gelsenkirchen
|
Nee, nicht ganz. Es ist nicht so, dass der Scanner zwischendurch in einer Art "Zahlenmodus" ist, wo man ihn erst wieder rausholen müsste. Vielmehr ist der Cursor des Scanner s einfach noch nicht am Anfang der nächsten Zeile, sondern eben erst hinter der zuletzt ausgegebenen Zahl. Man muss ihn erst dazu bringen, sozusagen die aktuelle Zeile zu beenden und in die nächste zu springen. Das kann man am Besten mit einem zusätzlichen nextLine() machen. Die Newline-Zeichen hat man nach jeder Eingabe bzw jedem Enter-Drücken mit drin. Nur werden die bei den Ausgaben weg gelassen, sodass man sie als Benutzer der Scanner -API halt nicht direkt sieht. Hier übrigens ein sehr einfach gehaltenes Beispiel, welches den schon von mir vorgeschlagenen Weg über eine grundsätzliche Abfrage von nextLine() geht:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | import java.util.Scanner;
public class Benutzereingabe {
private static final Scanner eingabeleser = new Scanner(System.in);
public static String erfrageText() {
return eingabeleser.nextLine();
}
public static int erfrageZahl() {
return Integer.parseInt(eingabeleser.nextLine());
}
public static void main(String[] args) {
System.out.println("Bitte eine Zahl eingeben:");
int zahl = erfrageZahl();
System.out.println("Jetzt bitte beliebigen Text eingeben:");
String text = erfrageText();
System.out.println("Zahl war: " + zahl);
System.out.println("Text war: " + text);
}
}
|
Ich finde das deutlich robuster, da hierdurch garantiert wird, dass der Cursor *immer* am Anfang der nächsten Zeile steht, nachdem etwas eingelesen wurde. Die Reaktion auf Fehleingaben durch den Benutzer (z.B. keine Zahl, obwohl eine erwartet wird) habe ich hier erstmal weg gelassen.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
rklm hatte es hier schon mal geschrieben, ich erläutere es nochmal etwas ausführlicher:
Zu Anfang stehen im Datenpuffer der Tastatur die Zeichen:
| 1 | 2 | 3 | \n | t | e | x | t | \n |
=^===^===^=
Du liest diesen Integer aus.
Danach steht dort immer noch: (denn Du hattest nach der Zahl doch ein [Enter] eingegeben, nicht wahr ?)
| \n | t | e | x | t | \n |
==^=
Das ist das, was Du mit Deinem 1.Zeilenlesen aus dem Puffer holst ! (also kein Text, nur das [Enter])
Danach geht es normal weiter mit:
| t | e | x | t | \n |
=^===^===^===^====^=
Das wird beim 2.Zeilenlesen abgeholt: der "text" und das [Enter].
Merke: das [Enter] wird immer nur beim Zeilenlesen abgeholt, aber nicht beim Integerlesen !
Siehst Du es jetzt ? LG, track
|
313373n3wb33
(Themenstarter)
Anmeldungsdatum: 7. November 2012
Beiträge: 71
|
Also bei nextInt wird /n (nächster Absatz) nicht angewendet.
Später wird aber ein, durch nextInt zurückgelassenes, /n vom nächsten nextLine benutzt.
Dadurch wird die Eingabe geöffnet und gleich danach durch /n die Zeile beendet.
Durch ein dazwischen eingegebenes nextLine(); wird die Zeile beendet. Hab ich das so richtig? Die hätten mir das gleich sagen sollen.xD Mein Problem war das ich den Eingabestream nicht kannte. Und dass eine Eingabe hier nicht durch den /n nicht automatisch beendet wird.
Danke an alle Beteiligten, Ich wünschte ich könnte euch nen Cafe für die Umstände und meine schlechte Laune zahlen. :/ MfG
N3w
|
Hefeweiz3n
Moderator, Webteam
Anmeldungsdatum: 15. Juli 2006
Beiträge: 5814
Wohnort: Ankh-Morpork
|
313373n3wb33 schrieb: Also bei nextInt wird /n (nächster Absatz) nicht angewendet.
Später wird aber ein, durch nextInt zurückgelassenes, /n vom nächsten nextLine benutzt.
Dadurch wird die Eingabe geöffnet und gleich danach durch /n die Zeile beendet.
Durch ein dazwischen eingegebenes nextLine(); wird die Zeile beendet. Hab ich das so richtig?
Bis auf die Terminologie, ja 😉. Benutzen und öffnen sind hier eher die falschen Begriffe. Der Eingabescanner bleibt ja die ganze Zeit über offen. Wichtig ist hier das Daten ab dem Cursor (Zeiger) gelesen (Was du wohl mit "Benutzen" meinst) werden. Und zwar je nach Methode unterschiedlich viele. nextInt() beendet das auslesen nach dem letzten Zeichen was eine Zahl ist, nextLine() halt nach dem Zeilenumbruch. Da \n = newline keine Zahl ist wird es von nextInt() halt nicht gelesen, weshalb der Cursor davor stehenbleibt. Das Verhalten ist, so betrachtet, sehr logisch und konsistent, wie du sagst muss man dafür aber natürlich wissen wie genau das funktioniert. Ich hoffe das ist jetzt bei dir der Fall 😉.
|
snafu1
Anmeldungsdatum: 5. September 2007
Beiträge: 2133
Wohnort: Gelsenkirchen
|
Ich glaube, das was hinter den Kulissen vor sich geht, ist immer noch die große Unbekannte für unseren Threadersteller. Da spielt noch viel Phantasie mit rein. Vielleicht fragt er sich ja gerade: "Hackt sich Java da etwa in mein Terminal ein und bewegt einfach so den Cursor...?" 😉 Aber egal: Das grundsätzliche Prinzip wurde jetzt anscheinend verstanden und der Rest kommt schon irgendwann im Laufe der Zeit. ☺
|
313373n3wb33
(Themenstarter)
Anmeldungsdatum: 7. November 2012
Beiträge: 71
|
Das ganze funktioniert über Tokens nicht wahr?
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13177
|
313373n3wb33 schrieb: Das ganze funktioniert über Tokens nicht wahr?
Token sind die Ausgabe des Scanners - kein Zwischenprodukt. Ein Scanner zerlegt einen uniformen Eingabestrom von Zeichen in einen Strom von Tokens. Das sind jeweils Gruppen von aufeinander folgenden Zeichen, z.B. alle Ziffern, die eine Ganzzahl bilden.
|
Hefeweiz3n
Moderator, Webteam
Anmeldungsdatum: 15. Juli 2006
Beiträge: 5814
Wohnort: Ankh-Morpork
|
rklm hat das mit den Tokens ja schon erklärt. Das mit dem Cursor ist aber noch eine Ebene tiefer, vor den Token. Weil du kannst ja auch einfach einen einzelnen Bustaben auslesen anstatt eines kompletten Tokens. Den Cursor kannst du dir einfach wie deinen Finger vorstellen, mit dem du beim Lesen in einem Text mitgehst um nicht zu vergessen wo du bereits warst. Aktuelle Position ----------+
|
Text Foo Bar, eine Zahl: 123\n
Und hier beginnt die neue Zeile Das kann man dann sowohl so implementieren das man auch auf bereits gelesene Bustaben erneut zurückgreifen kann oder auch nicht.
Achtung: Wenn du das folgende nicht verstehst lass es einfach, oder aber wenn du mal Zeit und Muße hast arbeite dich in die Grundlegenden Informatikmodelle wie Listen und Bäume ein und versuche es dann noch einmal 😉. Man könnte das ganze z.B. mit einer einfach verketteten Liste lösen, dann hätte jeder Buchstabe eine Referenz (Verweis) auf den nächsten besitzt. Bei einer doppelt Verketteten Liste hätte man dann auch eine Referenz auf den jeweiligen vorherigen Buchstaben. Einfach verkettet
+---+ +---+ +---+ +---+
| T |==>| e |==>| x |==>| t |
+---+ +---+ +---+ +---+ Doppelt verkettet
+---+ +---+ +---+ +---+
| T |<=>| e |<=>| x |<=>| t |
+---+ +---+ +---+ +---+ Näher an der Hardware dran (z.B. mit C/C++), und damit auch effizienter und schneller, setzt man sowas mit Pointern um, Pointer sind dabei Variablen die direkt auf einen Speicherbereich verweisen in dem dann der nächste Buchstabe zu finden ist.
|
313373n3wb33
(Themenstarter)
Anmeldungsdatum: 7. November 2012
Beiträge: 71
|
@Rklm: Ja ich sag int bla input.nextInt und es wird ein Token erstell der bis zur nächsten nicht-Zahl (Sprich Ende der Zahlenfolge) hält. Sobald der abgelaufen ist wird die variable bla in nem Variablenspeicher o.ä. gesichert und verweist auf einen Speicher bereich in dem sich meine Eingegebene Zahl befindet. @Hefe: Ich merk schon dass ich hier das gesamte Thema warscheinlich falsch verstanden habe. Kann mich da sonst jemand an nen Guten Artikel o.ä. verlinken?
Dann könnte ich ein bischen Geistreicher hier rein Posten. x) MfG
N3w
|
Hefeweiz3n
Moderator, Webteam
Anmeldungsdatum: 15. Juli 2006
Beiträge: 5814
Wohnort: Ankh-Morpork
|
313373n3wb33 schrieb: @Rklm: Ja ich sag int bla input.nextInt und es wird ein Token erstell der bis zur nächsten nicht-Zahl (Sprich Ende der Zahlenfolge) hält. Sobald der abgelaufen ist wird die variable bla in nem Variablenspeicher o.ä. gesichert und verweist auf einen Speicher bereich in dem sich meine Eingegebene Zahl befindet.
Du vermischst da verschiedene Arten von Tokens 😉.
@Hefe: Ich merk schon dass ich hier das gesamte Thema warscheinlich falsch verstanden habe. Kann mich da sonst jemand an nen Guten Artikel o.ä. verlinken?
Dann könnte ich ein bischen Geistreicher hier rein Posten. x)
Die Java Insel ist eine sehr gute Quelle 😉.
|
Covex
Anmeldungsdatum: 11. November 2013
Beiträge: Zähle...
|
Hi
für den fall du einfach nur den code möchtest habe ich mir mal 10min zeit genommen und so ein programm geschreiben. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 | import java.util.InputMismatchException;
import java.util.Scanner;
public class UniformMotionCalculator {
private float var_one;
private float var_two;
private Scanner input;
public static void displayHelp() {
System.out.println("No arguments - View help\n");
System.out
.println(" -v Calculates the velocity from the time and distance");
System.out
.println(" -d Calculates the distance from the velocity and time");
System.out
.println(" -t Calculates the time from the velocity and distance");
System.exit(0);
}
public UniformMotionCalculator(String arg) {
input = new Scanner(System.in);
if (arg.startsWith("-v")) {
getData("Distance in km: ", "Time in h: ");
System.out.println("Velocity: " + var_one / var_two + " km/h");
} else if (arg.startsWith("-d")) {
getData("Velocity in km/h: ", "Time in h: ");
System.out.println("Distance: " + var_one * var_two + " km");
} else if (arg.startsWith("-t")) {
getData("Distance in km: ", "Velocity in km/h: ");
System.out.println("Time: " + var_one / var_two + " h");
} else {
displayHelp();
}
}
public void getData(String name_one, String name_two) {
try {
System.out.print(name_one);
var_one = input.nextFloat();
System.out.print(name_two);
var_two = input.nextFloat();
} catch (InputMismatchException e) {
System.out.println("No valid input!");
System.exit(0);
}
}
public static void main(String[] args) {
if (args.length == 1 && args[0].length() == 2) {
new UniformMotionCalculator(args[0]);
} else {
UniformMotionCalculator.displayHelp();
}
}
}
|
|