Freitag, 9. Januar 2009
Integer aus Eingabestrom in Array, formatierte Ausgabe
Allgemeines
Erstellen Sie ein Projekt klasse-intNumbers-name
, z.B. 2ad-intNumbers-mueller
.
Schreiben Sie ein Programm zum Auffinden von ganzen Zahlen in Textdateien.
Die gefundenen Zahlen speichern Sie in einem int-Array und geben Sie am Ende der Verarbeitung in Tabellenform aus.
Aufgabe 1 – FindIntNumbers(), find(), fill()
Erstellen Sie eine Klasse FindIntNumbers
mit einem Konstruktor FindIntNumbers(int value)
. value
ist die, aus der Kommandozeile eingelesene Größe eines anzulegenden Arrays zum Speichern der Zahlen.
public void find(BufferedReader in)
liest pro Datei bis zu EOF
alle Zeichen des Streams ein und sucht nach ganzen Zahlen. Ganze Zahlen bestehen nur aus zusammenhängenden Ziffern (1-n, begrenzt durch den Wertebereich vom integer-Datentyp). Die Zahlen werden durch beliebige Zeichen getrennt. Die gefundenen Zahlen werden in einem StringBuffer zusammengestellt und mit der Methode fill() im angelegten Array abgespeichert.
public void fill(StringBuffer sb)
füllt die Zahl aus dem
StringBuffer in das nächste freie Arrayelement. (maximal size Zahlen!). Bei Array-Überlauf bitte eine Fehlermeldung auf stderr ausgeben.
Aufgabe 2 – toString()
public String toString()
erstellt aus dem Array die Ausgabe in Tabellenform.
Die Formatierung der Zahlen (Spaltenbreite) wird durch die größte gefundene Zahl bestimmt, damit die Zahlen in der Tabelle linksbündig ausgerichtet untereinander stehen. In einer Zeile der Tabelle dürfen nicht mehr als 80 Zeichen stehen!
Beispiel:
Tabelle der gefundenen Zahlen
43 515 45 43 3567 24 36 23
478 6 59 346 1356887656 266 57 3624
487 346 57 345 245 6 6 3
3567 4 2134 934 193 4 934 934
931 193 934 3498 1943 190843 314 143
4 4 43 13
zugehörige Eingabedatei:
43 515 45 43 3567 24 36 23 478 6 59 346 1356887656 266 57 3624 487 346 57 345
245 6 gfr 6z3 qg tg rtg3567 4g
sadjfhalsd 2134h c934h fcnc193h4c nx934hc934ncjkd c931hqnc193hcudc 934
3498f 1943j190843jx n314dj143..4.4.43c13
Aufgabe 3 – main()
Erstellen Sie eine main()
-Methode, sodass die Klasse als Programm verwendet werden kann.
Das Programm soll beliebig viele Dateien durchsuchen oder von der Standardeingabe lesen, wenn kein Dateiname angegeben ist. Die Ausgabe soll immer auf Standardausgabe erfolgen.
Aufruf:
java FindIntNumbers [-h] size [dat1 ... datn]
-h ...
Hilfe ausgeben und Programm beenden
size ...
Zahl, welche die Größe des Arrays angibt
dat1,datn ...
aus diesen Dateien wird gelesen
Aufrufbeispiele:
java FindIntNumbers -h ...
gibt Hilfe aus und sonst nichts
java FindIntNUmbers 200 dat.txt text.txt ...
versucht alle Zahlen in den Dateien dat.txt und text.txt zu finden und gibt maximal die ersten 200 aus..
java FindIntNUmbers 100 ...
liest aus der Standardeingabe und sucht nach allen Zahlen und gibt maximal 100 aus.
Lösungsansatz:
Die Klasse
FindIntNumbers
benötigt folgende Informationen (Eigenschaften):- das Array mit den gelesenen Zahlen
- den Füllstand des Arrays
- die maximale Zeilenlänge (Konstant)
- die längste Zahl (d.h. die Anzahl der Ziffern der größten Zahl)
private static final int zeilenLaenge = 80;
private int[] array;
private int arraySize = 0;
private int fillTo = 0;
private int max = 0;
Im Konstruktor wird das Array angelegt.
Die Methode
find()
liest aus dem BufferedReader
zeichenweise und ermittelt die Zahlen (in einem StringBuffer
zusammengebaut) und füllt das Array mittels fill()
. find()
implementiert einen einfachen Automaten mit zwei Zuständen inZahl
und nicht inZahl
um zu unterscheiden, ob gerade eine Zahl aus den Eingabezeichen "zusammengebaut" wird oder nicht:
public void find(BufferedReader in) throws IOException {
int c;
boolean inZahl = false;
StringBuffer sb = new StringBuffer();
while ((c = in.read()) != EOF) {
if (inZahl) {
if (!Character.isDigit((char) c)) {
inZahl = false;
fill(sb);
sb = new StringBuffer();
} else {
sb.append((char) c);
}
} else {
if (Character.isDigit((char) c)) {
inZahl = true;
sb.append((char) c);
}
}
}
}
fill()
prüft, ob noch Platz im Array ist und konvertiert den StringBuffer
in einen int
und ermittelt gleichzeitig das Maximum für die Formatierung der Ausgabe (längste Zahl).
public void fill(StringBuffer sb) {
if (fillTo < arraySize) {
array[fillTo] = Integer.parseInt(sb.toString());
if (array[fillTo] > max) {
max = array[fillTo];
}
//System.out.printf("filled %d into array[%d]\n", array[fillTo], fillTo);
fillTo++;
}
}
Die Methode
toString()
macht die gesamte Formatierungsarbeit, indem zunächst ein Formatstring erstellt wird, bei dem die Länge mittels der Funktion maxlen()
eingetragen wird. Die Anzahl der Zahlen pro Zeile ergibt sich aus der Division aus zeilenLaenge / maxlen()
. maxlen()
liefert die Länge der größten Zahl plus eins (für den Zwischenraum).
public String toString() {
StringBuffer sb = new StringBuffer();
String format = String.format("%%-%dd", maxlen());
int anzZahlenProZeile = zeilenLaenge / maxlen();
int spaltennummer = 0;
for (int i = 0; i < fillTo; i++) {
int zahl = array[i];
sb.append(String.format(format, zahl));
spaltennummer++;
if (spaltennummer >= anzZahlenProZeile) {
spaltennummer = 0;
sb.append("\n");
}
}
if (spaltennummer > 0) {
sb.append("\n");
}
return sb.toString();
}
Das gesamte Programm könnte folgendermaßen aussehen:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* lehrer-intNumbers-haberstroh: .FindIntNumbers.java
*
* 17.12.2008, Harald R. Haberstroh
*/
/**
* Auffinden von ganzen Zahlen in Dateien und speichern in einem Array.
*
* @author Harald R. Haberstroh (hp)
*
*/
public class FindIntNumbers {
private static final int EOF = -1;
private static final int zeilenLaenge = 80;
private int[] array;
private int arraySize = 0;
private int fillTo = 0;
private int max = 0;
/**
* @param arraySize
*/
public FindIntNumbers(int arraySize) {
this.arraySize = arraySize;
this.array = new int[this.arraySize];
this.fillTo = 0;
this.max = Integer.MIN_VALUE;
}
/**
* default Konstruktor
*/
public FindIntNumbers() {
this(10);
}
/**
* liest bis EOF und ermittelt alle ganzen Zahlen und speichert sie im Array.
*
* @param in
* Eingabestrom
* @throws IOException
*/
public void find(BufferedReader in) throws IOException {
int c;
boolean inZahl = false;
StringBuffer sb = new StringBuffer();
while ((c = in.read()) != EOF) {
if (inZahl) {
if (!Character.isDigit((char) c)) {
inZahl = false;
fill(sb);
sb = new StringBuffer();
} else {
sb.append((char) c);
}
} else {
if (Character.isDigit((char) c)) {
inZahl = true;
sb.append((char) c);
}
}
}
}
/**
* liefert maxmale Länge einer Zahl in Zeichen.
*
* @return maximale Länge + 1
*/
private int maxlen() {
return Integer.toString(max).length() + 1;
}
/**
* füllt die Zahl im Stringbuffer in die nächste freie Stelle von array.
*
* @param sb
*/
public void fill(StringBuffer sb) {
if (fillTo < arraySize) {
array[fillTo] = Integer.parseInt(sb.toString());
if (array[fillTo] > max) {
max = array[fillTo];
}
System.out.printf("filled %d into array[%d]\n", array[fillTo], fillTo);
fillTo++;
}
}
/**
* liefert schön formatierte Tabelle als String.
*
* @return Tabella als String.
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
String format = String.format("%%-%dd", maxlen());
int anzZahlenProZeile = zeilenLaenge / maxlen();
int spaltennummer = 0;
for (int i = 0; i < fillTo; i++) {
int zahl = array[i];
sb.append(String.format(format, zahl));
spaltennummer++;
if (spaltennummer >= anzZahlenProZeile) {
spaltennummer = 0;
sb.append("\n");
}
}
if (spaltennummer > 0) {
sb.append("\n");
}
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
if (args.length >= 1) {
if (args[0].equals("-h")) {
System.out.println("Aufruf: java FindIntNumber [-h] size [dateien...]");
} else {
try {
int size = Integer.parseInt(args[0]);
BufferedReader in;
FindIntNumbers fn = new FindIntNumbers(size);
if (args.length > 1) { // Dateien
for (int i = 1; i < args.length; i++) {
in = new BufferedReader(new FileReader(args[i]));
fn.find(in);
in.close();
}
} else { // stdin
in = new BufferedReader(new InputStreamReader(System.in));
fn.find(in);
}
System.out.print(fn.toString());
} catch (NumberFormatException e) {
System.err.println("ungültige Größe angegeben, Hilfe mit -h");
} catch (IOException e) {
System.err.println("Ein-/Ausgabefehler: " + e.getLocalizedMessage());
}
}
} else {
System.err.println("keine Größe angegeben, Hilfe mit -h");
}
}
}
Labels: Aufgabe, Java, Lösung, PR2
Abonnieren Posts [Atom]
Kommentar veröffentlichen