Zeichenketten

Werbung
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
Einführung in die Informatik
- Teil 5b Zeichenketten
mit dem JBuilder
Inhalt:
1. Bezug zum Unterricht: Anwendungen
2. Oberfläche und Ereignisverarbeitung
2.1 Die Erzeugung von GUI-Komponenten
2.2 Die Verarbeitung von Ereignissen
2.3 Ein Applet zur Ein- und Ausgabe von Zeichenketten
3. Methoden zur Zeichenkettenverarbeitung
4. Verschlüsselungsverfahren
5. Aufgaben:
Literaturhinweise:
• Küchlin/Weber: Einführung in die Informatik, Objektorientiert mit Java,
Springer 1998
• Krüger, Guido: Handbuch der Java-Programmierung,
http://www.javabuch.de oder Addison Wesley 2002
S. 1
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S. 2
Zeichenketten
1.
Bezug zum Unterricht: Anwendungen
Die im Unterricht benutzten Elemente einer Programmiersprache sollten sich nicht aus Vollständigkeits- oder anderen fachimmanenten Überlegungen ergeben, sondern möglichst aus einer Problemstellung abgeleitet werden, die Bezug zu den Möglichkeiten und Folgen der Anwendung von Informatiksystemen hat. Da außer bei grafischen Problemen fast die gesamten
Ein- und Ausgabe von Programmen über Zeichenketten erfolgt, ergeben sich entsprechend
viele Anwendungsmöglichkeiten:
•
•
•
•
Reine Datenverarbeitung (Daten einlesen, Typkonvertierungen, verarbeiten, ausgeben)
Verschlüsselung (Sicherheit, eCommerce, Vertrauen im Netz, ...)
Symbolverarbeitung (Computeralgebra, DNA-Strukturen, mathematische Anwendungen... )
Textinterpretation (Syntax, Mustererkennung, Übersetzung, Ersetzung, Suchvorgänge,
...)
Nebenbei bietet die Zeichenkettenverarbeitung gute Möglichkeiten zur Binnendifferenzierung und eine Fülle von Aufgaben zur Leistungsmessung, die von sehr einfachen Fällen für
den Anfangsunterricht bis zu ziemlich kniffeligen Problemen reichen.
2.
Oberfläche und Ereignisverarbeitung
Zeichenketten werden innerhalb des Java-Programms verarbeitet. Um Ausgangsmaterialien
einzulesen und Ergebnisse darzustellen, benötigt man eine Verknüpfung mit Darstellungskomponenten des Bildschirms, die ziemlich beliebig ist. Wir wollen uns hier zur Darstellung
auf Textfelder in einem Applet beschränken und Aktionen mit Knöpfen auslösen.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
Appletoberfläche
mit Textfeldern
und Buttons
Javaprogramm, das
die gewünschten
Aktionen ausführt
public class Applet1 extends Applet implements ActionListener
{
Label lrein = new Label("Eingabe: ");
Label lraus = new Label("Ausgabe“);
Button start = new Button("start!");
TextField rein = new TextField(40);
Die Arbeitsweise solcher Programme ist immer gleich:
•
•
•
zuerst wird die grafische Oberfläche (GUI) erzeugt und angezeigt,
dann wartet das Applet auf Eingaben, z. B. auf aus Eintippen eines Textes in ein Textfeld, (schon dabei werden jede Menge Ereignisse (Events) ausgelöst, z. B. beim Loslassen einer Taste, die wir hier aber ignorieren wollen)
beim Anklicken eines Knopfes (Buttons) wird ein Ereignis ausgelöst, das im Programm den gewünschten Ablauf startet. Dazu holt sich das Programm die erforderlichen Daten aus den GUI-Komponenten, verarbeitet sie und stellt die Ergebnisse auf
diesen oder anderen GUI-Komponenten dar.
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
S. 3
Eckart Modrow
2.1
Die Erzeugung von GUI-Komponenten
Wir benötigen von den GUI-Komponenten des AWT (abstract windowing toolkit) von Java
nur Label-, TextField- und Button-Objekte. Wir erzeugen sie mit Hilfe des JBuilderDesigners, der auf der Registerkarte gleich neben dem Editor zu finden ist.
AWTKomponenten
Eigenschaften
Ereignisse
Designer
Im Eigenschaftsfenster des Applets
setzen wir das Layout auf null (damit werden die Komponenten frei
positionierbar), klicken dann oben
auf die Registerkarte AWT, wählen
die Label-Komponente („A“) aus
und platzieren ein solches Objekt
auf das Applet (durch Klicken). Danach ändern wir die Eigenschaften
des Objekts: Wir setzen die Schriftgröße (font) z. B. auf 40, wählen als
Text das Wort „Hallo!“ in rot und
zentriert können auch noch den
Namen von label1 z. B. auf
Begruessungstextanzeige
ändern.
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S. 4
Der vom JBuilder erzeugte Quelltext lautet:
package label1;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
der übliche Kopf
die erzeugte Label-Komponente
public class Applet1 extends Applet {
private boolean isStandalone = false;
Label Begruessungstextanzeige = new Label();
//Parameterwert holen
public String getParameter(String key, String def) {
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
}
//Das Applet konstruieren
public Applet1() {
}
//Das Applet initialisieren
Die im Eigenpublic void init() {
schaftsfenster
try {
vorgenommenen
jbInit();
}
Einstellungen
catch(Exception e) {
umsetzen
e.printStackTrace();
}
}
//Initialisierung der Komponenten
private void jbInit() throws Exception {
Begruessungstextanzeige.setAlignment(Label.CENTER);
Begruessungstextanzeige.setFont(new java.awt.Font("Serif", 0, 40));
Begruessungstextanzeige.setForeground(Color.red);
Begruessungstextanzeige.setText("Hallo!");
Begruessungstextanzeige.setBounds(new Rectangle(65, 87, 257, 80));
this.setLayout(null);
this.add(Begruessungstextanzeige, null);
}
//Applet-Information holen
public String getAppletInfo() {
return "Applet-Information";
}
//Parameter-Infos holen
public String[][] getParameterInfo() {
return null;
}
Der restlichen Quelltextzeilen sind „Bürokratie“ und können von uns erstmal ignoriert – aber
nicht gelöscht! - werden.
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
2.2
S. 5
Die Verarbeitung von Ereignissen
Wir wollen uns hier auf Reaktionen beschränken, die auf das Anklicken eines Buttons erfolgen. Dazu müssen wir den Button – als Ereignissender - mit einem Ereignisempfänger verbinden (einem Listener), der die gewünschten Aktionen mit einer Ereignisbehandlungsmethode auslöst. Wir wollen beim Button das ActionEvent benutzen, das durch das Anklicken
ausgelöst wird. (Genauso gut hätten wir auch ein Mausereignis nehmen können!) Es gibt in
Java sehr viele verschiedene Möglichkeiten, auf Ereignisse zu reagieren. Wir wollen hier das
vom JBuilder automatisch erzeugte Verfahren besprechen:
Die in Java benutzten Listener reagieren meist auf eine ganze Reihe von Ereignissen, für die
wir dann die entsprechenden Methoden schreiben müssen – auch dann, wenn wir sie gar nicht
benötigen. Um das zu umgehen, gibt es die so genannten Adapterklassen, die für alle benötigten Methoden leere Methodenrümpfe besitzen. Aus solch einer Adapterklasse leitet der JBuilder dann eine Tochterklasse ab, die die nicht benötigten leeren Methoden erbt und nur die im
Eigenschaftsfenster angegebenen Methoden überschreibt. Das ist auf den ersten Blick umständlich, spart aber Schreibarbeit.
Doppelklicken wir im Designer auf den Button, dann wird eine Klasse
Applet1_button1_actionAdapter erzeugt, die eine Methode button1_actionPerformed bereitstellt, in die wir den Code eingeben können, der beim Anklicken des Buttons ausgeführt wird.
class Applet1_button1_actionAdapter implements
java.awt.event.ActionListener {
Applet1 adaptee;
}
Applet1_button1_actionAdapter(Applet1 adaptee) {
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e) {
adaptee.button1_actionPerformed(e);
}
hier wird die actionPerformed-
Methode des Applets („adaptee“)
aufgerufen
Die Abläufe sind dann so:
Vorbereitung:
ActionAdapterKlasse angeben …
… und beim Button
als Listener anmelden …
Ausführung:
Der Button
wird angeklickt
ein ActionEvent
wird dem Listener übergeben
… und auf Action-Ereignisse warten
die actionPerformedMethode des Applets wird
vom Listener aufgerufen
und löst die gewünschten
Aktionen aus
Ein Beispiel, bei dem sich auf Mausklick die Aufschrift des Buttons ändert, sieht so aus:
//.. der übliche Kopf
public class Applet1 extends Applet {
Button button1 = new Button();
public Applet1()
{ /… wie immer }
Button erzeugen
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
private void jbInit() throws Exception {
Eigenschaften
button1.setFont(new java.awt.Font("Dialog", 0, 40));
button1.setLabel("Hallo!");
einstellen
button1.setBounds(new Rectangle(84, 95, 244, 75));
button1.addActionListener(new Applet1_button1_actionAdapter(this));
this.setLayout(null);
this.add(button1, null);
ActionListener (s.o.) hinzufügen
}
void button1_actionPerformed(ActionEvent e) {
button1.setLabel("hat geklappt");
}
}
Reaktion auf Mausklicks
S. 6
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
2.3
S. 7
Ein Applet zur Ein- und Ausgabe von Zeichenketten
Wir wollen zwei Textfelder benutzen, deren Inhalte wird mit den Methoden getText() bzw.
setText() lesen und beschreiben können. Ein Start-Button soll die Verarbeitung einleiten.
Zwei Label-Komponenten beschriften die Felder. Der Inhalt des oberen Eingabefeldes wird in
Grossbuchstaben im unteren dargestellt.
Wir erzeugen die benötigten Komponenten (zwei Label, zwei Textfelder und einen Button)
im Designer und stellen die Eigenschaften so ein, dass das Ergebnis dem Screenshot oben ähnelt. Dabei vergessen wir nicht, die Abmessungen im Appletviewer (Projekteigenschaften …)
so einzustellen, dass auch alles zu sehen ist.
Dann müssen wir nur noch auf den Button doppelklicken und drei (hier fett und rot gedruckte)
Zeilen in die ActionPerformed-Methode schreiben:
package zeichenketten1;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Applet1 extends Applet {
Label lEingabe = new Label();
Label lAusgabe = new Label();
TextField tAusgabe = new TextField();
TextField tEingabe = new TextField();
Button button1 = new Button();
public Applet1() {//wie immer}
Komponenten
erzeugen
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S. 8
private void jbInit() throws Exception {
Eigenschaften
lEingabe.setFont(new java.awt.Font("Dialog", 0, 20));
lEingabe.setText("Eingabe:");
einstellen
lEingabe.setBounds(new Rectangle(6, 10, 86, 37));
this.setLayout(null);
lAusgabe.setBounds(new Rectangle(4, 53, 90, 37));
lAusgabe.setText("Ausgabe:");
lAusgabe.setFont(new java.awt.Font("Dialog", 0, 20));
tAusgabe.setFont(new java.awt.Font("Dialog", 0, 20));
tAusgabe.setText("");
tAusgabe.setBounds(new Rectangle(98, 60, 503, 36));
tEingabe.setFont(new java.awt.Font("Dialog", 0, 20));
tEingabe.setText("");
tEingabe.setBounds(new Rectangle(97, 11, 503, 36));
button1.setBackground(Color.orange);
button1.setFont(new java.awt.Font("Serif", 0, 20));
button1.setForeground(Color.red);
button1.setLabel("Start!");
button1.setBounds(new Rectangle(15, 110, 93, 40));
button1.addActionListener(new Applet1_button1_actionAdapter(this));
this.add(lEingabe, null);
this.add(lAusgabe, null);
this.add(tAusgabe, null);
this.add(tEingabe, null);
this.add(button1, null);
}
void button1_actionPerformed(ActionEvent e) {
String eingabe = tEingabe.getText();
String ausgabe = eingabe.toUpperCase();
tAusgabe.setText(ausgabe);
}
}
class Applet1_button1_actionAdapter implements
java.awt.event.ActionListener {// wie immer }
Text holen,
umwandeln
und ausgeben
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
S. 9
Eckart Modrow
3.
Methoden zur Zeichenkettenverarbeitung
Zeichenketten bezeichnet man als Strings. Es gibt eine String-Klasse und eine StringBufferKlasse. Sie unterscheiden sich dadurch, dass Strings als final deklariert, StringBuffer aber dynamisch sind. Verändert man also Strings, so erhält man einen neuen String, während StringBuffer geändert werden. (Es gibt auch noch andere Unterschiede.) Für unsere Zwecke sind
die Unterschiede ohne Bedeutung: wir verwenden Strings.
Einen Strings können wir uns als eine Folge von Zeichen vorstellen, wobei die Nummerierung bei Null beginnt.
Die Zählung beginnt bei 0!
D a
s
i
s
t
e
i
n
S
t
r
i
n g
Im String stehen 16-Bit-Unicode-Zeichen. Bei Bedarf können wird diese Zeichen durch
Typecasting in ganze Zahlen umwandeln - z. B. um die Ordnungsnummer des Zeichens zu
bestimmen: int i = (int)’c’; Will man solche Zahlen in Textfeldern darstellen,
dann gibt es drei „Tricks“ dafür:
• Entweder man verwandelt die ganze Zahl in ein Objekt der Wrapper-Klasse Integer,
das dann in einen String umgewandelt wird:
raus.setText(new Integer(i).toString());
• oder man hängt die Zahl einfach an einen existierenden String (z. B. ein Leerzeichen)
an – dann erfolgt eine automatische Typumwandlung. Zur Not kann man das erste
Zeichen dann wieder entfernen:
raus.setText(“ “+i);
• oder man benutzt eine der statischen Umwandlungsmethoden valueOf() der StringKlasse:
raus.setText(String.valueOf(i));
Von den zahlreichen Methoden der String-Klasse wollen wir nur einige benutzen:
charAt(int)
liefert das entsprechende Zeichen zurück
compareTo(String)
vergleicht mit einem String
concat(String)
verbindet mit einem String
indexOf(String)
liefert den Index des ersten Zeichens des Teilstrings
length()
liefert die Länge des Strings
replace(char1, char2)
ersetzt alle Zeichen char1 durch char2
substring(int, int)
liefert einen Teilstring
toLowerCase()
konvertiert in Kleinschreibung
toUpperCase()
konvertiert in Grossschreibung
toString()
wandelt ein Objekt in einen String um
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S.
10
4.
Verschlüsselungsverfahren
Eines der ältesten kryptografischen Verfahren ist das Cäsar-Verfahren, bei dem alle Zeichen
zyklisch um eine Stelle im Alphabet verschoben werden: AÆB, BÆC, ..., ZÆA
In der folgenden Verschlüsselungsmethode wird ausgiebig vom Typecasting Gebrauch gemacht: Zeichen werden in Zahlen und diese wieder in Zeichen umgewandelt.
public void actionPerformed(ActionEvent e)
{
char c,d;
int nr,max,min;
eingabe = rein.getText().toUpperCase();
ausgabe = "";
max = (int)'Z';
min = (int)'A';
for(int i=0;i<eingabe.length();i++)
{
c = eingabe.charAt(i);
nr = (int)c;
nr = nr + 1;
if (nr > max) nr = (nr-max)+min-1;
ausgabe = ausgabe+(char)nr;
}
raus.setText(ausgabe);
}
Die Zeichen können natürlich auch um andere Werte verschoben werden.
Versetzungsverfahren:
Die Zeichen werden zeilenweise in einen „Block“ der Breite n geschrieben und spaltenweise
wieder ausgelesen:
Klartext:
DIE GROESSTEN KRITIKER DER ELCHE WAREN FRUEHER SELBER WELCHE
Block mit n=8:
D
S
I
E
W
U
L
C
I
S
T
R
A
E
B
H
E
G
T E N
I K E
E L
R E N
H E R
E R
E
R O
K
R
C H
F
S
W E
E
R
D
E
R
E
L
Geheimtext: DSIEWULCISTRAEBHETI RHEE EKEEER GNELNR R RC W OK HFSE ERDEREL
XOR-Verschlüsselung:
Der Klartext wird mit Hilfe eines Schlüsselwortes verschlüsselt. Dazu werden Klartext und
der ggf. wiederholte Schlüssel untereinander geschrieben. Die Ordnungsnummern der Zeichen werden in die Dualdarstellung gebracht und bitweise xor-verschlüsselt: Stehen zwei
gleiche Ziffern (Nullen oder Einsen) übereinander, dann ergibt sich eine Null, sonst eine Eins.
Das Verfahren ist durch nochmalige Verschlüsselung umkehrbar und sehr schnell. Die
Schlüssel können z. B. in einer Chipkarte gespeichert sein.
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S.
11
Klartext:
Schlüssel:
GEHEIM
TEST
71 69 72 69 73 77
84 69 83 84 84 69
1000111 1000101 1001000 1000101 1001001 1001101
1010100 1000101 1010011 1010100 1010100 1000101
0010011 0000000 0011011 0010001 0011101 0001000
19
0
27
17
29
8
Das Ergebnis wird wieder in eine Zeichenfolge umgewandelt (die hier aber nicht im normalen
Zeichensatz liegt).
Blockweises Chiffrieren:
Die Zeichen werden „fest verdrahtet“ auf einander abgebildet. Die „Verdrahtung“ ist gut auf
einer Chipkarte unterzubringen.
A
B
C
D
E
F
G
H
I
J
K …..
A
B
C
D
E
F
G
H
I
J
K …..
Einwegverfahren:
Die Verfahren beruhen darauf, dass Zahlen, insbesondere große, leicht multipliziert, aber nur
schwer faktorisiert werden können. Damit wird es möglich, einen öffentlichen Schlüssel
(public key) frei zu verteilen, mit dem Texte verschlüsselt werden. Nur mit einem dazu
passenden privaten Schlüssel (private key) können sie wieder entschlüsselt werden. Das
bekannte RSA-Verfahren, mit dem z. B. die Pretty-Good-Privacy-(PGP)-Verfahren des Internets arbeiten, funktioniert wie folgt:
Hat man zwei Primzahlen p und q sowie zwei
Zahlen n=p*q und r<n, dann gilt:
Z(p-1)*(q-1)*r+1 modulo (p*q) = Z
Wählt man jetzt zwei natürliche Zahlen x und y,
für die gilt:
x*y = (p-1)*(q-1)*r+1
dann können wir mit ihrer Hilfe eine Zahl Z
verschlüsseln und wieder entschlüsseln:
Zx*y modulo n = (Zx)y modulo n = Z
Wir geben deshalb den öffentlichen Schlüssel x und die Zahl n allgemein bekannt, und dazu
das Kodierungsverfahren:
Mit allen Zeichen des Klartextes tue
Z
Ordnungsnummer des Zeichens
V
Z x modulo n
Die Dekodierung erfolgt mit Hilfe des privaten Schlüssels y:
Mit allen Zeichen des verschlüsselten Textes tue
V
Ordnungsnummer des Zeichens
Z
V y modulo n
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S.
12
Wir wollen das Verfahren an einem Beispiel durchgehen:
Als Primzahlen wählen wir:
deren Produkt ist
Als r wählen wir beliebig
und damit das Produkt
x bestimmen wir so,
dass auch y eine ganze Zahl ist
und erhalten für y
p = 97 und q = 151,
n = 14647.
r = 11,
x*y = 96*150*11+1 = 144001.
x = 19
y = 7579.
Jetzt kann es losgehen:
Wir verschlüsseln das Klartextzeichen „A“:
Ordnungsnummer Z von „A“:
Z = 65
verschlüsselte Zeichennummer V: V = 6519 modulo 14647 = 12561
Der Empfänger möchte wieder entschlüsseln:
Geheimzeichennummer V:
V = 12561
Klartextzeichennummer Z:
Z = 125617579 modulo 14647 = 65
Klartextzeichen:
„A“
Da sich bei dem Verfahren riesige Zahlen durch die Potenzen ergeben, benötigen wir noch ein
schnelles Verfahren, um die Reste dieser Potenzen zu berechnen:
Berechnung von r = BasisExponent modulo n:
b
Basis
e
Exponent
r
1
SOLANGE e <> 0 TUE
e ist eine gerade Zahl
Wahr
Falsch
b
(b*b) MOD n
e
e DIV 2
e
r
e-
(r * b) MOD
Virtuelle Lehrerweiterbildung Informatik in Niedersachsen
Zeichenketten mit J++
Eckart Modrow
S.
13
5.
Aufgaben:
1. a: Realisieren Sie das Cäsar-Verfahren für beliebige Verschiebungswerte. Entwickeln Sie
eine GUI, in der die Verschiebungsweite ausgewählt werden kann. Entschlüsseln Sie
die Texte auch wieder.
b: Realisieren Sie das Versetzungsverfahren. Ermöglichen Sie auch hier Wahlmöglichkeiten.
c: Realisieren Sie die XOR-Verschlüsselung. Wandeln Sie dazu die Zeichen in Bitfolgen
um. Probieren Sie alternativ den XOR-Operator für Zahlen aus.
2. a: Realisieren Sie das beschriebene Verfahren zur Berechnung von Resten großer Potenzen.
b: Benutzen Sie alternativ für diese Berechnung die Java-Klasse BigInteger.
3.
Verschlüsseln Sie längere Texte und stellen Sie die Verteilung der Zeichen in Tabellenform oder grafisch als Histogramm dar. Versuchen Sie die Zeichen anhand der Zeichenhäufigkeit zu entschlüsseln. Funktioniert das bei allen Verfahren?
4. a: Extrahieren Sie eine Zahl, die als Zeichenkette eingegeben wurde. Benutzen Sie das Java-Hilfesystem.
b: Geben Sie Rechenaufgaben als Zeichenketten ein: „3+4=“, „12-5=“, ... Suchen Sie die
Zahlen und die Operatoren im String und geben Sie das Ergebnis aus.
c: Analysieren Sie Polynome, die als String eingegeben werden. Beginnen Sie mit einstelligen ganzen Zahlen als Koeffizienten und Exponenten. „f(x)=3*x^2-2*x-1“. Weiten Sie
dann die Zahlendarstellung aus.
d: Stellen Sie die Graphen der eingegebenen Funktionen dar.
5. a: Benutzen Sie die Lösung aus 4.b, um die Ableitung ganzrationaler Funktionen zu
bestimmen.
b: Diskutieren Sie das Problem, Produkt-, Quotienten- und Kettenregel auf entsprechende
Funktionen anzuwenden. Welche Teilprobleme müssen gelöst werden?
Herunterladen