Programmieren mit Harald R. Haberstroh (original) (raw)

Montag, 30. September 2013

Python Objekte, Aufrufstack (POS1: 2BHIF)

Objekte

In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:

def fun(x): # auch ein Objekt! y = x * x return y

f2 = fun # f1 ist eine Refernz auf fun

lst = [1, 2, fun] # Liste mit 3 Objekten l2 = lst # l2 ist eine Refernz auf obige Liste

erg = fun(2) print(erg) erg = f2(3) print(erg) print(f2 == fun) print(l2 == lst) print(lst)

Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem f2(3) (ist ja fun(3)) in der Zeile 12 Aufgerufen wurde.

Sie können den Ablauf unter folgendem Link testen:objects.py

Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.

Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von lst zum Listenobjekt [1, 2, fun] dar. Auch l2 ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion fun. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").

Aufrufstack

Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktion fact() stapeln und dann in Folge wieder zerstört werden:

def fact(n): if n > 1: return n * fact(n - 1) else: return 1

f = fact(5) print(f)

Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem return wieder zerstört. Man nennt diesen Stapel Aufrufstack:

Sie können den Ablauf unter folgendem Link testen:fact.py

Labels: allgemeines, POS1-2, Python

Sonntag, 6. Januar 2013

Abgaben im Schuljahr 2012/13

Bei den Abgabenamen jjjj_ N_bhif_aufgabe_N_ name_vorname.tgz wird für das Schuljahr 2012/13 weiterhin jjjj durch 2012 ersetzt, auch wenn wir bereits das Jahr 2013 haben. Siehe auch Abgaben (POS1: 2BHIF, 3BHIF).

Sollten wir auch im Schuljahr 2013/14 kein brauchbares zentrales Repository haben, dann werden wir Dateinamen mit 2013 im Namen haben...

Labels: allgemeines, Aufgabe, POS1-2, POS1-3

# Eingestellt von Harald R. Haberstroh @ 15:36 0 Kommentare

Montag, 12. November 2012

Python Objekte, Aufrufstack, Klassen (POS1)

Objekte

In Python sind alle Elemente Objekte. Folgendes Beispiel enthält ein paar solche Objekte:

def fun(x): # auch ein Objekt! y = x * x return y

f2 = fun # f1 ist eine Refernz auf fun

lst = [1, 2, fun] # Liste mit 3 Objekten l2 = lst # l2 ist eine Refernz auf obige Liste

erg = fun(2) print(erg) erg = f2(3) print(erg) print(f2 == fun) print(l2 == lst) print(lst)

Folgendes Bild zeigt den Speicher, wenn das Progarmm in der Zeile 3 angelangt ist, nach dem f2(3) (ist ja fun(3)) in der Zeile 12 Aufgerufen wurde.

Sie können den Ablauf unter folgendem Link testen:objects.py

Sie sehen auf der rechten Seite die Objekte, welche Python angelegt hat. Der linke Bereich ("Frames") zeigt den Speicher, den Python für die (globalen) Variablen anlegt sowie den Speicher für die aufgerufene Funktion. Für jede Funktion wird so ein Bereich (Frame) angelegt und beim beenden wieder zerstört.

Pfeile stellen Referenzen dar. Zum Beispiel stellt der Pfeil von lst zum Listenobjekt [1, 2, fun] dar. Auch l2 ist eine Referenz zu dieser Liste.
In dieser Liste gibt es eine weitere Referenz zur Funktion fun. Funktionsnamen sind also Referenzen zu "Funktions-Objekten" (die den Code der Funktion "enthalten").

Aufrufstack

Beim folgenden Beispiel können Sie sehen, wie Frames sich bei den Aufrufen der Funktion fact() stapeln und dann in Folge wieder zerstört werden:

def fact(n): if n > 1: return n * fact(n - 1) else: return 1

f = fact(5) print(f)

Folgendes Bild zeigt die Frames, wenn das Programm die Zeile 5 erreicht (aber nicht ausgeführt) hat. Sie sehen einen Stapel von Frames. Ein Frame pro Aufruf. Diese Frames werden anschließend bei jedem return wieder zerstört. Man nennt diesen Stapel Aufrufstack:

Sie können den Ablauf unter folgendem Link testen:fact.py

Klassen

Bei Klassen handelt es sich um benutzerdefinierte Typen. D.h. es werden Typen ange- legt, für die benutzerdefinierte Methoden (also objektgebundene Funktionen) definiert werden können:

class Car: def init(self, cartype, kind, serNr): self.cartype = cartype # die Attribute type, self.kind = kind # kind und self.serNr = serNr # serNr sind in der Instanz def maxSpeed(self): if self.kind == "pickup": # Wenn Pickup, dann langsamer return 100.0 else: return 130.0

passat1 = Car("VW/Passat", "regular_car", 11142) jetta1 = Car("VW/Jetta", "small_car", 11143) ram1 = Car("Dodge/Ram", "pickup", 22242)

fleet = [passat1, jetta1, ram1] # Fuhrpark for car in fleet: print(car.cartype, car.maxSpeed(), "km/h")

Mittels der Anweisung class wird ein neuer Typ definiert. Dieser heißt in diesem Fall ‘Car’. Wir sehen, dass es sich bei der class Anweisung ebenfalls um eine Block - Anweisung handelt, da nach der Bezeichnung der Klasse (Car) der Doppelpunkt folgt und die danach folgenden Methoden eingerückt sind.
Die einzelnen Methoden werden wie Funktionen definiert. D.h. die Definition erfolgt durch das Schlüsselwort def. Als Unterschied gibt wird jedoch ein zusätzlicher Parameter an erster Stelle angeführt, der zur Ausführungszeit der Methode mit der Referenz des aktuellen Objektes vom Laufzeitsystem belegt wird.

Das folgende Bild zeigt, wie Python den Speicher für die Objekte und die Klasse angelegt hat.

Sie können das Programm hier ausführen car.py.

Die Ausgabe wäre wie folgt:

VW/Passat 130.0 km/h VW/Jetta 130.0 km/h Dodge/Ram 100.0 km/h

Durch Aufrufen der Klasse (durch Angabe des Klassennamens) und Übergabe der Initialisierungsparameter wird eine neue Instanz angelegt. Die übergebenen Parameter werden verwendet, um die spezielle Methdode __init__ nach dem Anlegen der Instanz aufzurufen. D.h. zuerst wird das neue Objekt angelegt und danach wird diese spezielle Methode aufgerufen. Dazu wird auch dieser Methode die Referenz auf das gerade angelegte Objekt mitgegeben (als Parameter self).
D.h. in der Methode __init__ werden die Attribute cartype, kind und serNr für das gerade erzeugte Objekt angelegt. D.h. ab diesem Zeitpunkt besitzt das Objekt diese Attribute. Die Methode maxSpeed kann danach ebenfalls auf diese Attribute zugreifen.

Attribute gehören also zu einem Objekt und können in den Methoden abgefragt und verändert werden. Anders als in anderen Programmiersprachen ist es jedoch so, dass der Zugriff auf diese Attribute nicht nur ausschließlich in den Methoden erfolgen kann. Diese Attribute können prinzipiell auch von außerhalb gelesen und verändert werden, wie man in obigem Beispiel in der Zeile 21 (print(...)) sehen kann.

Labels: allgemeines, POS1-2, POS1-3, Python

# Eingestellt von Harald R. Haberstroh @ 14:52 0 Kommentare

Sonntag, 4. November 2012

Testen und erweitern von text_analyzer.py (POS1: 2BHIF)

Abgabename: 2012_2bhif_aufgabe6_ Name_Vorname.tgz

Ziel dieser Aufgabe ist es, fremden Code zu testen, zu verstehen und zu erweitern. Dazu werden Sie text_analyzer.py von zwei Mitschülern testen und um unten beschriebene Funktionalität erweitern. Schreiben Sie dazu ein Modul test_text_analyzer, welches die Funktionen vom Modul text_analyzer importiert und testet.

Protokollieren Sie die Testläufe und beschreiben Sie die eventuell gefundenen Fehler in einer Textdatei errors.txt. Haben Sie Fehler entdeckt, so korrigieren Sie diese, sodass die Tests fehlerfrei laufen.

Sollten Ihre Tests Fehler enthalten, so korrigieren sie diese ebenfalls (solche Fehler werden Sie u.U. erst finden, wenn Sie das zweite Programm testen).

Ergänzen Sie die Funktionalität von text_analyzer um die Funktion read_sentences(file), welche aus der geöffneten Datei file (d.h. die Datei muss vor dem Aufruf dieser Funktion geöffnet werden) Zeilen liest und in der selben Form wie die bereits bestehende Funktion input_sentences() liefert.

Ändern/Ergänzen Sie text_analyzer um ein main, welches prüft, ob Dateinamen auf der Kommandozeile angegeben wurden, diese Dateien der Reihe nach öffnet und das (End-)Ergebnis der Funktionen analyze_words(lst) und sort_letters(dic) ausgibt. Weiters sollen auch die Häufigkeiten der Worte, absteigend sortiert nach Häufigkeit (genau wie sort_letters(dic)) ausgegeben werden (braucht man eine neue Funktion?). Dabei soll die Ausgabe formatiert sein (also nicht nur die Listen bzw. Dictionaries ausgeben).
Werden keine Dateinamen angegeben, so ist wieder von der Konsole zu lesen.
Die Option -h gibt eine kurze Hilfe aus.

Die Einteilung der Gruppen finden Sie in der Schule unter
/home/teachers/hp/public/2bhif/2012_2bhif_aufgabe6_gruppeneinteilung.pdf.

Labels: allgemeines, POS1-2, Python, Testen

# Eingestellt von Harald R. Haberstroh @ 10:38 0 Kommentare

Sonntag, 30. September 2012

Abgaben (POS1: 2BHIF, 3BHIF)

Bis es ein zentrales Repository für Abgaben gibt, gilt folgende Form der Abgabe:

  1. Erzeugen Sie ein Mercurial-Repository (hg init).
  2. Arbeiten Sie an der Lösung der Aufgabe und nehmen Sie die neuen Dateien in Ihr Repository auf (hg add).
  3. Übergeben Sie einen fertigen Arbeitsschritt an das Repository (hg commit).
  4. Sind alle Teilaufgaben gelöst bzw. der Abgabetermin erreicht, packen Sie das Repository in ein Archiv mit dem Namen**jjjj_ N_bhif_aufgabe_N_ name_vorname.tgz**
  5. Kopieren Sie dieses Archiv in das Abgabeverzeichnis/home/teachers/hp/abgabe/_N_bhif/.

Dabei bedeuten:

jjjj

Die Jahreszahl des Schuljahresbeginns. Für das Schuljahr 2012/13 also 2012.

N

Bei der Klasse, der Jahrgang (also 2bhif, 3bhif) und bei der Aufgabe die Aufgabennummer (aufgabe1, aufgabe2...).

name_vorname

Ihr Name und Vorname in Kleinbuchstaben sowie ohne Umlaute, scharfes s (ß) und Akzente.

Beispiel:

2012_3bhif_aufgabe2_mayer_juergen.tgz

Dieses Archiv sollte in das Verzeichnis

/home/teachers/hp/abgabe/_3_bhif/

kopiert werden.

Bei jeder Aufgabe steht nun zur Erinnerung ganz oben der Abgabename. Zum Beispiel:
Abgabename: 2012_3bhif_aufgabe2_ name_vorname.tgz

Erstellen Sie auch für die bereits per Mail abgegebenen Aufgaben Repositories, packen Sie diese in ein entsprechendes Archiv und geben Sie es wie oben beschrieben ab!

Labels: allgemeines, Aufgabe, POS1-2, POS1-3

# Eingestellt von Harald R. Haberstroh @ 21:21 0 Kommentare

Montag, 24. September 2012

Mini-Vergleich verschiedener Programmiersprachen

Dieser Artikel vergleicht ein paar Programmiersprachen (die in der Abteilung Informatik der HTL Wiener Neustadt unterrichtet werden) und dient nur zur Demonstration der "Optik" dieser Sprachen.

Als Beispiel kommt "99 bottles of beer" zum Einsatz. Die Programme stammen von http://99-bottles-of-beer.net/ und dienen eigentlich nur als Beispiele, um die Code-Struktur kleinerer Programme zu sehen.

Python

Python unterstützt mehrere Programmierparadigmen. So werden objektorientierte, aspektorientierte und funktionale Programmierung unterstützt. Wie andere dynamische Sprachen wird Python oft als Skriptsprache genutzt.

""" 99 bottles of beer in Python """ for quant in range(99, 0, -1): if quant > 1: print(quant, "bottles of beer on the wall,", quant, "bottles of beer.") if quant > 2: suffix = str(quant - 1) + " bottles of beer on the wall." else: suffix = "1 bottle of beer on the wall." elif quant == 1: print("1 bottle of beer on the wall, 1 bottle of beer.") suffix = "no more beer on the wall!" print("Take one down, pass it around,", suffix) print("--")

Hier die Python Lösung zum Ausführen

Java

Java ist eine objektorientierte Programmiersprache und eine eingetragene Marke des Unternehmens Sun Microsystems (seit 2010 Oracle). Die Programmiersprache ist ein Bestandteil der Java-Technologie – diese besteht grundsätzlich aus dem Java-Entwicklungswerkzeug (JDK) zum Erstellen von Java-Programmen und der Java-Laufzeitumgebung (JRE) zu deren Ausführung. Die Laufzeitumgebung besteht selbst aus der virtuellen Maschine (JVM) sowie den mitgelieferten Bibliotheken der Java-Laufzeitumgebung.

/*

C

C ist eine imperative Programmiersprache, die der Informatiker Dennis Ritchie in den frühen 1970er Jahren an den Bell Laboratories für die Systemprogrammierung des Betriebssystems Unix entwickelte. Seitdem ist sie auf vielen Computersystemen verbreitet. Die Anwendungsbereiche von C sind sehr verschieden. Sie wird zur System- und Anwendungsprogrammierung eingesetzt. Die grundlegenden Programme aller Unix-Systeme und die Systemkerne vieler Betriebssysteme sind in C programmiert. Zahlreiche Sprachen, wie C++, Objective-C, C#, Java, PHP, Vala oder Perl orientieren sich an der Syntax und anderen Eigenschaften von C.

/*

#define MAXBEER (99)

void chug(int beers);

main() { register beers;

for(beers = MAXBEER; beers; chug(beers--))
    puts("");

puts("\nTime to buy more beer!\n");

exit(0);

}

void chug(register beers) { char howmany[8], *s;

s = beers != 1 ? "s" : "";
printf("%d bottle%s of beer on the wall,\n", beers, s);
printf("%d bottle%s of beeeeer . . . ,\n", beers, s);
printf("Take one down, pass it around,\n");

if(--beers) sprintf(howmany, "%d", beers); else strcpy(howmany, "No more");
s = beers != 1 ? "s" : "";
printf("%s bottle%s of beer on the wall.\n", howmany, s);

}

C++

C++ ist eine von der ISO genormte Programmiersprache. Sie wurde ab 1979 von Bjarne Stroustrup bei AT&T als Erweiterung der Programmiersprache C entwickelt. C++ ermöglicht sowohl die effiziente und maschinennahe Programmierung als auch eine Programmierung auf hohem Abstraktionsniveau.

C++ unterstützt mehrere Programmierparadigmen:

/*

#include using namespace std;

int main() { int bottles = 99; while ( bottles > 0 ) { cout << bottles << " bottle(s) of beer on the wall," << endl; cout << bottles << " bottle(s) of beer." << endl; cout << "Take one down, pass it around," << endl; cout << --bottles << " bottle(s) of beer on the wall." << endl; } return 0; }

C#

C# (lies englisch c sharp, englische Aussprache [ˌsiːˈʃɑːp]) ist eine vom Softwarehersteller Microsoft im Rahmen seiner .NET-Strategie entwickelte Programmiersprache. C# ist bei ECMA und ISO als Standard registriert.

C# unterstützt mehrere Programmierparadigmen:

/*

namespace NinetyNineBottles { class Beer { static void Main(string[] args) { StringBuilder beerLyric = new StringBuilder(); string nl = System.Environment.NewLine;

    var beers =
        (from n in Enumerable.Range(0, 100)
         select new { 
           Say =  n == 0 ? "No more bottles" : 
                 (n == 1 ? "1 bottle" : n.ToString() + " bottles"),
           Next = n == 1 ? "no more bottles" : 
                 (n == 0 ? "99 bottles" : 
                 (n == 2 ? "1 bottle" : n.ToString() + " bottles")),
           Action = n == 0 ? "Go to the store and buy some more" : 
                             "Take one down and pass it around"
         }).Reverse();

    foreach (var beer in beers)
    {
        beerLyric.AppendFormat("{0} of beer on the wall, {1} of beer.{2}",
                                beer.Say, beer.Say.ToLower(), nl);
        beerLyric.AppendFormat("{0}, {1} of beer on the wall.{2}", 
                                beer.Action, beer.Next, nl);
        beerLyric.AppendLine();
    }
    Console.WriteLine(beerLyric.ToString());
    Console.ReadLine();
}

} }

Labels: allgemeines, C, C#, C++, Java

# Eingestellt von Harald R. Haberstroh @ 14:33 0 Kommentare

Dienstag, 18. September 2012

Mercurial Einführung

Mercurial ist ein Version Control System (abk. VCS, dt. Versionsverwaltungssystem). Software-Entwickler verwenden es um ihren Source Code zu verwalten. Zweck von Mercurial ist:

  1. Verwalten (und Speichern) aller alten Versionen von jeder Datei
  2. Verschiedene Versionen des Source Codes zusammenführen, sodass Team-Mitglieder unabhängig voneinander am Code arbeiten können um dann ihre Änderungen wieder zusammenzuführen.

Ohne Versionsverwaltung müsste man die verschiedenen Versionen in Verzeichnissen mit unterschiedlichen Namen speichern:

hh@knuth:~/Dokumente/mercurial-demo$ ls -l insgesamt 20 drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy (2) of CountDown drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy (3) of CountDown drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 Copy of CountDown drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 CountDown drwxrwxr-x 2 hh hh 4096 Sep 18 17:44 CountDown 2012-09-18

Das ist mühsam und verwirrend und benötigt eine Menge Speicherplatz (das Projekt ist dann praktisch vollständig in jeder Kopie des Projektverzeichnisses). Mit einem VCS kann man das viel besser machen.

Die meisten arbeiten mit Mercurial auf der Kommandozeile. Das funktioniert völlig identisch unter Linux, Windows und Mac. Das Kommando ist hg:

hh@knuth:~/Dokumente/mercurial-demo$ hg Mercurial Distributed SCM

Grundlegende Befehle:

add Fügt die angegebenen Dateien der nächsten Version hinzu annotate Zeigt Informationen über Änderungssätze pro Dateizeile an clone Erzeugt eine Kopie eines bestehenden Projektarchivs commit Übernimmt Änderungen der angegebenen Dateien oder alle ausstehenden Änderungen ins Archiv diff Zeigt Änderungen des Projektarchivs oder angegebener Dateien an export Gibt Kopfzeilen und Änderungsverlauf einer oder mehrerer Versionen aus forget Angegebene Dateien ab dem nächsten Commit nicht mehr unter Versionskontrolle stellen init Erzeugt ein neues Projektarchiv im angegebenen Verzeichnis log Zeigt die Revisionshistorie des Archivs oder von Dateien an merge Führt das Arbeitsverzeichnis mit einer anderen Revision zusammen pull Holt Änderungen aus dem angegebenen Projektarchiv push Überträgt lokale Änderungen in das angegebene Ziel remove Entfernt die angegebenen Dateien in der nächsten Version serve Startet einen eigenständigen Webserver status Zeigt geänderte Dateien im Arbeitsverzeichnis summary Fasst den Status des Arbeitsverzeichnisses zusammen update Aktualisiert das Arbeitsverzeichnis (oder wechselt die Version)

Nutze "hg help" für eine Liste aller Befehle oder "hg -v" für Details

Vielfach ist das Betriebssystem auf englisch eingestellt:

hh@knuth:~/Dokumente/mercurial-demo$ hg Mercurial Distributed SCM

basic commands:

add add the specified files on the next commit annotate show changeset information by line for each file clone make a copy of an existing repository commit commit the specified files or all outstanding changes diff diff repository (or selected files) export dump the header and diffs for one or more changesets forget forget the specified files on the next commit init create a new repository in the given directory log show revision history of entire repository or files merge merge working directory with another revision pull pull changes from the specified source push push changes to the specified destination remove remove the specified files on the next commit serve export the repository via HTTP status show changed files in the working directory summary summarize working directory state update update working directory

use "hg help" for the full list of commands or "hg -v" for details

Im weiteren werden Sie nur mehr die englischen Ausgaben sehen!

Um Mercurial verwenden zu können, muss noch eine Konfigurationsdatei .hgrc im Homeverzeichnis angelegt werden:

hh@knuth:~ $ cat > .hgrc [ui] username = Name user@email.com hh@knuth:~ $

Name und E-Mail muss natürlich sinnvoll sein (z.B. Manfred Bauer mbauer10922@gmail.com). Die Datei kann natürlich mit jedem Texteditor angelegt werden.

Um eine Versonsverwaltung zu verwenden, benötigt man ein Repository (dt Lager, Magazin). Das Repository speichert alle alten Versionen aller Dateien eines Verzeichnisses. Natürlich wird ein platzsparendes Verfahren verwendet. Es werden die Dateien plus aller Änderungen gespeichert.

Früher war das Anlegen eines Repositories ziemlich mühsam. Mit Mercurial geht das ganz einfach: einfach ins Hauptverzeichnis des Projekts (des Dateibaums) wechseln und hg init eingeben.

hh@knuth:/Dokumente/mercurial-demo$ cd c2bf hh@knuth:/Dokumente/mercurial-demo/c2bf$ ls -a . .. .project 1tox GPL Makefile README cc ld math strip test.sh wrapper hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg init hh@knuth:/Dokumente/mercurial-demo/c2bf$

Was ist nun passiert? Ein Verzeichnis .hg wurde angelegt:

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ ls -a . .. .hg .project 1tox GPL Makefile README cc ld math strip test.sh wrapper

.hg ist das Repository. Ein Verzeichnis mit allem Drum und Dran für Mercurial. Einstellungen, alte Versionen von Dateien, Tags (dt Etiketten, Marken), ein paar extra Socken, wenn es kalt wird usw. In dem Verzeichnis hat man nichts verloren, man sollte da nicht händisch herumdrehen, da könnte was kaputt gehen.

Das Repository ist noch leer. Die Dateien müssen noch hinzugefügt werden.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg add adding .project adding 1tox/BF1to2.txt adding 1tox/BF1to4.txt adding 1tox/Makefile adding 1tox/MultiBitwidth.txt adding 1tox/c2bf-1to16bit adding 1tox/c2bf-1to2 adding 1tox/c2bf-1to2.c adding 1tox/c2bf-1to2.o adding 1tox/c2bf-1to32bit adding 1tox/c2bf-1to4 adding 1tox/c2bf-1to4.c adding 1tox/c2bf-1to4.o adding GPL adding Makefile adding README adding cc/Makefile adding cc/README.txt

uswusf...viele Dateien...

hh@knuth:~/Dokumente/mercurial-demo/c2bf$

Ein Schritt fehlt noch... die Änderungen müssen committed (commit - übergeben) werden. Welche Änderungen?

Das Hinzufügen der neuen Dateien.

Commit sagt Mecurial, dass der aktuelle Dateibestand als neue Version übernommen werden soll. Solange kein commit erfolgt, wird im Repository nichts geändert.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg commit

Mercurial öffnet nun einen Editor (bei mir vim), sodass eine Nachricht eingegeben werden kann. Diese Nachricht ist eine Erinnerung für den Programmierer, die beschreiben soll, was sich geändert hat.

Initial version of the c2bf code.

HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: hh HG: branch 'default' HG: added .project HG: added 1tox/BF1to2.txt HG: added 1tox/BF1to4.txt HG: added 1tox/Makefile HG: added 1tox/MultiBitwidth.txt HG: added 1tox/c2bf-1to16bit HG: added 1tox/c2bf-1to2 HG: added 1tox/c2bf-1to2.c HG: added 1tox/c2bf-1to2.o HG: added 1tox/c2bf-1to32bit HG: added 1tox/c2bf-1to4 HG: added 1tox/c2bf-1to4.c HG: added 1tox/c2bf-1to4.o HG: added GPL HG: added Makefile HG: added README HG: added cc/Makefile HG: added cc/README.txt HG: added cc/ast.h HG: added cc/c2bf-cc HG: added cc/c2bf-dispast "/tmp/hg-editor-eMVxZ3.txt" 204L, 6635C

Im vim muss man zuerst I (großes i) dann gleich den Text eingeben. Mit (Esc-Taste) und :x (Eingabetaste) speichern.

Mit hg log bekommt man eine Liste der Änderungen.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg log changeset: 0:3d54225035a3 tag: tip user: hh date: Tue Sep 18 21:00:02 2012 +0200 summary: Initial version of the c2bf code.

Jetzt ändern wir eine Datei:

So, nun Übergeben wir die Änderung an Mercurial: hg commit

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg commit

Mercurial erkennt die Änderung und bietet wieder den Editor für die Commit-Nachricht an:

Added comment.

HG: Enter commit message. Lines beginning with 'HG:' are removed. HG: Leave message empty to abort commit. HG: -- HG: user: hh HG: branch 'default' HG: changed test.sh ~
~
~
~
~

hg log zeigt nun folgendes an:

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg log changeset: 1:ad33e88c004f tag: tip user: hh date: Tue Sep 18 21:24:58 2012 +0200 summary: Added comment.

changeset: 0:3d54225035a3 user: hh date: Tue Sep 18 21:00:02 2012 +0200 summary: Initial version of the c2bf code.

hg log funktioniert wie ein Blog: das Neuseste wird zuoberst angezeigt.

Werden versehentlich Dateien gelöscht oder nicht funktionierende Änderungen im Sourcecode gemacht, kann man mit hg revert --all die Änderungen bis zum letzten Commit zurücknehmen.

--all nimmt alle Änderungen aller Dateien zurück.

Statt --all kann eine Liste von Dateien angegeben werden, für die man die Änderungen zurücknehmen will.

Wenn Sie mit Mercurial an einem Projekt arbeiten, dann sollten Sie folgendermaßen vorgehen:

  1. Mache ein paar Änderungen
  2. Schau, ob sie funktionieren
  3. Funktionieren sie, dann hg commit
  4. Andernfalls hg revert --all
  5. GOTO 1

Will man wissen, welche Dateien sich geändert haben, kann man hg status verwenden:

hh@knuth:/Dokumente/mercurial-demo/c2bf$ ls 1tox GPL Makefile README cc ld math strip test.sh wrapper hh@knuth:/Dokumente/mercurial-demo/c2bf$ vim test.sh hh@knuth:/Dokumente/mercurial-demo/c2bf$ cp test.sh testall.sh hh@knuth:/Dokumente/mercurial-demo/c2bf$ rm GPL hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg status M test.sh ! GPL ? testall.sh

M bedeutet modified, also geändert. ! bedeutet fehlend, die Datei war beim letzten Commit noch da, ist aber nun verschwunden. ? bedeutet unbekannt, Mercurial weiß von dieser Datei (noch) nichts.

Will man nun wissen, was sich in einer Datei geändert hat, kann man hg diff verwenden:

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg diff test.sh diff -r ad33e88c004f test.sh --- a/test.sh Tue Sep 18 21:24:58 2012 +0200 +++ b/test.sh Tue Sep 18 21:54:11 2012 +0200 @@ -1,5 +1,6 @@ #!/bin/bash

run tests with c2bf

+# BFI=egobfi16

Test 1

Das ist etwas kryptisch, aber oft verwendet man eine IDE, welche die Änderungen schön anzeigt. mit gvim und ein paar Shell-Tricks bekommt man das auch hin.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ *hg cat test.sh | * gvim - -c ":vert diffsplit test.sh" -c 'map q :qa!'

Damit die Änderungen von oben committed werden können, müssen noch das ! und ? behandelt werden. Dass die Datei GPL gelöscht wurde, muss mit hg remove gekanntgegeben werden und die neue Datei testall.sh muss mit hg add Mercurial bekannt gemacht werden:

hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg status M test.sh ! GPL ? testall.sh hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg remove GPL hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg st M test.sh R GPL ? testall.sh hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg add adding testall.sh hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg st M test.sh A testall.sh R GPL

A bedeutet nun added (hinzugefügt) und R removed (gelöscht).

Die Änderungen werden aber erst mit hg commit ins Repository übernommen!

Übrigens kann man die hg-Kommandos abkürzen, wie man beim letzten Beispiel sieht. Man benötigt nur so viele Zeichen bis das Kommando eindeutig ist.

Nach dem Commit, sieht das Log so aus:

hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg com hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg log changeset: 2:a8ff7f27bcaf tag: tip user: hh harald@haberstroh.at date: Tue Sep 18 22:24:30 2012 +0200 summary: some major changes.

changeset: 1:ad33e88c004f user: hh harald@haberstroh.at date: Tue Sep 18 21:24:58 2012 +0200 summary: Added comment.

changeset: 0:3d54225035a3 user: hh harald@haberstroh.at date: Tue Sep 18 21:00:02 2012 +0200 summary: Initial version of the c2bf code.

hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg status hh@knuth:/Dokumente/mercurial-demo/c2bf$ /harald@haberstroh.at/harald@haberstroh.at/harald@haberstroh.at

Beim Log zeigt changeset die Versionsnummern an. Die Versionsnummern bestehen aus zwei Teilen, einer "lesbaren" Zahl wir 0 (initiale Version) oder 1 sowie nach dem : eine komische Hexadezimalzahl, welche meist "ignoriert" werden kann.

Wie man sieht, zeigt nun hg status nichts mehr an, alle Änderungen wurden übernommen.

Mit hg cat kann man sich jede beliebige Version einer Datei aus dem Repository anzeigen lassen. Mit der Option -r [zahl] (-r wie revision) kann man sich die Version mit der Nummer [zahl] anzeigen lassen.

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg cat test.sh #!/bin/bash

run tests with c2bf

BFI=egobfi16

Test 1

uswusf...viele Zeilen...

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg cat -r 0 test.sh #!/bin/bash BFI=egobfi16

Test 1

uswusf...viele Zeilen...

Übrigens kann die Option -r [zahl] auch bei hg diff verwendet werden:

hh@knuth:~/Dokumente/mercurial-demo/c2bf$ hg diff -r 0 test.sh diff -r 3d54225035a3 test.sh --- a/test.sh Tue Sep 18 21:00:02 2012 +0200 +++ b/test.sh Tue Sep 18 22:41:20 2012 +0200 @@ -1,4 +1,6 @@ #!/bin/bash +# run tests with c2bf +# BFI=egobfi16

Test 1

Mit hg update kann man den Inhalt des aktuellen Verzeichnisses auf jede beliebige Version setzen. hg update -r 279999 liefert leider keine super coole SciFi Version mit Laserschwertern unseres Projekts. Jede Version in der Vergangenheit ist aber möglich. Ohne Versionsnummer wird die aktuelle Version (tip) verwendet.

hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg update -r 0 2 files updated, 0 files merged, 1 files removed, 0 files unresolved hh@knuth:/Dokumente/mercurial-demo/c2bf$ head -6 test.sh #!/bin/bash BFI=egobfi16

Test 1

echo -n "Test 1: " ./wrapper/c2bf cc/tests/test1.c hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg up -r 1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved hh@knuth:/Dokumente/mercurial-demo/c2bf$ head -6 test.sh #!/bin/bash

run tests with c2bf

BFI=egobfi16

Test 1

echo -n "Test 1: " hh@knuth:/Dokumente/mercurial-demo/c2bf$ hg up 2 files updated, 0 files merged, 1 files removed, 0 files unresolved hh@knuth:/Dokumente/mercurial-demo/c2bf$ head -6 test.sh #!/bin/bash

run tests with c2bf

BFI=egobfi16

Test 1

hh@knuth:~/Dokumente/mercurial-demo/c2bf$

Übrigens zeigt das Kommando head die mit -[zahl] angegeben Anzahl von Zeilen an (in unserem Beispiel immer 6). Das Kommando hat wie auch vim nichts mit Mercurial zu tun.

In einem weiteren Artikel werde ich zeigen, wie man zusätzlich ein zentrales Repository für ein Team (oder für Abgaben :-)) verwenden kann.

In Zukunft sollten Sie folgendermaßen an Ihren Aufgaben arbeiten:

  1. Bearbeite einen Punkt der Aufgabe (Mache ein paar Änderungen)
  2. Schau, ob sie funktionieren
  3. Funktionieren sie, dann hg commit
  4. Andernfalls hg revert --all
  5. GOTO 1

Abgegeben wird dann das Repository, also das Verzeichnis .hg, in einer komprimierten Datei:
tar -czf [jjjj_ N_bhif_aufgabe_N_ _name_vorname_].tgz .hg.

jjjj

Die Jahreszahl des Schuljahresbeginns. Für das Schuljahr 2012/13 also 2012.

N

Bei der Klasse, der Jahrgang (also 2bhif, 3bhif) und bei der Aufgabe die Aufgabennummer (aufgabe1, aufgabe2...).

name_vorname

Ihr Name und Vorname in Kleinbuchstaben sowie ohne Umlaute, scharfes s (ß) und Akzente.

Beispiel:

tar -czf 2012_3bhif_aufgabe2_mayer_juergen.tgz .hg

Wir evaluieren gerade ein paar Möglichkeiten für ein zentrales Repository für die Abgabe. Dann braucht man keine Mails mehr schicken. Details folgen...

Weitere Informationen

Labels: allgemeines, hg, mercurial

# Eingestellt von Harald R. Haberstroh @ 23:29 0 Kommentare

Freitag, 31. August 2012

Coding Conventions, Programmierrichtlinien

Diese Programmierrichtlinien sind für den Programmierunterricht an der HTL Wiener Neustadt, Abteilung Informatik gedacht, sind aber auch für andere ganz praktisch (nach diversen Anpassungen).

Sammlung von Programmierrichtlinen, die für alle Programmiersprachen gelten.

- Verwenden Sie sprechende Namen (für Funktionen, Variable, Methoden usw.)
- Jede Variablendeklaration muss in einer eigenen Zeile stehen.
- Keine Umlaute in Namen (auch wenn sei von der Programmiersprache erlaubt werden).
- Keine Tabulatoren verwenden. Der Editor (vim, eclipse usw.) muss so eingestellt werden, sodass nur Leerzeichen eingefügt werden.
- Einrückungen dürfen nur mit Leerzeichen erfolgen. Eine Ebene muss mindestens zwei Leerzeichen eingerückt werden. Mehr als vier Leerzeichen sind nicht sinnvoll.
- Die Länge von Zeilen soll nicht größer als 79 Zeichen sein. Zeilen, die deshalb umgebrochen werden müssen, sind nach dem Zeilenumruch (eventuell mit Zeilenfortsetzungszeichen zu markieren) zusätzlich einzurücken.
- Dateinamen, Verzeichnisnamen dürfen keine Umlaute, Sonderzeichen und Leerzeichen enthalten.
- Jede Programmdatei muss einen Kommentarkopf mit folgenden Inhalten haben:

Ihrem Namen
Ihrer Klasse
Ihrer Katalognummer
Ihrer Evidenznummer (und/oder E-Mail-Adresse)
dem Dateinamen
Kurzbeschreibung des Programms oder der Klasse (Zweck)

- Funktionen, Subroutinen, Methoden müssen mindestens durch eine Leerzeile getrennt werden.
- Klassennamen müssen mit einem Großbuchstaben beginnen. Klassennamen sind normalerweise Substantive in der Einzahl.
- Methodennamen müssen mit einem Kleinbuchstaben beginnen. Methoden beschreiben eine Tätigkeit!
- Konstante definieren. Es dürfen keine Zahlen unmotiviert im Code verwendet werden.
- Links und rechts je binären Operator genau ein Leerzeichen.
- Nach einem unären Operator kein Leerzeichen, jedoch davor schon.
- Keine Leerzeichen unmittelbar innerhalb von runden, eckigen oder geschweiften Klammern.
- Keine Leerzeichen vor runder Klammer von Funktionen.
- Keine Leerzeichen vor Komma, Strichpunkt, Punkt oder Doppelpunkt. Ein Leerzeichen nach Komma, Strichpunkt und Doppelpunkt, aber kein Leerzeichen nach einem Punkt.
- Fixe Dateipfade müssen als Konstante definiert werden. Noch besser wäre die Verwendung von Konfigurationsdateien.
- Bei Vergleichen sollte die Konstante immer links stehen, damit nicht versehentlich eine Zuweisung entsteht.
- Globale Variable sollten vermieden werden.
- Alle Methoden (Funktionen), die nur lokal in einer Klasse oder einem Modul verwendet werden, müssen privat sein (je nach Programmiersprache z.B. private oder static).
- Der Zweck von Parametern/Variablen/Methoden muss durch den Namen erkennbar sein. Alternativ kann auch (zusätzlicher) Kommentar verwendet werden.
- Sichern Sie den Code mit assertions (Zusicherungen assert()) ab.
- Verwenden Sie englische Kommentare und Bezeichner (wenn möglich, die folgenden Beispiele wurden noch ohne diese Regel verfasst).

Python

Grundsätzlich gelten obige Richtlinien. Es folgt ein Beispielprogrammkopf zur Demonstration:

#!/usr/bin/python

-"- coding: UTF8 -*-

hauf.py

Worthäufigkeiten ermitteln, indem ein Dictionary mit Worten erzeugt wird.

Danach wird das Dictionary in eine Liste umgewandelt (mit Elementen der

Art [häufigkeit,wort]), um ein Sortieren nach Häufigkeit zu ermöglichen.

Eingelesen wird alles und mittels Regulärem Ausdruck in eine Wortliste

zerlegt.

2006-10-12, Maier Lukas, 2BD, 20, d09999

Der Header enthält den Dateinamen hauf.py, den Namen Maier Lukas, die Klasse 2BD, die Katalognummer 20 und die Evidenznummer d09999. Darüberhinaus wird der Zweck des Programms kurz umrissen.
Jede Methode bzw. Funktion soll einen DocString enthalten (zwischen "), in dem der Zweck der Methode und die Parameter beschrieben werden:

def einlesen(fp): """ Einlesen der Wörter aus der Datei fp, liefert eine Liste von Worten """ text = fp.read() # lies alles ein

... Rest fehlt

Siehe auch PEP 8 -- Style Guide for Python Code oder PEP 8 - Übersetzung

Java

- Paketnamen sind klein zu schreiben
- Klassennamen beginnen mit einem Großbuchstaben und werden in KamelSchreibWeise geschrieben
- Methoden beginnen mit einem Kleinbuchstaben und werden in kamelSchreibweise geschrieben
- Verwenden Sie Javadoc-Strings in Ihren Komentaren.
- Jede Datei Soll wieder einen Header haben, z.B.:

/**

Hier ist zusätzlich der Paketname im Kommentar angegeben (bo).
- Jede Klasse muss ebenfalls einen Header haben, der den Zweck beschreibt, z.B.:

/**

- Ist nur eine Klasse in einer Datei, so können die beiden Header zusammengefasst werden.
- Methoden sollten mindestens @param und @return Docstrings enthalten:

/**

Am besten machen Sie sich schon passende Vorlagen in eclipse (Menü Window->Preferences):

eclipse-templates.png

Siehe auch Code Conventions for the Java Programming Language

C#

Hier gilt im Wesentlichen das selbe wie für Java, nur dass die Docstrings ein anderes Format haben (XML), ein Beispiel:

///

/// Diese Funktion gibt den größeren Betrag zurück /// /// Der erste Übergabeparameter /// Der zweite Übergabeparameter /// Die Zahl mit dem größeren Betrag /// Diese Funktion gibt den größeren Betrag der beiden Übergegeben /// zurück. /// Sind die Beträge gleich groß ist dies ein Fehler /// Der Betrag der beiden Zahlen ist gleich /// groß public int GetGreaterAbs(int a, int b) { return Math.Max(Math.Abs(a), Math.Abs(b)); }

Siehe auch C# Coding Conventions (C# Programming Guide)

C, C++

Beide Sprachen sind wie Java zu dokumentieren. Hier gibt es externe Programme zur Auswertung der DocStrings.

andere Sprachen

Die Regeln müssen entsprechend adaptiert werden. Etliche Sprachen haben ein ähnliches Format für DocStrings wie Java. Bitte verwenden Sie diese Tags.

Labels: allgemeines, coding conventions, programmierrichtlinien

# Eingestellt von Harald R. Haberstroh @ 19:56 0 Kommentare

Mittwoch, 5. Oktober 2011

Abgaben am CVS (POS1: 2., 3. Klassen)

Nennen Sie Projekte _klasse_-_name_-projekt, wobei klasse "2a" für 2AHIF, "2c" für 2CHIF, "3b" für 3BHIF usw. und name Ihr Familienname sein soll (bei Namensgleichheit machen Sie bitte _klasse_-_name-vorname_-projekt daraus). Checken Sie die Projekte am CVS (cvs.htlwrn.ac.at, Pfad /cvs/user - user ist Ihr Login) ein.

Den Source Code müssen Sie auch in gedruckter Form abliefern. Dieses Listing sollte dann etwa so aussehen:

Das Listing sollte folgende Eigenschaften aufweisen:

Beispiel mit Zeilennummern:

Beispiel mit Zeilennummern, nur jede 5. Zeile bekommt eine Nummer:

Unter Linux können Sie den Befehl a2ps (ASCII to PostScript, 2 = two = to, daher a2ps) verwenden.

Beispiele:

Die Datei dreieck.py wird auf dem Drucker hpg1 ohne Zeilennummern gedruckt.

a2ps --line-numbers=1 -Phpg2 dreieck.py newprog.py

Die Dateien dreieck.py und newprog.py werden am Drucker hpg2 mit Zeilennummern gedruckt.

a2ps --line-numbers=5 -Phpg3 dreieck.py newprog.py

Die Dateien dreieck.py und newprog.py werden am Drucker hpg3 mit Zeilennummern gedruckt, wobei nur jede fünfte Zeilennummer gedruckt wird.

Weitere Optionen zu a2ps finden Sie in der man-Page (man a2ps).

Die meisten IDEs (z.B. eclipse oder netbeans) und viele Editoren bieten ähnliche Möglichkeiten, jedoch passt bei a2ps der Ausdruck praktisch immer, abgesehen davon, dass a2ps nur ASCII-versteht und damit Probleme mit Umlauten hat. Sind Umlaute im Source Code (nur in Kommentaren erlaubt), so kann man mit dem Tool iconv das Encoding für a2ps anpassen. Obiges Beispiel würde dann so aussehen:

iconv -f utf8 -t latin1 dreieck.py -o - | a2ps --stdin=dreieck.py --line-numbers=5 -Phpg3

a2ps benötigt noch einen Titel für stdin (Option --stdin=title), weil die Standardausgabe von iconv von a2ps gelesen wird.

Labels: allgemeines, Aufgabe, POS1-2, POS1-3

# Eingestellt von Harald R. Haberstroh @ 11:15 0 Kommentare

Samstag, 1. Oktober 2011

Überlauf mit C-Datentypen in Python

Wenn man z.B. ganze Zahlen mit nur einem Byte (8bit) darstellen will, so hat man den Bereich -128 (-28 - 1) bis +127 (28 - 1 - 1) zur Verfügung, weil üblicherweise die negativen Zahlen im Zweierkomplement dargestellt werden. Hat eine ein Byte große Variable var den Wert 127, so entspricht das binär 011111112. Zählt man 1 dazu, so erhält man binär 100000002. Dieser Wert entspricht aber der Zahl -12810.
-110 entspricht der binären Zahl 111111112 im Zweierkomplement (ansonsten wäre es 28 - 1 also 255). Zählt man zu 111111112 1 dazu, erhält man 1000000002. Da der Einser ganz vorne die 9. Stelle wäre, die in 8bit nicht mehr dargestellt werden kann, so fliegt sie raus und wir bekommen 000000002, also 0.
Das folgende Bespiel zeigt die Verwendung eines C-Datentypen für ein Byte, wo tatsächlich immer nur 8bit verwendet werden. Allerdings kann man nicht unmittelbar mit den Werten rechnen, da diese Werte sonst einfach in den entsprechenden Python-Typ int umgewandelt werden würde und es nicht zu einem Überlauf käme.

import ctypes # see help(ctypes)

def inc(var): """increment var by one""" return type(var)(var.value + 1)

def dec(var): """decrement var by one""" return type(var)(var.value - 1)

if name == 'main': var = ctypes.c_byte(126) # var = 126 - one byte var = inc(var) # var = 127 print(var.value) var = inc(var) # var = -128 (10000000 binary) print(var.value)

var = ctypes.c_byte(-1)  # var = -1 - one byte (11111111 binary)
var = inc(var)           # var = 0
print(var.value)

Im folgenden Video wird das auch ganz schön erklärt:

Labels: allgemeines, Informatik, POS1-2, Python

# Eingestellt von Harald R. Haberstroh @ 16:30 0 Kommentare

Dienstag, 20. September 2011

Commandline resurrected

Am Anfang war die Kommandozeile
Das stimmt natürlich nicht ganz, denn davor gab es Programme durch Verdraten der Computer-Hardware, dann "Schreibmaschinen", mit denen man Lochkarten/Lochstreifen stanzen konnte, welche dann über ein Lesegerät in den Computer gelangten.

Die Ausgabe erfolgte über Endlos-Drucker.

Zur Datenspeicherung gab es Wieder Lochkarten oder Magnetbänder:

Natürlich gab es noch verschiedenste Ein- und Ausgabegeräte, aber das Wesentliche an der Arbeit mit Computern war damals, dass es nur "Stapelverarbeitung" (Batch Processing) gab (bis Anfang der 70er-Jahre, in Schulen etwas länger - bis Anfang der 80er). Der große Fortschritt waren dann Fernschreiber/Teletypes, mit denen man interaktiv am Computer arbeiten konnte. Das waren quasi Schreibmaschinen mit eingebautem Drucker. Aus dieser Zeit stammt die Kommandozeile. Der Computer druckte einen "Prompt" aus und wartete dann auf eine Eingabezeile, die er dann verarbeitete und das Ergebnis oder die Fehlermeldungen ausdruckte.

Natürlich wartete der Computer die meiste Zeit auf Eingaben. Daher wurde aus dem Batch Processing ein Multi Processing, d.h. mehrere Terminals wurden an den Computer angeschlossen und mehrere Programme konnten (scheinbar) gleichzeitig laufen.
Aus den Teletypes entwickelten sich echte Terminals (Bildschirm und Tastatur).

Man arbeitete immer mit einer Read-eval-print loop (REPL). Der Computer las einen Befehl ein, führte ihn aus, gab das Ergebnis aus und wartete auf die nächste Eingabe (wieder zurück zum Lesen).
Um effizient zu arbeiten, musste man ziemlich viele Kommandos auswendig wissen (übrigens funktionierten damals Texteditoren auch mit einer Kommandozeile, z.B. edlin unter DOS oder ed unter Unix). Die Kommandos bestanden oft nur aus wenigen Buchstaben. Jedenfalls nichts für Anfänger oder Personen, die nur ab und zu einen Computer bedienen wollten.
Durch Menü-Bedienung wurde es langsam aber sicher auch für "Laien" möglich Computer zu bedienen. Viele elektronische Geräten können über Menüs bedient werden. Die Menüführung war der Tod der Kommandozeile.
Auch in grafischen Benutzeroberflächen (GUI) gibt es jede Menge Menüs oder andere Dialoge, bei denen man etwas auswählen kann und nicht Befehle auswendig wissen muss. Durch Shortcuts (Tastenkombinationen) kann man als geübter Benutzer trotzdem relativ flink arbeiten. Manche User verwenden aber immer noch gerne Commandline Interfaces, weil sie damit schneller arbeiten können. Dazu gibt es auf praktisch allen Systemen Terminal-Emulatoren.

Im Prinzip werden moderne Systeme immer noch großteils mit Menüs bedient, aber je mehr Funktionen, desto mehr Einträge gibt es. Es wird also selbst für geübte Benutzer teilweise ziemlich mühsam, zumal man oft zur Maus greifen muss.

Optionen (Einstellungen) sind oft ziemlich umfangreich, viele Tabs, Radio-Knöpfe usw.

eclipse hat so viele Einstellungsmöglichkeiten, dass im Optionendialog schon lange eine Suchfunktion integriert ist:

Auch das Windows-Menü oder KDE-Menü hat seit einigen Jahren eine integrierte Suchfunktion, sodass man z.B. [Alt]+[F1]ecl[Enter] (KDE) drücken muss, um Eclipse zu starten. Unter Windows muss man die Windows-Taste drücken und z.B. "not" eingeben um Notepad aufzurufen. Ist der Befehl noch nicht eindeutig, so werden mögliche Alternativen angezeigt.

Übrigens gibt es so eine Art Mini-Kommandozeile ([Alt]+[F2]) schon seit es KDE gibt (1996), also lange bevor so etwas unter Windows existierte.
Bei Mobiltelefonen hat sich auch die Menüführung schon lange durchgesetzt. Selbst bei Smartphones ist es noch so, wenn man die vielen Anwendungs-Icons als Menü betrachtet:

Man muss oft einige Zeit "herumswipen", um die richtige App zu finden. Ich weiß nicht, ob es das beim iPhone gibt, aber bei Andorid kann man einfach den Such-Button drücken und dann ein paar Buchstaben tippen und man bekommt die passenden Anwendungen nebst Kontakten angezeigt.

Das geht oft viel schneller als "Swipen".
Im übrigen verwenden die meisten im Browser eine Art Kommandozeile, wenn sie oben Fragmente eines URLs eingeben. Der Browser schlägt sinnvolle Ergänzungen vor oder man ruft gleich die (Google-)Suchfunktion damit auf. Geht meist viel schneller als Bookmarks.

Natürlich unterscheidet sich diese neue Form der Kommandozeile von der ursprünglichen: man muss nicht alle "Befehle" auswendig wissen, man braucht nur etwas über das Kommando oder die Funktion wissen und das eingeben. Meist findet das System dann die gewünschte Funktion.

In eclipse wäre das dann so, dass ich, um den Sourcecode schön zu formatieren nicht im (Kontext-)Menü suchen muss oder mir das Tastenkürzel dafür (und für viele andere Funktionen) merken muss, sondern nur ein Tastenkürzel - z.B. [Strg]+[F1] - und dann brauche ich nur einfach tippen, was ich will: "format", "build", "class" (für neue Klasse anlegen, das geht aber auch jetzt schon auf anderem Weg) usw. Meist müsste ich gar nicht alles tippen.
Diese neue Form der Kommandozeile ist sowohl für Anfänger und Personen, die selten ein bestimmtes Programm verwenden, als auch für Power User, die alles mit der Tastatur bedienen wollen. Ich bin nur gespannt, wann sich so etwas noch allgemeiner durchsetzen wird.

Die Kommandozeile ist wiederauferstanden!

Labels: allgemeines, GUI, User Interface

# Eingestellt von Harald R. Haberstroh @ 12:29 0 Kommentare

This page is powered by Blogger. Isn't yours?

Abonnieren Kommentare [Atom]