ZFX
ZFX Neu
Home
Community
Neueste Posts
Chat
FAQ
IOTW
Tutorials
Bücher
zfxCON
ZFXCE
Mathlib
ASSIMP
NES
Wir über uns
Impressum
Regeln
Suchen
Mitgliederliste
Membername:
Passwort:
Besucher:
4370321
Jetzt (Chat):
21 (0)
Mitglieder:
5239
Themen:
24223
Nachrichten:
234554
Neuestes Mitglied:
-insane-
ZFX - KurzartikelDruckversion

Unix-Style Filter Programme
Der Kurzartikel von Eike Anderson aka Swordfighter

© Copyright 2002 [whole tutorial] by Eike Anderson aka Swordfighter
Die Texte der Tutorials unterliegen dem Copyright und dürfen ohne schriftliche Genehmigung vom Author weder komplett noch auszugsweise vervielfältigt, auf einer anderen Homepage verwendet oder in sonst einer Form veröffentlicht werden. Die zur Verfügung gestellten Quelltexte hingegen stehen zur freien Weiterverwendung in Software Projekten zur Verfügung.
Die Quelltexte dieses Tutorials werden auf einer "as is" Basis bereit gestellt. Der Autor übernimmt keinerlei Garantie für die Lauffähigkeit der Quelltexte. Für eventuelle Schäden die sich aus der Anwendung der Quelltexte ergeben wird keinerlei Haftung übernommen.


Die Entwicklung von Unix-Style Filter Programmen in C


  1. Filter Programme
  2. wc - der Unix Wordcount Filter
  3. Wordcount Implementation

Wenn man in einer Unix Umgebung (wie z.B.Linux) arbeitet, sollte man wissen, wie Unix Filter
Programme funktionieren, da sie die wahrscheinlich meistgenutzen Programme (außer cd und
ls)
in einer Unix-Shell sind. Dies ist besonders wichtig, wenn man selber einen Unix Filter
programmieren muß.

Nun könnte man die Frage stellen, was ein Filter mit Computerspielen zu tun hat. Die einfache
Antwort ist: Nichts! Andererseits können Filter ein nützliches Tool bei der Spieleentwicklung
sein, z.B. als Batchkonvertierungsprogramm für 3D Modelle.

Filter Programme

ein Filter ist normalerweise ein externes Programm (d.h. nicht in die Shell integriert) oder ein
unabhaengiger Unix Befehl, der Daten von der Standard Eingabe liest und Daten auf der
Standard Ausgabe ausgibt, nachdem sie verarbeitet wurden.

Die folgenden Programme sind häufig benutzte Filter Programme in auf Unix basierenden
Betriebssystemen:

  • grep
  • sort
  • wc
Einer der simpelsten Filter ist der wordcount Befehl wc, und deshalb wird dieser hier benutzt,
um die Funktionsweise von Filtern zu demonstrieren.

wc - wordcount
Die Syntax für den Unix Wordcount Befehl ist:
wc [options] [file(s)]
der Befehl wc liest Daten direkt aus ASCII Dateien oder von der Standard Eingabe
und zählt, wie viele Zeilen, Worte und/oder Zeichen eingelesen wurden. Worte
sind durch Whitespaces getrennt (Leerzeichen, Tabulatoren, Carriage-Returns und
Line-Feeds).

nachdem alle Daten ausgelesen sind, werden die 3 Werte fuer die Zahl der gelesenen
Zeilen, Worte und Zeichen angezeigt. Wurden die Daten direkt aus einer Datei
gelesen, so wird der Dateiname ebenfalls angezeigt.

Der Unix Filer wc akzeptiert die drei Kommandozeilenargumente -l, -w und -c. Sie
werden benutzt um zu bestimmen, ob nur die Zahl der Zeilen (-l), die Wortzahl (-w)
oder die Anzahl der Zeichen (-c) angezeigt werden sollen.


Einfache Wordcount Implementation

Eine spartanische Version von Wordcount könnte folgende Syntax besitzen:
swc
das Programm würde alle Eingaben von der Standard Eingabe erhalten und alle Ausgaben in
den Standard Ausgabe Stream drucken.

Der Source für so ein Programm würde dann so aussehen:




Dies ist eine stark vereinfachte Lösung die nur einen Teil der Funktionalität von wc hat:
sie verarbeitet keine Kommandozeilenargumente und benutzt als Eingabedatenstrom nur
die Standard Eingabe (stdin). In einer Unix Shell könnte dieses Programm (swc - simple
wordcount) mit einer der folgenden Kommandozeilen aufgerufen werden:
cat textfile | swc
swc < textfile

Verbesserte Wordcount Implementation

Ein besserer C Wordcount Befehl könnte folgende Syntax besitzen:
cwc [options] file[s]
Das Programm erhält Eingaben aus einer Datei oder aus mehreren Dateien, die als Argumente
in der Kommandozeile gegeben werden und gibt die Ergebnisse seiner Zählungen auf dem
Standard Ausgabestrom aus. Das Programm akzeptiert ebenfalls einige Optionen, die die
Ausgabe beeinflussen (zählen von Zeilen, Worten und/oder Zeichen).

Diese erweiterte Funktionalität hat erst einmal den Effekt, daß die Zahl der Variablen im
Programm erweitert werden muß:


    char letter,*filename;
    FILE *fp;
    int w=0,c=0,l=0,i,j,words,lines,chars;


Ein String Pointer zum Namen der momentan geöffneten Datei ist die erste Variable, die dem
Programm hinzugefügt werden sollte. Als nächstes muß ein FILE Pointer deklariert werden,
damit das Programm auf Dateien zugegreifen kann. Index Variablen (i, j) werden für Schleifen
gebraucht, die zum Zugriff auf mehrere Dateien durchlaufen werden, da ja mehr als eine Datei
eingelesen werden kann. Letztendlich werden noch die Flags zum selektiven Zählen der Zeilen,
Worte und Zeichen (l, w, c) benötigt.

Die erste größere Veränderung zum ursprünglichen Programm ist die Einführung eines switch-
case Konstruktes zur Abarbeitung der Kommandozeilenargumente:
Die Werte, die geswitched werden sind die Zahl der Argumente argc.

  1. da mindestens ein Dateiname angegeben werden muß würde dieser Fall
    einen Fehler erzeugen und das Programm beenden
  2. defaultmäßig würden alle Flags (l, w, c) gesetzt und der Index i würde auf
    das Kommandozeilenargument verwiesen, das den Namen der Datei enthält,
    die eingelesen werden soll.
dies deckt den Fall ab, daß keine Kommandozeilenargumente gegeben werden, was nicht
funktionieren könnte, und den Fall, daß nur ein Dateiname gegeben ist. Was noch behandelt
werden muß sind die verschiedenen Programmoptionen und eine beliebige Zahl von
Dateinamen, was im default Fall des switch Konstruktes gemacht wird.

Nach Konvention folgen optionale Programmparameter in Unix einem Bindestrich /
Gedankenstrich '-' (unter DOS / Windows würde man einen Schrägstrich '/' verwenden).
Nun müssen noch die übrigen Kommandozeilenargumente abgearbeitet werden. Das letzte
Argument das übergeben wurde ist dabei das Argument argv[argc-1], und da alle Argumente
außer dem Programmnamen abgearbeitet werden müssen ist das erste Argument argv[1]. Für
diesen Fall bietet sich eine For-Schleife an, die i als Index verwendet, der in jedem
Schleifendurchlauf erhöht wird.

Diese Schleife wird jedoch nur zur Registrierung der optionalen Parameter verwendet, womit
die Abbruchbedingung das Erreichen des ersten Arguments ist, das nicht mit einem
Gedankenstrich als erstem Zeichen beginnt. Erfreulicherweise wird der Index  i hierbei bei
Verlassen der Schleife an der korrekten Position für das erste Argument sein, das ein
Dateiname ist.

Unix Kommandozeilenoptionen sind entweder ein einzelnes Flag nach einem Gedankenstrich
oder eine Anzahl von Flags, die einem Gedankenstrich ohne trennende Leerzeichen folgen.
Aus diesem Grund muß die Schleife, die die Optionen registriert eine weitere Schleife
enthalten, die jedes Zeichen in dem String einer Programmoption auf alle Flags des Programms
untersucht. Falls eine illegale, d.h. unbekannte Option gefunden wird, sollte das Programm mit
einer Fehlermeldung beendet werden, wogegen für jede gefundene gültige Option das
entsprechende Flag gesetzt werden muß:


        default:for(i=1;argv[i][0]=='-';i++)
                    for(j=1;argv[i][j]!='\0';j++) 
                       {
                        switch(argv[i][j])
                           {
                            case 'w':w=1; /* w gefunden - setze <i>w</i> auf <b>true</b> */
                                    break;
                            case 'c':c=1; /* c gefunden - setze <i>c</i> auf <b>true</b> */
                                    break;
                            case 'l':l=1; /* l gefunden - setze <i>l</i> auf <b>true</b> */
                                    break;
                            default:printf("UNBEKANNTE OPTION\n");
                                    exit(EXIT_FAILURE);
                           }
                       }


Nachdem die optionalen Parameter registriert worden sind werden die übrigen Argumente
abgearbeitet:
    for(i;i<argc;i++)       
       {
        filename=argv[i];
        words=0;      
        lines=0;
        chars=0;


Alle diese Argumente sollten Dateinamen sein. Wenn sich eine der Dateien nicht öffnen läßt, so
kann man annehmen, daß ein Fatal Error aufgetreten ist und das Programm sollte mit einer
Fehlernachricht beendet werden. Die Dateien selber sollten so ausgelesen werden, wie der
Standard Eingabestrom im swc Programm.

Nachdem jede der angegebenen Dateien abgearbeitet wurde, soll das Programm das Resultat
der Zählungen entsprechend der gewählten Flags - gefolgt vom Namen der Datei - ausgeben:


        fclose(fp);
        if(l) printf("\t%d",lines);
        else  printf("\t%d");
        if(w) printf("\t%d",words);
        else  printf("\t%d");
        if(c) printf("\t%d",chars);
        else  printf("\t%d");
        printf("\t%s\n",filename);


Das komplette Source Listing für diese Wordcount Version gibt es hier: cwc.c.

Dies ist wiederum eine Lösung, die nur einen Teil der Fähigkeiten des Unix Filters wc hat:
obwohl sie Kommandozeilenargumente akzeptiert, benutzt sie nur Daten, die aus Dateien in
das Filter Programm eingelesen wurden, aber keine Daten aus dem Standard Eingabestrom
(stdin).
In einer Unix Shell könnte dieses Programm (cwc - C Wordcount) mit einer der folgenden
Beispiels-Kommandozeilen ausgeführt werden:

cwc textfile
cwc textfile1 textfile2
cwc -l textfile
cwc -l -w textfile
cwc -lc textfile

Ultimative Wordcount Implementation

Inzwischen haben wir jetzt zwei verschiedene Versionen des Programms - eine, die keine
Kommandozeilenargumente akzeptiert, aber dafür mit den Standard I/O Streams arbeitet,
und eine Version, die Kommandozeilenargumente annimmt und Daten aus Dateien liest. Alles
was jetzt noch zu tun ist, ist ein Hybridprogramm zu erstellen, das die Fähigkeiten der beiden
Programme in sich vereinigt. Dieses Hybridprogramm hat dann alle Features des Wordcount
Filters.

Erst einmal eine simpler kosmetische Verbesserung - falls ein Fatal Error auftritt soll das
Programm eine Usage-Meldung ausgeben, bevor es beendet wird:


 #define PUSAGE fprintf(stderr,"USAGE: %s [options] [file(s)]\n\<br>       <stream> | %s [options]\n\n",argv[0])


Die größte Veränderung im Vergleich zum Vorgängerprogramm ist es, daß es nun nur noch
zwei Fälle bei den Kommandozeilenargumente gibt, die getrennt behandelt werden:

1. wenn wir wissen, daß Eingaben aus dem Standard Eingabestrom (stdin) kommen und
2. der Default-Fall, der die Optionalen Kommandozeilenargumente abarbeitet.

Damit das so funktioniert, müssen eine Reihe von Konditionen geprüft werden:

  • wurden keine Flags gesetzt, dann werden die Default Settings benutzt
  • wurden keine Dateinamen angegeben, wird die Standard Eingabe benutzt
Das restliche Programm ist mehr oder weniger identisch zur Vorgängerimplementation.

Das komplette Source Listing für diese Wordcount Version gibt es hier: mwc.c.

So - das war's auch schon. Hat doch überhaupt nicht weh getan - oder?!



Informationen: " ); ?> " ); ?> " ); ?> " ); ?>
WWW :$wwwtitel
Data:Projektdateien
Mail:$author ($email)
Nick:$nick