Lass uns reden! 1

Erstellt von Frithjof Fri, 29 Jun 2007 22:19:00 GMT

Na schön, das mit dem Ausgeben klappt ja nun schon recht gut. Irgendwie kann es aber nicht alles sein, wenn das Rubyprogramm nur gestartet wird, ein wenig was arbeitet und dann irgendetwas ausgibt. Das ist, als wenn dir jemand gegenüber steht, der nur plaudert und dich nicht zu Wort kommen lässt. Dabei hast du auch etwas zu sagen, oder?

Ganz so schlimm ist es aber doch nicht. Ein wenig hattest du schon zu sagen – das Fahrrad konntest du mit der L- und R-Taste steuern und mit der X-Taste vom Rad absteigen.

In diesem Artikel zeige ich dir, wie du dein Rubyprogramm dazu bekommst, sich mit dem, der es ausführt zu unterhalten.

Eingaben von Anwenderinnen abfragen

Schauen wir uns gleich folgendes Programm an:


# theorie_02.rb

print "Gib eine Zahl a zwischen 1 und 100 ein! a=" 
a = gets
a = a.chomp
a = a.to_i

zahl_teilbar_durch_3 = false
if a % 3 == 0 
  zahl_teilbar_durch_3 = true
end

puts "Du hast a=#{a} eingegeben." 
if zahl_teilbar_durch_3
  puts "#{a} ist durch 3 teilbar." 
else
  puts "#{a} ist nicht durch 3 teilbar." 
end

Wir fordern die Anwenderin zunächst mit der Ausgabe Gib eine Zahl a zwischen 1 und 100 ein! dazu auf, na was wohl, natürlich eine Zahl einzugeben, die größer oder gleich 1 aber kleiner oder gleich 100 ist. Damit sie weiß, wo beim Tippen die Zahl erwartet wird, schreiben wir noch das a= hin. Direkt nach dem = wird dann an der Kommandozeile das erscheinen, was sie eintippt. Ruby wartet nun darauf, solange, bis sie die Enter-Taste drückt.

Dann geht unser Programm zur nächsten Zeile und liest das was eingegeben wurde von der Kommandozeile in die Variable a ein. In a steht nun eine Zeichenkette mit dem Sonderzeichen für die Entertaste \n am Schluß.

Dieses Sonderzeichen schneiden wir mit dem Befehl chomp (englisch: mampfen) ab. Den Befehl oder besser die Nachricht chomp schicken wir direkt an die Variable a. Das kennst du auch schon aus den früheren Lektionen. Wir trennen dabei die Nachricht chomp vom Variablennamen mit dem Punkt . ab. Das was nach dem Abschneiden von \n noch übrig bleibt, weisen wir wieder der Variablen a zu.

In der nächsten Zeile schicken wir wieder eine Nachricht an a und zwar lautet diese to_i. Das ist die Abkürzung für englisch to integer, d.h. mache eine ganze Zahl daraus!. Den dadurch entstehenden Zahlenwert weisen wir wieder der Variablen a zu. Wir könnten auch jedesmal eine andere Variable verwenden. Da wir aber eigentlich nur am Zahlenwert interessiert sind, können wir den Wert von a ohne Sorge überschreiben.

So, jetzt steht in a keine Zeichenkette (in Ruby String genannt) mehr, sondern eine Zahl (in Ruby Fixnum oder Integer genannt).

Mit der Zahl a führen wir nun den Test durch, ob sie durch 3 teilbar ist. Dazu berechnen wir den Rest bei der Division durch 3. Den Rest erhalten wir mit dem Operator %. Nur wenn der Rest beim Teilen durch 3 Null ist, ist die Zahl (restlos) durch 3 teilbar. Ob sie das ist, merken wir uns in der Variablen zahl_teilbar_durch_3.

Okay, nun können wir der Anwenderin Bescheid geben, was wir herausgefunden haben. Wir zeigen ihr zuerst nochmal das, was sie eingegeben hat. Halt, das stimmt eigentlich nicht. Sie hat ja genau genommen noch die Entertaste eingegeben. Aber das will sie sicher nicht wissen.

Schließlich verraten wir ihr noch, ob die Zahl durch 3 teilbar ist oder nicht.

Und wenn sie nicht auf mich hört?

Versuche das Programm zu starten und gib mal eine Zahl ein, die größer als 100 ist. Es geht! Warum auch nicht. Wir prüfen nirgendwo, ob die eingegebene Zahl auch tatsächlich einen Wert hat, den wir gefordert haben. Das überlasse ich dir als Übung.

Die Büchse der Pandora

Ein Programm, das man startet, es dann irgendetwas tut und sich am Ende mit irgendeiner Ausgabe verabschiedet ist einfach. Wobei einfach hier nicht im Sinne zu verstehen ist, dass solche Programme nicht auch kompliziert oder auch schwierig zu entwickeln sein könnten. Nein, mit einfach meine ich, dass der Ablauf des Programmes recht übersichtlich ist. Man gibt etwas ein, wartet und schaut sich dann das Ergebnis an. Fertig.

Sobald du aber ein Programm während seiner Laufzeit (englisch: runtime), also nachdem du es gestartet hast und es noch nicht fertig ist, für die Anwenderinnen öffnest, verliert es seine einfache Ablaufstruktur.

Kommunizierst du mit einem realen Menschen direkt von Angesicht zu Angesicht, kannst du auf ihr Reden sofort reagieren. Du siehst ihre Mimik und Gestik und hörst auch auf den Ton, wie sie etwas sagt. Daraus kannst du neben den Worten, die von ihr an dein Ohr dringen, sogar noch eine zusätzliche Bedeutung entnehmen.

Die Kommunikation mit einem realen Menschen, allerdings nicht direkt, sondern nun über den Umweg eines Computerprogramms ist da anders. Der Austausch von Information geschieht hier zeitlich versetzt. Du musst dir während du das Programm entwickelst, Gedanken darüber machen, wie du die Fragen stellst, welche Antworten du erwartest und wie du wiederum auf diese Antworten reagieren möchtest.

Angenommen, du schreibst ein Programm, dass zwei Zahlen a und b einliest und als Ausgabe den Quotienten aus a/b ausgeben soll. Du forderst die spätere Anwenderin deines Programms etwa so auf:


"Gib die erste Zahl größer als 1 ein! a=" 
...
"Gib die zweite Zahl größer als 1 ein! b=" 

Nun hast du in deinem Programm zwei Variablen a und b. Du weißt aber während du das Programm entwickelst nicht, welchen Wert genau a und b haben werden. Du wirst sicher nicht dabei sein, wenn sie irgendwo auf der Welt vor ihrem Computer sitzt und dein Programm ausführt, du siehst nicht, was sie eingibt. Es wäre leichtsinnig sich darauf zu verlassen, dass sie wirklich das macht, wozu du sie aufgefordert hast, nämlich zwei Zahlen einzugeben, die beide je größer als 1 sind. Was, wenn sie für b eine Null eintippt? Die Division durch Null ist in der Mathematik nicht erlaubt. Ruby wird sich mit einer Fehlermeldung beklagen. Je mehr Fehlermeldungen dein Programm produziert, ums so mehr wird das Vertrauen in deine Software sinken. Sie wird nie sagen Oh, ich habe eine Null eingegeben, das war mein Fehler. Stattdessen wird sie sagen So ein dummes Programm, es lässt einfach zu, dass ich eine Null eingeben kann. Dabei weiß doch jeder, dass man durch Null nicht dividieren kann. Und sie wird sich ein anderes Divisionsprogramm suchen.

Sobald dein Programm interaktiv genutzt werden soll—also nicht nur Ausgaben produziert, sondern auch Eingaben entgegen nimmt—bist du gezwungen, jede Eingabe zu prüfen. Liegt sie nicht in dem Bereich, mit dem du weiterarbeiten kannst, dann gibt dein Programm eine freundliche Hinweismeldung zurück.

Es gibt verschiedene Formen von fehlerhaften Eingaben:

  1. Unabsichtliche Fehleingaben Vielleicht waren deine Anweisungen nicht verständlich genug. Oder sie hat sie nicht richtig gelesen, oder hat einfach die falsche Taste erwischt.
  2. Bewusste Fehleingaben Sie legt es darauf an, dein Programm in einen Fehlerzustand zu versetzen. Entweder, um dir zu zeigen, dass du dein Programm nachlässig entwickelt hast, oder sogar, um dir absichtlich zu schaden. Insbesondere ist Software, die über das Internet genutzt wird böswilligen Angriffen ausgesetzt. Sie will über dein Programm hinaus eigentlich an die dahinterliegende Hardware herankommen, bpsw. an den Server und seine Festplatten, um dort an weitere Daten zu gelangen, die du in deinem Programm niemals freiwillig über das Internet zu ihr geschickt hättest.

Du wirst bald merken, dass du manchmal viel mehr Code dafür schreiben musst, um diese Fehleingaben sicher abfangen zu können, als für das, was du eigentlich mit deinem Programm anbieten möchtest.

Üben mit Peter und Livia

  1. Livia: Ich will aber keine Zahl zwischen 1 und 100 eingeben. Vielleicht will ich überhaupt keine Zahl eingeben. Ändere obiges Programm so ab, dass ich dann eine höfliche Fehlermeldung von dir bekomme!
  2. Peter: Entwickle ein Programm, das folgendes macht:
    • Es verlangt von der Anwenderin eine Zahl zwischen 1 und 5. Nennen wir sie n.
    • Es fragt dann die Anwenderin nacheinander n mal nach je einer weiteren Zahl im Bereich von 1 bis 1000.
    • Am Schluß teilt es der Anwenderin mit, ob die eingegebenen n Zahlen jede für sich eine Primzahl ist. Eine Primzahl ist eine Zahl, die nur durch 1 und sich selbst teilbar ist.

schreib und schreibe oder puts und print 2

Erstellt von Frithjof Sun, 24 Jun 2007 20:30:00 GMT

Das ist der erste reine Theorieartikel. Ich schiebe damit den Start des neuen Blocks an Lektionen noch etwas auf. Wir wollen ab Lektion 11 ein Spiel programmieren. Darauf möchte ich dich mit den folgenden Theorielektionen etwas besser vorbereiten.

In Lektion 7 hatten wir schon ein recht umfangreiches Programm geschrieben. Wir konnten ein Fahrrad auf der Straße vor einer Häuserreihe mit der Tastatur hin und her fahren lassen. Wenn du dir das Programm zur Wiederholung nochmals anschaust, stellst du sicher fest, dass es sich trotz der paar Wochen Abstand immer noch gut lesen lässt.

Das liegt zu einem großen Teil daran, dass wir viele deutsche Befehle und Variablennamen verwenden. Wenn dort der Befehl schreib dach steht, ist klar, was passiert – es wird etwas ausgegeben, was das Dach eines Hauses darstellen soll.

Die deutschen Namen für die Variablen sind sehr okay. Die deutschen Befehle wie schreibe, schreib, lies_ein_zeichen und dergleichen wollen wir aber schrittweise durch die richtigen Rubybefehle ersetzen. Keine Angst, dadurch werden unsere Programme nicht unleserlicher. Im Gegenteil, oft sind die deutschen Begriffe etwas länger und machen den Programmcode etwas zu dicht.

Wie du dir sicher denken kannst, sind die echten Befehle in Ruby hauptsächlich in englischer Sprache, entweder als komplettes Wort oder als Abkürzung. Schauen wir uns also als erstes heute einmal die Befehle für die Ausgabe genauer an.

schreibe oder puts

Mit dem schreibe Befehl können wir Text (Zeichenketten) oder Zahlen ausgeben. Am Ende der Ausgabe wird dabei immer die Zeile abgeschlossen, sodass jede weitere Ausgabe in der Zeile darunter beginnt. Etwa so:


schreibe "Dies ist der Text der Ausgabe" 

Den Befehl schreibe habe ich in der Datei rubykids.rb festgelegt. Der echte Rubybefehl, der dasselbe macht wie schreibe lautet puts. puts steht für die englischen Wörter put string oder put as string oder output as string, was soviel heißt wie gib es als Zeichenkette aus. Du kannst somit überall, wo wir den Befehl schreibe verwendet haben, ihn durch puts ersetzen.

Nach dem Befehl selbst folgt der Text oder die Zahl die ausgegeben werden soll. Folgt stattdessen der Name einer Variablen, dann wird nicht der Name, sondern der Inhalt der Variablen ausgegeben. Mehrere Ausgabeargumente lassen sich durch je ein Komma trennen. puts beginnt dann allerdings hinter jedem Argument einen neue Zeile (schreibe macht das ebenfalls).


puts "Erste Zeile", "Zweite Zeile", 5*3

Die Ausgabe sieht dann so aus:


C:\entwicklung>ruby test.rb
Erste Zeile
Zweite Zeile
15

C:\entwicklung>

schreib oder print

Der Befehl schreib arbeitet fast genauso wie schreibe, allerdings springt er nach der Ausgabe nicht in eine neue Zeile. So wird jede weitere Ausgabe direkt danach angefügt.

Der echte Rubybefehl, der dasselbe macht lautet print (englisch drucken). Auch ihm kannst du mehrere Argumente durch Komma getrennt mitgeben.

Nehmen wir bspw. den obigen Code und ersetzen nur puts durch print dann siehst du den Unterschied:


print "Erste Zeile", "Zweite Zeile", 5*3

Die Ausgabe ist eine einzige Zeile, alle Argumente sind aneinander geklatscht:


C:\entwicklung>ruby test.rb
Erste ZeileZweite Zeile15
C:\entwicklung>

Du kannst aber mit print natürlich auch eine neue Zeile erzeugen. Weißt du noch, wie das komische Sonderzeichen für den Zeilenumbruch war? Wir hatten es in den letzten Lektionen mal verwendet – \n. Wenn wir die beiden ersten Argumente mit dem Newline Zeichen abschließen, dann wird jedes Argument in einer eigenen Zeile ausgegeben, obwohl wir den print Befehl verwenden:


print "Erste Zeile\n", "Zweite Zeile\n", 5*3

Ausgabe:


C:\entwicklung>ruby test.rb
Erste Zeile
Zweite Zeile
15
C:\entwicklung>

Üben mit Peter und Livia

In den Theorieartikeln werden dir Peter und Livia ein paar Aufgaben stellen, die du selbstständig zur weiteren Übung lösen kannst. Wenn du dir eine Lösung erarbeitet hast, kannst du sie gerne als Kommentar hier an den Artikel anfügen - würde mich freuen. Nutze die Möglichkeit zum Kommentar auch, wenn du Fragen hast, oder mit einer Aufgabe nicht weiterkommst.

  1. Livia: Mit dem Body Mass Index kannst du feststellen, ob du mehr Sport treiben solltest oder ob das mit dem Nachschlag beim Essen okay ist. Der Index berechnet sich aus deinem Körpergewicht (in kg) und deiner Körpergröße (in m) nach der Formel: Gewicht / (Größe*Größe). Schreibe ein Rubyprogramm, das für Gewicht und Größe je eine Variable definiert und dann den BMI ausgibt.
  2. Peter: Schreibe ein Rubyprogramm, dass in einer Schleife alle Zahlen von 1 bis 20 ausgibt. Versuche das Programm so zu schreiben, dass die Ausgabe stets in derselben Zeile erfolgt. Die Ausgabe von 2 überschreibt also die vorherige Ausgabe von 1, die Ausgabe von 3 die von 2 usw. Versuche das Programm so zu verändern, dass es nur aus einer einzigen Zeile Rubycode besteht (die Zeile für require ‘rubykids’ zählt natürlich nicht mit).
Lösungen

require 'rubykids'

# 1. Livia
gewicht = 80
groesse = 1.85
bmi = gewicht / (groesse*groesse)
print "Der BMI bei Gewicht ", gewicht, " und Groesse ", groesse, " ist ", bmi

# 2. Peter
1.biszu(20) { |zahl| print "\r", zahl; schlafe_kurz }