3.3 Übungen
3.3 Übungen
3.3.1 Übung: SchleifenterminierungWelche der folgenden Schleifen terminieren?
|
int i = 1, j = 1; do { i = i + j; j++; } while (i < 200);
int i = 1, j = 20; while (i + j < i) { i = i + 2; j--; }
int i = 1, j = 20; while (i + j > i) { i = i + 2; j--; }
int i = 100, j = 27; while (i != j) { i = i / 2; j = j / 3; }
3.3.2 Übung: Ziffern einer Zahl
Hilfestellung:
Einlesen von Zahlenwerten beim Starten von der Kommandozeile als Option wie zum Beispiel:
$ java Main 17 19
erfolgt durch Einlesen von Zeichenketten und Umwandlung in Zahlen. Anbei ein Rahmenprogramm welches das Problem löst:
public class Main { public static void main(String[] args) { int firstArg=0; int stellen=0; if (args.length > 0) { try { firstArg = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.err.println("Argument muss Ganzzahl sein"); System.exit(1); } System.out.println("Die Zahl firstArg = " + firstArg + " wurde eingelesen"); // Implementierung gehört hierher System.out.println(" Die Zahl " + firstArg + " hat " + stellen + " Stellen!"); } }
Eine andere Möglichkeit besteht darin, dass man das Programm startet und bei Bedarf eine Eingabe von der Konsole anfordert.
Achten Sie hier auf die fettgedruckte Importanweisung der Klasse Scanner. Sie ist notwendig um die Klasse zu benutzen:
import java.util.Scanner; public class Eingabe { public static void main(String[] args) { Scanner eingabe = new Scanner(System.in); System.out.print("Geben Sie die erste Zahl ein: "); int zahl1 = eingabe.nextInt(); System.out.print("Geben Sie die zweite Zahl ein: "); int zahl2 = eingabe.nextInt(); System.out.println("Ergebnis: " + zahl1); System.out.println("Ergebnis: " + zahl2); } }
Das Programm Eingabe kann man auf der Konsole wie folgt bedienen:
$ java Eingabe Geben Sie die erste Zahl ein: 34 Geben Sie die zweite Zahl ein: 56 Ergebnis: 34 Ergebnis: 56
Am einfachsten ist es die Eingaben in der ersten Zeile des Programmes hart zu belegen...
3.3.3 Übung: Quersumme
Schreiben Sie ein Java-Programm, das die Quersumme einer positiven ganzen Zahl berechnet und ausgibt.
Beispiel: Zahl 4711 --> Quersumme 13.
3.3.4 Übung: Zahlenstatistik
Hilfestellung:
Einlesen eines Feldes (Arrays) von der Kommandozeile
package s1.block3; public class Zahlenstatistik { public static void main(String[] args) { int feld[]; if (args.length > 0) { feld = new int[args.length]; try { for (int i=0;i<args.length;i++) { feld[i] = Integer.parseInt(args[i]); // Einlesen der Kommandozeilenargumente und umwandeln in Ganzzahlen } } catch (NumberFormatException e) { System.err.println("Argument muss Ganzzahl sein"); System.exit(1); } // Ab hier steht das Feld mit allen Werten zur Verfügung } }
3.3.5 Übung: Primfaktorzerlegung
- Die Zahl 100 besteht aus den Primfaktoren 2, 2, 5, 5;
- die Zahl 252 aus den Primfaktoren 2, 2 , 3, 3, 7.
Option: Optimieren sie Ihr Programm auf die kürzeste Laufzeit. Verwenden Sie hierzu den Nanotimer von JDK 6.0 wie folgt:
package s1.block3; public class Primzahlzerlegung { public static void main(String[] args) { int firstArg = 0; int p=0; long time; time= System.nanoTime(); if (args.length > 0) { try { p = Integer.parseInt(args[0]); } catch (NumberFormatException e) { System.err.println("Argument muss Ganzzahl sein"); System.exit(1); } System.out.println("Eingelesene Zahl: " + p); } // Die Eingabe der Kommandozeile liegt als Variable p vor. // Implementierung ... time= System.nanoTime() - time; System.out.println("Zeit in m: "+ time); } }
Überlegungen:
- Welche Zeit wird hier gemessen?
- Was hat ausser dem Algorithmus noch Einfluss auf die Ausführungsgeschwindigkeit?
- Sind Ihre Messungen wiederholbar?
- Welche Risiken hat eine Optimierung des Algorithmus?
- Wie wichtig ist die Schnelligkeit eines Programms?
3.3.6 Übung: Codevereinfachung
// Annahme: j >= 0 i = 0; while (i != j) i++;
while (a < b) { c = a; a = b; b = c; }
3.3.7 Übung: Wochentagberechnung
Lesen Sie ein Datum in Form dreier Zahlen für den Tag, den Monat und das Jahr sowie eine weitere Zahl zwischen 0 und 6 ein, die den Wochentag (Sonntag bis Samstag) des 1. Januars dieses Jahres darstellt. Berechnen Sie den Wochentag des eingelesenen Datums und geben Sie diesen aus. Sie können davon ausgehen, dass die Eingaben korrekt sind. Berücksichtigen Sie auch Schaltjahre.
3.3.8 Übung: Überlaufprüfung
Lesen Sie zwei 32 Bit Ganzahlen (int) a und b ein und prüfen Sie, ob bei ihrer Addition ein Überlauf stattfindet, also eine Summe entstehen würde, die größer als 231 - 1 oder kleiner als -231 ist.
3.3.9 Übung: Schnitt zweier Linien
Lesen Sie die Endpunkte zweier horizontaler oder vertikaler Linien in Form ihrer x- und y-Koordinaten ein und prüfen Sie, ob sich die beiden Linien schneiden. Die beiden Linien befinden sich in einem zweidimensionalen kartesischen System:
Hinweis: Wenn es einen Schnittpunkt gibt ist er (c,b)
3.3.10 Übung: Codevereinfachung
a)
if (b == 0) a = 2 * c; else if (c != 0) a = a * b + 2 * c; else a = a * b;
b)
if (x < 0 && y < 0) a = x * y; else if (x < 0) a = x * (-y); else if (y > 0) a = (-x) * (-y); else a = x * (-y);
3.3.11 Übung: Dreiecksbestimmung
Schreiben Sie ein Java-Programm, das die Seitenlängen eines Dreiecks einliest und prüft, ob es ein
- gleichseitiges
- gleichschenkeliges
- rechtwinkeliges
- sonstiges gültiges
- ungültiges Dreieck ist.
Ein Dreieck ist ungültig, wenn die Summe zweier Seitenlängen kleiner oder gleich der dritten Seitenlänge ist. Beachten Sie, dass ein Dreieck sowohl rechtwinkelig als auch gleichschenkelig sein kann!
3.3.12 Übung: Sortieren
Schreiben Sie ein Java-Programm, das 3 Zahlen a, b und c einliest und sie in sortierter Reihenfolge wieder ausgibt. Im Rahmenprogramm muss die letzte Zeile durch einen Sortieralgorithmus und Ausgaben ersetzt werden.
public class Sortieren { public static void main(String[] args) { int a = 0; int b = 0; int c = 0; if (args.length > 2 ) { try { a = Integer.parseInt(args[0]); b = Integer.parseInt(args[1]); c = Integer.parseInt(args[2]); } catch (NumberFormatException e) { System.err.println("Argument muss Ganzzahl sein"); System.exit(1); } } System.out.println("Eingelesene Werte: " + a + ", " + b + ", " + c); System.out.println("Anstatt dieser Zeile muss ein Sortieralgorithmus implementiert werden..."; } }
3.3.13 Übung: Plausibilitätsprüfung
Lesen Sie ein Datum in Form dreier Zahlen für den Tag, den Monat und das Jahr ein. Prüfen Sie, ob es sich um ein gültiges Datum handelt. Berücksichtigen Sie auch Schaltjahre.
Hinweis: Gregorianischer Kalender: Ein Jahr ist ein Schaltjahr, wenn es durch 4 teilbar ist. Jahre, die durch 100, aber nicht durch 400 teilbar sind, sind keine Schaltjahre.
Vorsicht: In der Musterlösung werden Felder verwendet. Die sind noch nicht vorgestellt worden, sie machen es aber deutlich leichter...
3.3.14 Übung: Textverschlüsselung
Schon im alten Rom verschlüsselte man Nachrichten. Ein einfaches Verschlüsselungsverfahren ist von Julius Cäsar überliefert. Es verschiebt jeden Buchstaben der Nachricht um einen fixen Wert n. Ist n gleich 2, so wird 'A' auf 'C', 'B' auf 'D' und 'Z' auf 'B' verschoben. Ziffern und Sonderzeichen werden nicht verschoben. Schreiben Sie ein Programm, das eine Zahl n und einen beliebigen Text liest und ihn nach obigem Verfahren verschlüsselt wieder ausgibt.
3.3.15 Übung: Verzweigungen
Schreiben Sie ein Java-Programm, das drei Werte x, y und z einliest und prüft, ob
- x, y und z nicht lauter gleiche Werte enthalten,
- x, y und z lauter verschiedene Werte enthalten,
- mindestens zwei Werte gleich sind.
3.3.16 Übung: Häufigkeit von Zeichen
Schreiben Sie ein Programm, das einen Text liest und die Häufigkeit der darinvorkommenden Zeichen berechnet. Geben Sie die Zeichenhäufigkeit als Histogramm aus. Beispiel:
a **** b ** c ******** ...
Hinweis: Dieses Programm setzt Kenntnisse von Feldern vorraus die erst später behandelt werden
3.3.17 Übung: Weckzeiten implementieren
Implementieren Sie zwei logische Tests für die Kontrolle der Weckzeit einer Uhr.
Diese Aufgabe baut auf der Übung zur Implementierung einer analogen Uhr auf.
Sie benötigen 3 Klassen für diese Aufgabe die alle im gleichen Verzeichnis stehen müssen:
- Klasse Zeiger (Lösung von 2.4.11) oder Ihre eigene Implementierung. Diese Klasse muss nicht modifiziert werden.
- Klasse WeckerUhr (weiter unten). Die Klasse muss nicht modifiziert werden. Die Klasse enthält die main() Methode. Es muss immer diese Klasse (java WeckerUhr) zum Starten der Anwendung verwendet werden!
- Klasse Weckzeit: Diese Klasse muss in der Übung modifiziert werden. Die Vorlage der Klasse ist bereits übersetzbasr und ausführbar.
Es reicht die Klasse WeckerUhr zu übersetzen. Die beiden anderen Klassen werden automatisch rekursiv mitübersetzt.
Nach dem Starten der Anwendung mit java WeckerUhr erscheint das folgende Fenster:
Uhr im normalen Zustand |
Uhr beim Klingeln (roter pulsierender Kreis) |
Erste Aufgabe: Kontrolle der Wertebereiche
Die Klasse Weckzeit enthält eine Methode korrekteWeckzeit(int h, int m, int s). Diese Methode prüft die Eingaben des GUI auf korrekte Wertebereiche. Das Ergebnis wird in einer boolschen Variablen result gespeichert. Die Vorlage liefert bei allen Eingaben false. Belegen Sie die Variable so, dass vernünftige Werte akzeptiert werden.
Fragen:
- Was sind vernünftige Werte für Stunde (h), Minute(m), Sekunde(s)?
- Welche logische Verknüpfung muss man nutzen wenn alle Werte im korrekten Bereich sein sollen?
Der Erfolg Ihrer Implementierung können Sie daran erkennen, dass die Eingaben des GUI nach dem klicken des OK Knopfs in das Anzeigenfeld übernommen worden sind.
Zweite Aufgabe: Bestimmen der richtigen Zeitpunkte zum Wecken
Das Lösen der ersten Teilaufgabe ist eine Voraussetzung für den zweiten Teil (Ihr Wecker funktioniert sonst nur Mittags und um Mitternacht...)
Das Hauptprogramm der Klasse WeckerUhr ruft in der aktuellen Implementierung viermal pro Sekunde die Methode klingeln() auf um zu kontrollieren ob der Wecker klingeln soll. Ändern Sie die Referenzimplementierung derart, dass nur nach der eingebenen Weckzeit für eine bestimmte Periode geklingelt wird.
Die zu modifizierende Referenzimplementierung:
result = (aktS%10 == 0);
lässt den Wecker bei allen Sekundenwerten die durch 10 teilbar sind für eine Sekunde klingeln.
Die Variablen aktH, aktM, aktS enthalten die aktuelle Zeit. Die Variablen wzh, wzm, wzs enthalten die Weckzeit.
Fragen:
- Wie lange soll der Wecker klingeln?
- (Zur Verfeinerung) Wie kann man gewährleisten, dass der Wecker auch um 11:59:50 für 15 Sekunden klingelt?
Klasse Weckzeit
package s1.block3; public class Weckzeit { int wzh = 0; // Weckzeit in Stunden int wzm = 0; // Weckzeit in Minuten int wzs = 0; // Weckzeit in Sekunden public void setzeWeckzeit(int hh, int mm, int ss) { if (korrekteWeckzeit(hh,mm,ss)) { wzh = hh; wzm = mm; wzs = ss; } } public boolean korrekteWeckzeit(int h, int m, int s) { boolean result; // benutzen die Variablen h,m,s um eine gültige Zeit zu bestimmen result = false; return result; } public boolean klingeln(int aktH, int aktM, int aktS) { boolean result; // benutzen die Variablen der aktuellen Zeit aktH (Stunde), // aktM (Minute), aktS (Sekunde) und die Weckzeit wzmh, wzm, wzs // um zu bestimmern ob der Wecker klingeln soll // Verbessern Sie diese Zuweisung // In der aktuellen Implementieren klingelt der Wecker // alle 10 Sekunden für 1 Sekunde result = (aktS%10 == 0); return result; } }
Klasse WeckerUhr
package s1.block3; /* * Zeichnen einer analogen Uhr in einem JFrame */ import java.awt.*; import java.awt.event.*; import java.util.Calendar; import javax.swing.*; /** * * @author sschneid */ public class WeckerUhr extends JPanel { int sekunde = 0; int minute = 0; int stunde = 0; boolean klingeln = false; String tzString; // aktuelle Zeitzone int initialHeight; float zoom = 1; boolean an = false; JFrame hf; // Das Fenster der Anwendung Container myPane; JTextField h,m,s; JButton eingabe; Weckzeit wz; int klingelRadius = 0; /** * Konstruktor der Klasse. Er initialisiert die Grafik */ public WeckerUhr() { wz = new Weckzeit(); hf = new JFrame("Uhr"); h = new JTextField(2); m = new JTextField(2); s = new JTextField(2); eingabe = new JButton("OK"); eingabe.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int stunde, minute, sekunde; try { stunde = Integer.parseInt(h.getText()); minute = Integer.parseInt(m.getText()); sekunde = Integer.parseInt(s.getText()); } catch (NumberFormatException ex) { // Es wurde keine korrekte Zahl eingegeben stunde = -100; minute = -100; sekunde= -100; } wz.setzeWeckzeit(stunde,minute,sekunde); } }); // Beenden der Anwendung bei Schließen des Fenster hf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Aufbau des Contentpanes myPane = hf.getContentPane(); myPane.add(this, BorderLayout.CENTER); JPanel wzPanel = new JPanel(new GridLayout(1,0)); wzPanel.add(new JLabel("hh:mm:ss")); wzPanel.add(h); wzPanel.add(m); wzPanel.add(s); wzPanel.add(eingabe); myPane.add(wzPanel,BorderLayout.SOUTH); // Erzeuge einen Menüeintrag zum Beenden des Programms JMenuBar jmb = new JMenuBar(); JMenu jm = new JMenu("Datei"); JMenuItem exitItem = new JMenuItem("Beenden"); exitItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } }); jm.add(exitItem); jmb.add(jm); hf.setJMenuBar(jmb); hf.pack(); // Das JFrame sichtbar machen // Gewünschte Größe setzen // 1. Parameter: horizontale Größe in Pixel // 2. Parameter: vertikale Größe in Pixel hf.setSize(2 * Zeiger.maxRadius + 80, 2 * Zeiger.maxRadius + 130); hf.setVisible(true); hf.setAlwaysOnTop(true); initialHeight = getHeight(); } /** * Hauptprogramm der Anwendung. Es werden keine Eingabeparameter benötigt * @param args dieser Parameter wird nicht ausgewertet */ public static void main(String[] args) { WeckerUhr dieUhr = new WeckerUhr(); dieUhr.tickTack(); } /** * Diese Methode verwaltet den Zeitgeber-thread. Dieser Thread belegt * die statischen Variablen der Uhrzeit neu */ public void tickTack() { try { boolean blinken = false; while (true) { Thread.sleep(250); // Schlafe x Millisekunden // Hole Systemzeit und belege statische Variablen Calendar call = Calendar.getInstance(); tzString = call.getTimeZone().getDisplayName(); sekunde = call.get(Calendar.SECOND); minute = call.get(Calendar.MINUTE); stunde = call.get(Calendar.HOUR); klingeln = wz.klingeln(stunde,minute,sekunde); if (blinken){ klingelRadius=100; } else { klingelRadius=30; } blinken = !blinken; repaint(); } } catch (InterruptedException e) { System.out.println( "Die Anwendung wird wegen einer Ausnahme beendet"); } } /** * Überladene Paintmethode. Sie führt alle Zeichenoperationen im Panel aus * @param g vom Laufzeitsystem übergebenes Graphikobjekt. */ @Override public void paint(Graphics g) { super.paint(g); zoom = (float)getHeight()/(float)initialHeight; int maxRadius = Zeiger.maxRadius; int xCenter = (int)(maxRadius*zoom) + 40; int yCenter = (int)(maxRadius*zoom) + 20; float fontSize = g.getFont().getSize2D(); int charCenterOffSet = (int)(fontSize/2); String timeString = stunde + ":" + minute + ":" + sekunde + " " + tzString; String klingelString; klingelString = wz.wzh +":"+wz.wzm + ":" +wz.wzs +" klingeln"; if (klingeln) { g.setColor(Color.red); g.fillOval(xCenter-((int)(zoom*klingelRadius/2)), yCenter-((int)(zoom*klingelRadius/2)), (int)(klingelRadius*zoom), (int)(klingelRadius*zoom)); } // Zeichne Uhrenhintergrung und Koordinatensystem g.setFont(g.getFont().deriveFont(fontSize)); g.setColor(Color.BLACK); // Farbe g.drawArc(xCenter - 5, yCenter - 5, 10, 10, 0, 360); g.drawLine(xCenter, yCenter, xCenter + 40, yCenter); g.drawLine(xCenter, yCenter, xCenter, yCenter + 40); g.drawString("X", (int)(xCenter + 45*zoom), yCenter + +charCenterOffSet); g.drawString("Y", xCenter - charCenterOffSet, (int)(yCenter + 55*zoom)); g.drawString("12",xCenter - charCenterOffSet, (int)(yCenter - maxRadius*zoom)); g.drawString("3", (int)(xCenter + maxRadius*zoom), yCenter + charCenterOffSet); g.drawString("6", xCenter - charCenterOffSet, (int)(yCenter + 2*charCenterOffSet+maxRadius*zoom)); g.drawString("9", (int)(xCenter - maxRadius*zoom - charCenterOffSet), yCenter + charCenterOffSet); // Zeichne aktuelle Zeit zum Debuggen g.drawString(timeString, 0, (int)(yCenter + maxRadius*zoom)); // Zeichne Weckzeit zum Debuggen g.drawString(klingelString, 0, (int)(yCenter + maxRadius*zoom + 25)); // Zeichne Stundenzeiger g.setColor(Color.BLACK); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.stundeX(stunde)*zoom), (int)(yCenter + Zeiger.stundeY(stunde)*zoom)); g.drawString("h[" + Zeiger.stundeX(stunde) + "," + Zeiger.stundeY(stunde) + "]", 0, (int)(yCenter + maxRadius*zoom - (3*fontSize))); // Zeichne Minutenzeiger g.setColor(Color.RED); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.minuteX(minute)*zoom), (int)(yCenter + Zeiger.minuteY(minute)*zoom)); g.drawString("m[" + Zeiger.minuteX(minute) + "," + Zeiger.minuteY(minute) + "]", 0, (int)(yCenter + maxRadius*zoom - (2*fontSize))); // Zeichne Sekundenzeiger g.setColor(Color.BLUE); g.drawLine(xCenter, yCenter, (int)(xCenter + Zeiger.sekundeX(sekunde)*zoom), (int)(yCenter + Zeiger.sekundeY(sekunde)*zoom-fontSize)); g.drawString("s[" + Zeiger.sekundeX(sekunde) + "," + Zeiger.sekundeY(sekunde) + "]", 0, (int)(yCenter + maxRadius*zoom - fontSize)); } }
- 13703 views
Primfaktorzerlegung
die Zahl 252 aus den Primfaktoren 3, 3, 4, 7.
4 ist keine Primzahl hier müsste 2x die 2 hin
Stimmt, danke
Wurde verbessert.