ING_DB
This commit is contained in:
parent
da00a9c0b2
commit
65a7369034
|
|
@ -0,0 +1,67 @@
|
|||
# include <stdio.h>
|
||||
/*
|
||||
* Das ist ein Beispiel eines EQL-Programmes in C.
|
||||
* Es setzt die Existenz der personal-Relation inner-
|
||||
* halb der dt-Datenbank voraus.
|
||||
* Wenn Sie nach Aufforderung einen Namen eintippen,
|
||||
* wird das Programm entweder mit dem Gehalt antworten
|
||||
* oder die Nachricht ausgeben, dass der Name in der
|
||||
* Datenbank nicht enthalten ist.
|
||||
* Durch Eingabe eines '?' wird eine Liste aller ge-
|
||||
* speicherter Namen ausgegeben.
|
||||
*
|
||||
* Programmbeendigung : Control-d bzw. Control-z
|
||||
*
|
||||
* Compilierung und Aufruf des Programmes:
|
||||
*
|
||||
* eqc eqldemo.q
|
||||
* cc eqldemo.c -lq
|
||||
* a.out
|
||||
*/
|
||||
main()
|
||||
{
|
||||
## char NAME[21];
|
||||
## char NAM[21];
|
||||
## int GEH;
|
||||
char flag;
|
||||
|
||||
## daba dt
|
||||
## range of p is personal
|
||||
while (eread(NAME))
|
||||
{
|
||||
if(NAME[0] == '?')
|
||||
{
|
||||
## retrieve (NAME=p.name)
|
||||
## {
|
||||
printf("%s\n",NAME);
|
||||
## }
|
||||
continue;
|
||||
}
|
||||
flag = 0;
|
||||
## retrieve (GEH = p.gehalt, NAM=p.name) where
|
||||
## p.name = NAME
|
||||
## {
|
||||
printf("Das Gehalt von %s betraegt %d\n",NAM,GEH);
|
||||
flag = 1;
|
||||
## }
|
||||
if(!flag) printf("%s ist nicht in der Datenbank\n",NAME);
|
||||
}
|
||||
## exit
|
||||
}
|
||||
|
||||
eread(p)
|
||||
char *p;
|
||||
{
|
||||
int c;
|
||||
printf("Name:");
|
||||
while((c = getchar()) != EOF)
|
||||
{
|
||||
if(c == '\n')
|
||||
{
|
||||
*p = 0;
|
||||
return(1);
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -0,0 +1,619 @@
|
|||
# include <stdio.h>
|
||||
/*
|
||||
** Dieses Dokument will als Lehrbeispiel eines EQL-Programmes
|
||||
** in C verstanden werden.
|
||||
** Als Voraussetzung sollten Sie sowohl mit der Programmiersprache
|
||||
** C als auch mit der DABA16-Anfragesprache QL vertraut sein,
|
||||
** bevor Sie die Beispiele durcharbeiten.
|
||||
** Das Programm kann abgearbeitet werden, um zu sehen, wie die
|
||||
** Beispiele bei entsprechenden Eingaben exakt funktionieren.
|
||||
** Um dieses Programm abzuarbeiten, sollten Sie folgende
|
||||
** Shell-Kommandos spezifizieren:
|
||||
**
|
||||
** eqc eqltut.q
|
||||
** cc eqltut.c -lq
|
||||
** a.out
|
||||
**
|
||||
** Das erste Kommando ruft den EQL-Praecompiler fuer C (eqc(mutos))
|
||||
** auf, der in das Programm Code einfuegt, mit dem Anfragen an DABA16
|
||||
** gesendet werden.
|
||||
** Die Ausgabe des Praecompilers erfolgt im vorliegenden Fall
|
||||
** in das File eqltut.c.
|
||||
** Allgemein wird der Praecompiler wie folgt aufgerufen:
|
||||
**
|
||||
** eqc [-d] [-f] [-r] file1.q [file2.q ...]
|
||||
**
|
||||
** Die Ausgabe erscheint in "file1.c" usw..
|
||||
** Die -d-Option veranlasst "eqc" die Zeilennummern-Informationen
|
||||
** in das File zu stellen, so dass bei Laufzeitfehlern diese
|
||||
** mit den entsprechenden Anfragen assoziiert werden koennen.
|
||||
**
|
||||
** Es ist moeglich den C-Praecompiler zu benutzen, um Files mit
|
||||
** EQL-Anweisungen und/ oder Deklarationen einzuschliessen, wenn
|
||||
** die Namen dieser Files auf ".q.h" enden.
|
||||
** Solche durch "eqc" bearbeiteten Files erhalten den Filesuffix
|
||||
** ".q.h" und werden durch den C-Praecompiler durch #include
|
||||
** eingeschlossen.
|
||||
** Files, fuer die zwar #include spezifiziert wird, die aber
|
||||
** obigen Namenskonventionen nicht genuegen, werden durch "eqc"
|
||||
** ignoriert.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** EQL verwendet i.allg. die gleiche Syntax wie QL.
|
||||
** Es gibt jedoch einige wenige Differenzen zwischen EQL und QL
|
||||
** und somit Unterschiede in den QL- und C-Konstruktionen.
|
||||
** Folgende Differenzen bestehen:
|
||||
**
|
||||
** C-variablen, die fuer EQL deklariert werden, sind i.allg. wie
|
||||
** solche ausserhalb von EQL-Anweisungen zu verwenden.
|
||||
** Das gilt nicht innerhalb von Strings bzw., wenn ihnen ein
|
||||
** sogenannter Entreferenzierungsoperator '#' vorangeht.
|
||||
** Im allgemeinen ist Vorsicht geboten, wenn Variablennamen
|
||||
** mit Domaenen-Namen uebereinstimmen.
|
||||
**
|
||||
** Alle Strings, die C-Variablen von DABA16 uebergeben werden,
|
||||
** werden durch Null abgeschlossen.
|
||||
** Damit werden sie um ein Byte laenger als innerhalb der Relation.
|
||||
** Das bedeutet, dass eine Zeichenkette, in die Daten uebertragen
|
||||
** werden sollen, um ein Byte groesser definiert werden muss
|
||||
** als die Domaene, aus der die Daten kommen.
|
||||
**
|
||||
**
|
||||
** Retrieve-Anweisungen ohne Ergebnisrelation haben in EQL
|
||||
** und QL unterschiedliche Interpretationen.
|
||||
** Dazu einige Beispiele.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Zuerst einige Anfragen, die auch in der Schrift
|
||||
** "IQL-Lehrbeispiele, Anleitung fuer den IQL-Nutzer"
|
||||
** enthalten sind. Somit werden die Gemeinsamkeiten und die
|
||||
** Unterschiede zwischen QL und EQL sichtbar.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Es wird mit der Deklaration einiger Variablen begonnen,
|
||||
** die fuer die Interaktionen benoetigt werden. Beachten Sie bitte,
|
||||
** dass die Variablen fuer EQL global sind und, dass die
|
||||
** Deklarationen fuer das gesamte File gelten.
|
||||
*/
|
||||
|
||||
## char tname[21]; /*
|
||||
** tname wird so dimensioniert, dass das
|
||||
** tname-Feld der teile-Relation plus
|
||||
** das Nullbyte gehalten werden koennen.
|
||||
** Der Entreferenzierungsoperator '#'
|
||||
** muss verwendet werden, wenn "tname"
|
||||
** sowohl als Feldname als auch als
|
||||
** Variablenname verwendet wird und
|
||||
** der Feldname gemeint ist. Bei einer
|
||||
** Spezifikation "tname." wuerde EQL an-
|
||||
** nehmen, dass "tname" als Variable
|
||||
** benutzt werden soll.
|
||||
*/
|
||||
|
||||
## char farb[9]; /*
|
||||
** Damit kann das farbe-Attribut der teile-
|
||||
** Relation gehalten werden. Es wurde "farb"
|
||||
** statt "farbe" genannt, so dass
|
||||
** der Term "t.farbe" kein Verweis auf eine
|
||||
** Variable darstellt und somit auch kein
|
||||
** Entreferenzierungsoperator benoetigt
|
||||
** wird.
|
||||
*/
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
|
||||
/*
|
||||
** Die Interaktion mit DABA16 unter Benutzung der dt-
|
||||
** Datenbank wird wie folgt eingeleitet.
|
||||
*/
|
||||
|
||||
|
||||
## daba "-i210" dt
|
||||
|
||||
/*
|
||||
** Beim daba-Aufruf koennen bis zu 9 Argumente spezifi-
|
||||
** ziert werden.
|
||||
** Hier wird das Integer-Ausgabeformat modifiziert.
|
||||
** Optionen muessen in Anfuehrungszeichen eingeschlossen
|
||||
** werden.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Wie in den IQL-Lehrbeispielen, kann die teile-Relation
|
||||
** durch folgende Spezifikation ausgegeben werden.
|
||||
*/
|
||||
|
||||
## print teile
|
||||
|
||||
/*
|
||||
** Das stimmt mit der entsprechenden QL-Anweisung ueberein.
|
||||
** Die EQL-Anweisung ist jedoch durch "##" gekennzeichnet,
|
||||
** um den "eqc"-Praecompiler zu veranlassen, diese Zeile
|
||||
** in C-Anweisungen zu transformieren.
|
||||
*/
|
||||
|
||||
|
||||
## range of t is teile /*
|
||||
** Dies stimmt mit der QL-Syntax
|
||||
** ueberein.
|
||||
** Beachten Sie bitte die
|
||||
** Benutzung eines Kommentares
|
||||
** in EQL-Anweisungen.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Fuer das folgende Beispiel ist zu beachten, dass das erste
|
||||
** "tname" auf die Variable "tname" verweist, waehrend fuer das
|
||||
** zweite "tname" angenommen wird, dass es einen Konstantennamen
|
||||
** darstellt, weil der Entreferenzierungsoperator vorangestellt
|
||||
** wurde.
|
||||
*/
|
||||
## retrieve (tname = t.#tname)
|
||||
## {
|
||||
/*
|
||||
** Alles innerhalb der geschweiften Klammern wird
|
||||
** fuer jedes wiederaufgefundene Tupel wiederholt.
|
||||
*/
|
||||
|
||||
printf("%s\n", tname);
|
||||
|
||||
/*
|
||||
** tname ist ein ordnungsgemaess abgeschlossener
|
||||
** String. EQL schliesst alle Strings, die von
|
||||
** DABA16 uebergeben werden, mit Null ab. Damit
|
||||
** werden Strings gegenueber der Attributlaenge
|
||||
** um Eins groesser. Es wird vorausgesetzt, dass
|
||||
** der Nutzer genug Speicherplatz bereitgestellt
|
||||
** hat!
|
||||
*/
|
||||
## }
|
||||
|
||||
/*
|
||||
** Jetzt sollen Farben und Namen der Teile wiedergefunden
|
||||
** werden.
|
||||
** Der in den "IQL-Lehrbeispielen" dargestellte Fehler soll
|
||||
** uebergangen werden. Es ist nur zu bemerken, dass EQL
|
||||
** den Fehler erkennen wuerde und fuer die folgende
|
||||
** Anweisung nachfolgenden Kommentar geben wuerde.
|
||||
** ## retrieve tname = t.#tname, farb = t.farbe
|
||||
** IS = '=' : line 7, syntax error
|
||||
*/
|
||||
|
||||
|
||||
## retrieve (tname = t.#tname, farb = t.farbe)
|
||||
## /*
|
||||
** Der Name "farb" wurde als Variablenname fuer
|
||||
** "farbe" verwendet.
|
||||
**
|
||||
** Der Kommentar an dieser Stelle muss mit "##"
|
||||
** am Zeilenanfang beginnen, da EQL nach
|
||||
** "## {" sucht, um das Wiederfinden zu wieder-
|
||||
** holen. Gleiches gilt fuer Leerzeilen. Auch sie
|
||||
** muessen mit "##" vor einem "## {" beginnen.
|
||||
*/
|
||||
## {
|
||||
printf("Die Farbe des Teiles %s ist %s\n", tname,farb);
|
||||
## }
|
||||
|
||||
/*
|
||||
** Die Anweisungen ##{ und ##} sind stets notwendig, auch
|
||||
** wenn nur eine Zeile C-Code innerhalb des Wieder-
|
||||
** findens auftritt.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Um die grauen Teile wiederzufinden und auszugeben, ist
|
||||
** folgendes zu spezifizieren.
|
||||
*/
|
||||
|
||||
printf("Folgende Teile sind grau:\n");
|
||||
## retrieve (tname = t.#tname)
|
||||
## where t.farbe = "grau"
|
||||
## {
|
||||
printf("\t%s\n", tname);
|
||||
## }
|
||||
|
||||
/*
|
||||
** Obige Anfrage stimmt mit der entsprechenden Anfrage
|
||||
** der "IQL-Lehrbeispiele" ueberein.
|
||||
*/
|
||||
|
||||
/*
|
||||
** In EQL gibt es den Begriff des "Anfragenpuffers" wie beim
|
||||
** DABA16-Terminal-Monitor nicht.
|
||||
** Wenn die Anfrage 6 der "IQL-Lehrbeispiele" ausgefuehrt
|
||||
** werden soll, muss mit Ausnahme der range-Anweisung
|
||||
** die komplette Anfrage spezifiziert werden.
|
||||
*/
|
||||
|
||||
## retrieve (tname = t.#tname, farb= t.farbe)
|
||||
## where t.farbe = "grau"
|
||||
## or t.farbe = "rosa"
|
||||
## {
|
||||
printf("Die Farbe des Teiles %s ist %s\n", tname, farb);
|
||||
## }
|
||||
|
||||
/*
|
||||
** Jetzt sollen keine Beispiele der "IQL-Lehrbeispiele" mehr
|
||||
** behandelt werden. Es soll auf EQL-Besonderheiten ein-
|
||||
** gegangen werden.
|
||||
*/
|
||||
|
||||
example1();
|
||||
|
||||
/*
|
||||
** Als naechstes ein interaktives Beispiel.
|
||||
*/
|
||||
|
||||
raise();
|
||||
|
||||
/*
|
||||
** Als naechstes ein Beispiel einer "parametrisierten"
|
||||
** Anweisung.
|
||||
*/
|
||||
|
||||
param_ex();
|
||||
}
|
||||
|
||||
/*
|
||||
** Es sei angenommen, dass Teile einer Relation in den Haupt-
|
||||
** speicher uebertragen werden sollen. Dies ist mit DABA16 sehr
|
||||
** schwierig.
|
||||
**
|
||||
** Dieses Beispiel uebertraegt Elemente der "lieferung"-Relation
|
||||
** in ein Feld von Strukturen.
|
||||
*/
|
||||
# define MAXDATA 20
|
||||
/*
|
||||
** Im Folgenden werden die Felder "tnum", "lnum" und "menge"
|
||||
** fuer EQL definiert.
|
||||
*/
|
||||
## struct lieferung
|
||||
## {
|
||||
## int tnum, lnum;
|
||||
## int menge;
|
||||
## };
|
||||
|
||||
/*
|
||||
** Die Zeichen ##{ und ##} am Anfang und Ende des Beispieles
|
||||
** der example1()-Funktion kennzeichnen den Gueltigkeitsbereich
|
||||
** der deklarierten Variablen. Deshalb werden diese Daten von
|
||||
** EQL bezueglich example1 als lokal betrachtet.
|
||||
** Irgendein freier Block (ein ##{...##}, nicht unmittelbar nach
|
||||
** einem ##-retrieve ohne Ergebnisrelation [ohne into]) erklaert
|
||||
** Variablen innerhalb des Blockes als lokal. Das bedeutet jedoch
|
||||
** nur lokal bezueglich einer Stufe. Eine Variable ist entweder
|
||||
** global fuer das File oder sie ist lokal bezueglich einge-
|
||||
** schlossener freier Bloecke.
|
||||
*/
|
||||
|
||||
char x;
|
||||
|
||||
example1()
|
||||
## {
|
||||
|
||||
## struct lieferung data [MAXDATA + 1];
|
||||
register int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
## range of l is lieferung
|
||||
|
||||
/*
|
||||
** Die Sruktur-Feldnamen sind als Strukturfelder bekannt,
|
||||
** weil sie als solche deklariert wurden und die Struktur-
|
||||
** variable "data" folgt.
|
||||
** Auf der rechten Seite des Gleichheitszeichens (=)
|
||||
** gibt es keine Strukturfelder, so dass sie als Domaenen-
|
||||
** namen betrachtet werden.
|
||||
** Jedoch auch der Entreferenzierungsoperator koennte ver-
|
||||
** wendet werden, um Klarheit zu schaffen.
|
||||
*/
|
||||
|
||||
## retrieve (data [i].tnum = l.tnum,
|
||||
## data [i].lnum = l.lnum,
|
||||
## data [i].menge = l.menge)
|
||||
## where l.liefdat <= "84-12-10"
|
||||
## {
|
||||
printf("Lieferant Nr.%d, liefert %d Teil(e) der Teilenr.%d.\n",
|
||||
data [i].lnum, data [i].menge, data [i].tnum);
|
||||
if (i++ >= MAXDATA - 1)
|
||||
{
|
||||
printf("Zu viele Daten!\n");
|
||||
break;
|
||||
/*
|
||||
** Die Unterbrechung ist berechtigt, da
|
||||
** die retrieve-Anweisung in eine "while"
|
||||
** Anweisung konvertiert wird. Die Unter-
|
||||
** brechung ist nur dann anwendbar, wenn
|
||||
** die Wiederauffindung bei einem vom
|
||||
** Anwender entdeckten Fehler verlassen
|
||||
** werden soll.
|
||||
** Nach dem "while" gibt es Code, um die
|
||||
** Uebertragung der Daten, die nicht vom
|
||||
** EQL-Prozess benutzt wurden, zu be-
|
||||
** enden.
|
||||
*/
|
||||
}
|
||||
|
||||
## }
|
||||
## }
|
||||
|
||||
/*
|
||||
** Folgende Routine liefert eine interaktive Terminalsitzung, um
|
||||
** Gehaelter zu aktualisieren. Dazu gibt es auch andere Moeglich-
|
||||
** keiten. Hier sollen jedoch moegliche Fallen gezeigt werden.
|
||||
*/
|
||||
|
||||
raise()
|
||||
## {
|
||||
int flag;
|
||||
int per;
|
||||
## char percent[10];
|
||||
## char rname[21];
|
||||
## char ename[21];
|
||||
## int geh;
|
||||
## char domain[20];
|
||||
## char info[255];
|
||||
|
||||
/*
|
||||
extern int (*IIinterrupt)();
|
||||
extern reset();
|
||||
*/
|
||||
|
||||
|
||||
## range of p is personal
|
||||
|
||||
/*
|
||||
** Weil die range-Anweisung solange gueltig ist, wie DABA16
|
||||
** arbeitet, wird sie vor der Schleife deklariert.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Vor Eintritt in die Schleife wird Vorsorge fuer eine
|
||||
** Fortsetzung der Verarbeitung getroffen, wenn durch
|
||||
** den Anwender eine Unterbrechung erfolgt.
|
||||
** An dieser Stelle darf durch das Programm keine Signal-
|
||||
** behandlung erfolgen, da DABA16 diese ausfuehrt und ver-
|
||||
** sucht, eine Synchronisation mit dem EQL-Prozess zu
|
||||
** erreichen.
|
||||
** Wenn der EQL-Prozess synchronisiert wurde, wird
|
||||
** (*IIinterrupt)() aufgerufen.
|
||||
*/
|
||||
/*
|
||||
|
||||
setexit();
|
||||
Iinterrupt = reset;
|
||||
*/
|
||||
|
||||
loop:
|
||||
printf("Spezifizieren Sie bitte den Namen\n");
|
||||
|
||||
if (eread(ename))
|
||||
return (0);
|
||||
|
||||
if (ename[0] == '?' && ename[1] == '\0')
|
||||
## print personal
|
||||
else
|
||||
{
|
||||
flag = 0;
|
||||
|
||||
/*
|
||||
** In dieser Interaktion werden drei Anfragen
|
||||
** und Berechnungen von DABA16 ausgefuehrt.
|
||||
** Der wiedergefundene Name wird nach "rname" ueber-
|
||||
** tragen, da "ename" Suchmuster-Zeichen enthalten
|
||||
** kann. So kann beispielsweise "Rose*" einge-
|
||||
** geben werden. Fuer "Rose, Peter" und "Rose,
|
||||
** Petra" wuerden die Gehaelter ausgegeben werden.
|
||||
*/
|
||||
|
||||
## retrieve (rname = p.name, geh = p. gehalt)
|
||||
## where p.name = ename
|
||||
## {
|
||||
printf("Das Gehalt von %s betraegt %d\n",
|
||||
rname, geh);
|
||||
flag = 1;
|
||||
## }
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
printf("Diese Person gibt es nicht\n");
|
||||
goto loop;
|
||||
}
|
||||
printf("Gib Zunahme in Prozent:");
|
||||
if (eread(percent))
|
||||
goto loop;
|
||||
|
||||
/*
|
||||
** Es gibt in EQL keine Moeglichkeit, um ein
|
||||
** Tupel zu pruefen, zu modifizieren und an-
|
||||
** schliessend zurueckzuschreiben. Bei "replace"
|
||||
** muss eine Qualifikation enthalten sein, weil
|
||||
** es keine Verbindung zwischen dem vorherigen
|
||||
** "retrieve" und dem "replace" gibt.
|
||||
*/
|
||||
## replace p ( gehalt = p. gehalt + float8(percent)/100
|
||||
## * p. gehalt)
|
||||
## where p.name = ename
|
||||
|
||||
|
||||
per = atoi(percent);
|
||||
|
||||
## retrieve (rname = p.name, geh = p. gehalt)
|
||||
## where p.name = ename
|
||||
## {
|
||||
printf("Diese Gehaltserhoehung ist ");
|
||||
if (per < 5)
|
||||
printf("gering\n");
|
||||
else if (per < 10)
|
||||
printf("maessig\n");
|
||||
else if (per < 30)
|
||||
printf("gut\n");
|
||||
else
|
||||
printf("gewaltig\n");
|
||||
printf(" Gehalt von %s ist jetzt %d\n",rname,geh);
|
||||
## }
|
||||
|
||||
|
||||
printf("Andere Informationen ueber %s gewuenscht?\n"
|
||||
, ename);
|
||||
|
||||
if (eread(domain) || domain[0] == 'n' )
|
||||
goto loop;
|
||||
|
||||
printf("Domaenenname: ");
|
||||
|
||||
if (eread(domain))
|
||||
goto loop;
|
||||
|
||||
/*
|
||||
** Wenn der Anwender mit '?' antwortet, werden
|
||||
** ihm alle vorhandenen Domaenen angezeigt.
|
||||
** Das erfolgt durch Ausgabe der Attribute der
|
||||
** Relation der Tupel der "attribute"-Relation.
|
||||
*/
|
||||
|
||||
if (domain[0] == '?' && domain[1] == '\0')
|
||||
{
|
||||
|
||||
## range of a is attribute
|
||||
|
||||
## retrieve(domain = a.attname)
|
||||
## where a.attrelid = "personal"
|
||||
## {
|
||||
printf("\t%s\n", domain);
|
||||
## }
|
||||
printf("Domaenenname : ");
|
||||
|
||||
if (eread(domain))
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
** Hier wird eine C-Variable als ein Domaenen-
|
||||
** name verwendet. Der Wert der Variablen wird
|
||||
** an DABA16 uebergeben und als Teil der Anfrage
|
||||
** interpretiert.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Die ascii-Funktion wird verwendet, weil der
|
||||
** Domaenentyp nicht bekannt ist. Der Aufruf der
|
||||
** ascii-Funktion fuer Zeichen-Domaenen ist
|
||||
** erlaubt.
|
||||
*/
|
||||
## retrieve (rname = p.name, info = ascii(p.domain))
|
||||
## where p.name = ename
|
||||
## {
|
||||
|
||||
printf("%s\t%s = %s\n", rname, domain, info);
|
||||
## }
|
||||
|
||||
}
|
||||
goto loop;
|
||||
##}
|
||||
|
||||
/*
|
||||
** Die folgende Routine zeigt die Benutzung parametrisierter
|
||||
** EQL-Anweisungen, wobei die Target-Liste bis zur Ausfuehrungs-
|
||||
** zeit unterbestimmt ist.
|
||||
** Dies zeigt einen Weg, wie eine variable Anzahl von Domaenen
|
||||
** oder variable Typen durch die gleiche EQL-Anweisung benutzt
|
||||
** werden koennen.
|
||||
*/
|
||||
|
||||
param_ex()
|
||||
{
|
||||
char name [25]; /*
|
||||
** Variable, verwendet
|
||||
** in der Target-Liste
|
||||
** der parametrisierten
|
||||
** Anweisung, die nicht
|
||||
** fuer EQL deklariert
|
||||
** werden muss.
|
||||
*/
|
||||
register char *string;
|
||||
union var {
|
||||
short empno;
|
||||
char cempno[2];
|
||||
};
|
||||
union var v;
|
||||
char *tl_vector [100];
|
||||
|
||||
/*
|
||||
** Folgender alternative Weg ist moeglich :
|
||||
** ## retrieve (name = p.#name, empno =p.num)
|
||||
** ## {
|
||||
** printf("Person Nr.%d heisst %s.\n",
|
||||
** empno, name);
|
||||
** ## }
|
||||
*/
|
||||
|
||||
/*
|
||||
** Diese Anweisung initialisiert die Target-Listen-
|
||||
** Variable.
|
||||
** Das Prozentzeichen '%' kennzeichnet den Typ des
|
||||
** korrespondierenden, nachfolgenden Argumentes.
|
||||
** Erlaubte Typen sind:
|
||||
** %c -- String beliebiger Laenge
|
||||
** %i2, %i4 -- integer oder long
|
||||
** %f4, %f8 -- float oder double
|
||||
*/
|
||||
|
||||
string = "%c is p.name, %i2 = p.num";
|
||||
tl_vector [0] = name;
|
||||
tl_vector [1] = v.cempno;
|
||||
|
||||
## param retrieve (string, tl_vector)
|
||||
## /*
|
||||
** Diese Anweisung koennte auch wie folgt formuliert
|
||||
** werden.
|
||||
** ## param retrieve ("%c is p.name, %i2 = p.num",
|
||||
** ## tl_vector)
|
||||
*/
|
||||
## {
|
||||
printf("Person Nr.%5d heisst %s.\n", v.empno, name);
|
||||
## }
|
||||
|
||||
/*
|
||||
** Parametrisierte Anweisungen koennen fuer
|
||||
** "append", "copy", "create", "define view",
|
||||
** "retrieve ohne Ergebnisrelation" und
|
||||
** "replace" benutzt werden.
|
||||
** Fuer "append" waere spezifizierbar :
|
||||
** ## param append to personal ("name is %c, num is %i2",
|
||||
** ## tl_vector)
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
** Nachfolgende Routine liest einen String vom Terminal und
|
||||
** schliesst ihn durch Null ab.
|
||||
** Es wird 1 zurueckgegeben, wenn EOF gelesen wird.
|
||||
*/
|
||||
|
||||
eread(p)
|
||||
char *p;
|
||||
{
|
||||
int c;
|
||||
while((c = getchar()) != EOF)
|
||||
{
|
||||
if(c == '\n')
|
||||
{
|
||||
*p = 0;
|
||||
return(0);
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
Loading…
Reference in New Issue