Dieses Beispiel nutzt die IEDTCMD
-Schnittstelle und die IEDTGET
-Schnittstelle, um Sätze einer Datei zu lesen und zu verarbeiten:
/********************************************************************/ /* */ /* Beispiel 2 */ /* */ /* Dieses Beispiel verwendet die IEDTCMD-Schnittstelle zur */ /* Ausfuehrung von EDT-Anweisungen sowie die IEDGET- */ /* Schnittstelle zum Lesen von Zeilen. Es werden aus einer */ /* Datei, die Rechnungsdaten enthaelt, alle Datensaetze */ /* ausgegeben, deren Rechnungsdatum mehr als eine fest */ /* vorgegebene Anzahl von Tagen vor dem aktuellen Datum */ /* liegen. */ /* */ /* Das Beispielprogramm fuehrt im Einzelnen folgende Aktionen */ /* durch: */ /* */ /* 1) Aktuelles Datum ermitteln. */ /* 2) Alle Zeilen der Datei mit den Rechnungsdaten mittels der */ /* @COPY-Anweisung (Format 1) in den Arbeitsbereich $0 einlesen. */ /* 3) In einer Schleife nacheinander alle Zeilen des Arbeits- */ /* bereichs $0 lesen und die Zeitdifferenz zwischen dem */ /* aktuellen Datum und dem Rechnungsdatum berechnen. Ist */ /* diese Zeitdifferenz groesser, als ein fest vorgegebenes */ /* Limit, wird von dieser Zeile Kundennummer, Rechnungsnummer */ /* und Rechnungsbetrag ausgegeben. */ /* 4) Nach Beendigung der Schleife wird der EDT mit der Anweisung */ /* @HALT und anschliessend dieses Beispielprogramm beendet. */ /* */ /********************************************************************/ #include <string.h> #include <stdlib.h> #include <stdio.h> #include <time.h> /* Include-Dateien der EDT-Unterprogrammschnittstelle */ #define EDT_V17 #include <iedtgle.h> /* Anlegen und Initialisieren der fuer dieses Beispiel benoetigten */ /* Datenstrukturen der EDT-Unterprogrammschnittstelle. */
static iedglcb glcb = IEDGLCB_INIT; static iedupcb upcb = IEDUPCB_INIT; static iedamcb amcb = IEDAMCB_INIT; static iedbuff *command = NULL; static iedbuff *message1 = NULL; static iedbuff *message2 = NULL; /* Definition einer Ausgabezeile */ typedef struct line { char kdnr[8]; /* Kundennummer */ char free1[2]; char renr[8]; /* Rechnungsnummer */ char free2[2]; char betr[10]; /* Rechnungsbetrag */ char free3[2]; char day[2]; /* Tag der Rechnungsstellung */ char trenn1[1]; char mon[2]; /* Monat der Rechnungsstellung */ char trenn2[1]; char year[4]; /* Jahr der Rechnungsstellung */ char rest[215]; } LINE; /********************************************************************/ /* Funktion: printrc */ /* */ /* Aufgabe: */ /* Falls der EDT eine Fehlermeldung zurueckgegeben hat, wird die */ /* Fehlermeldung durch diese Funktion ausgegeben. */ /* */ /* Parameter: errmsg (IN) Zeiger auf die im Fehlerfall */ /* zusaetzlich auszugebende Fehlermeldung */ /* */ /* Rueckgabewert: keiner */ /********************************************************************/ static void printrc(char *errmsg) { char message[81]; if (glcb.IEDGLCB_RC_MAINCODE != 0) { printf("%s: %08x\n",errmsg, glcb.IEDGLCB_RC_NBR);/* Uebergebene Fehlermeldung + code ausgeben */ if (glcb.return_message.structured_msg.rmsgl > 0) {
strncpy(message,(char*)glcb.return_message.structured_msg.rmsgf, glcb.return_message.structured_msg.rmsgl); message[glcb.return_message.structured_msg.rmsgl] = 0x00; printf("Meldungstext: %s\n",message); /* EDT-Meldung ausgeben */ } exit(1); } } /********************************************************************/ /* Funktion: fill_buff */ /* */ /* Aufgabe: */ /* Diese Funktion versorgt einen Satz variabler Laenge (DVS-Format) */ /* mit einem Inhalt sowie das Satzlaengenfeld. */ /* */ /* Parameter: p: (IN) Zeiger auf eine Struktur vom Typ */ /* iedbuff, die den zu versorgenden Satz */ /* variabler Laenge enthaelt. */ /* textp: (IN) Zeiger auf einen String, der den ein- */ /* zutragenden Text enthaelt. Die Laenge */ /* des Strings legt implizit die Laenge */ /* des Satzes fest (Laenge String + 4). */ /* */ /* Rueckgabewert: keiner */ /********************************************************************/ static void fill_buff(iedbuff *p,char *textp) { size_t l_text; /* Laenge des String */ if ((l_text = strlen(textp)) > 2044) l_text = 2044; /* Laenge auf 2044 Zeichen begrenzen */ strncpy((char *)p->text,textp,l_text); /* Text eintragen */ p->length = l_text + 4; /* Satzlaenge versorgen */ } /********************************************************************/ /* Funktion: edtcmd */ /* */ /* Aufgabe: */ /* Diese Funktion traegt die uebergegebenen Strings in Saetze */ /* variabler Laenge ein (DVS-Format) und ruft anschliessend die */ /* CMD-Schnittstelle des EDT auf. */ /* */ /* Parameter: cmd: (IN) Zeiger auf einen String, der die */ /* auszufuehrenden EDT-Anweisung(en) */ /* enthaelt. Die Laenge des Strings legt */
/* implizit die Laenge des Satze fest */ /* (Laenge String + 4). */ /* msg1: (IN) Zeiger auf einen String, der den ein- */ /* zutragenden Text enthaelt. Die Laenge */ /* des Strings legt implizit die Laenge */ /* des Satzes fest (Laenge String + 4). */ /* msg2: (IN) Zeiger auf einen String, der den ein- */ /* zutragenden Text enthaelt. Die Laenge */ /* des Strings legt implizit die Laenge */ /* des Satzes fest (Laenge String + 4). */ /* */ /* Rueckgabewert: keiner */ /********************************************************************/ static void edtcmd(char *cmd,char *msg1,char *msg2) { fill_buff(command,cmd); fill_buff(message1,msg1); fill_buff(message2,msg2); IEDTCMD(&glcb,&upcb,command,message1,message2); } /********************************************************************/ /* Funktion: edtget */ /* */ /* Aufgabe: */ /* Diese Funktion liesst mit der Funktion GET der Unterprogramm- */ /* Schnittstelle eine Zeile aus der Arbeitsdatei $0. Es wird immer */ /* relativ zum Satz mit Zeilennummer 0 gelesen. */ /* */ /* Parameter: rec: (IN) Zeiger auf einen Datenbereich, in dem */ /* die von der Funktion GET gelesene */ /* Zeile abgelegt wird. */ /* disp: (IN) Gibt an, die wievielte Zeile ab der */ /* Zeilennummer 0 gelesen werden soll. */ /* Rueckgabewert: keiner */ /********************************************************************/ static void edtget(char *rec,int disp) { char localfile[9] = "$0 "; iedbyte key1[8] = {0,0,0,0,0,0,0,0}; iedbyte key[8] = {0,0,0,0,0,0,0,0}; /* Kontrollblock IEDAMCB versorgen */ IEDAMCB_SET_NO_MARKS(amcb); amcb.length_key_outbuffer = 8; amcb.length_rec_outbuffer = 256;
amcb.length_key1 = 8; /* -------------------------- (1) */ amcb.displacement = disp; /* lese <disp> Sätze nach Nr. 0 */ strncpy((char *)amcb.filename,localfile,8); /* Arbeitsdatei $0 */ IEDTGET(&glcb,&amcb,key1,key,rec); } /********************************************************************/ /* Hauptprogramm */ /********************************************************************/ int main(void) { char filename[] = "edt.rechnung2"; char cmd[257]; LINE zeile; int disp; int days = 20; int time_diff; time_t zeit1; time_t zeit2; struct tm t; printf("\nStart Beispiel2\n\n"); /* buffer bereitstellen */ command = (iedbuff *)malloc(2048); message1 = (iedbuff *)malloc(2048); message2 = (iedbuff *)malloc(2048); /* Heutiges Datum ermitteln */ zeit1 = time((time_t *) 0); /* Fuer die Umwandlung des Datums in der Zeile */ /* wird die Uhrzeit auf 0 Uhr gesetzt */ t.tm_sec = 0; t.tm_min = 0; t.tm_hour = 0; /* Die zu bearbeitende Datei mit der */ /* Anweisung @COPY (Format 1) einlesen */ sprintf(cmd,"COPY FILE=%s",filename); edtcmd(cmd,"",""); printrc("Fehler bei der @COPY-Anweisung!"); /* In der folgenden Schleife werden alle Zeilen */ /* der Arbeitsdatei $0 bearbeitet. */
for (disp = 1; disp < 99999999; disp++) /*-------------------- (2) */ { /* Naechste Zeile lesen */ edtget((char *)&zeile,disp); printrc("Fehler bei der Funktion GET!"); /* Wenn jenseits der letzten Zeilennummer gelesen wird */ /* gibt IEDTGET "last record" zurück */ if (glcb.IEDGLCB_RC_SUBCODE1 == IEDGLCBlast_record) break; /* Schleife verlassen */ t.tm_mday = atoi(zeile.day); /* Datum aus der */ t.tm_mon = atoi(zeile.mon) - 1; /* eingelesenen */ t.tm_year = atoi(zeile.year) - 1900; /* Zeile holen */ zeit2 = mktime(&t); /* Datum in einen */ /* Zeitwert konv. */ /* Zeitdifferenz in Tagen bestimmen */ time_diff = difftime(zeit1,zeit2)/86400; /* Falls die vorgegebene Zeitspanne vorbei ist, fuer die */ /* aktuelle Zeile Kundennummer, Rechnungsnummer und */ /* Rechnungsbetrag ausgeben. */ if (time_diff > days) { zeile.free1[0] = '\0'; /* ---------------------------- (3) */ zeile.free2[0] = '\0'; zeile.free3[0] = '\0'; printf("Kdnr.: %s, Rechn.nr.: %s, Betrag: %s Euro\n", zeile.kdnr,zeile.renr,zeile.betr); } } /* EDT und Programm beenden */ edtcmd("HALT","",""); printrc("Fehler bei der @HALT-Anweisung!"); printf("\n\nEnde Beispiel2\n\n"); return 0; }
Erläuterungen
(1) | Bei der IEDTGET -Funktion müssen nur length_key1 und length_key_outbuffer versorgt sein. |
(2) | Die hier implementierte Methode zum sequenziellen Lesen der Arbeitsdatei ist nicht sonderlich effektiv, da immer wieder von Beginn an gelesen wird. Man überlege sich, wie man unter Verwendung des in key zurück gelieferten Schlüssels mit konstantem amcb.displacement = +1 einen günstigeren Algorithmus implementieren kann. |
(3) | Hier wird das Endezeichen für C-Strings eingesetzt, um eine direkte Ausgabe ohne Umwandlung zu ermöglichen. |
Wenn die in Abschnitt „Produktion von Hauptprogrammen in C“ erklärte Prozedur im BS2000 in einer Datei namens CC.DO
und die Quelldatei als S-Element BEISPIEL2.C
in der Bibliothek EDT.BEISPIELE
abgelegt ist, kann das obige Programm mit
/CALL-PROC CC.DO,(2)
übersetzt und gebunden werden. Das erzeugte Programm ist anschließend mit
/START-EXECUTABLE-PROGRAM (E=BSP2C,L=EDT.BEISPIELE)
ausführbar. Bei Ablauf von CC.DO
werden etwa folgende Ausgaben vom System bzw. vom Compiler erzeugt:
% BLS0524 LLM 'SDFCC', VERSION '03.1A40' OF '2005-02-03 16:16:36' LOADED % BLS0551 COPYRIGHT (C) Fujitsu Siemens Computers GmbH 2005. ALL RIGHTS RESERVED % CDR9992 : BEGIN C/C++(BS2000/OSD) VERSION 03.1A40 % CDR9907 : NOTES: 0 WARNINGS: 0 ERRORS: 0 FATALS: 0 % CDR9937 : MODULES GENERATED, CPU TIME USED = 2.6000 SEC % BND3102 SOME WEAK EXTERNS UNRESOLVED % BND1501 LLM FORMAT: '1' % BND1101 BINDER NORMALLY TERMINATED. SEVERITY CLASS: 'UNRESOLVED EXTERNAL' % CDR9936 : END; SUMMARY: NOTES: 0 WARNINGS: 0 ERRORS: 0 FATALS: 0 % CCM0998 CPU TIME USED: 3.6403 SECONDS
Die von diesem Beispielprogramm zu bearbeitende Datei EDT.RECHNUNG2
sehe folgendermaßen aus:
00347563 00028654 1378.89 21.05.2007 00345781 00027349 21500.00 07.04.2007 00375863 00028937 248.23 19.05.2007 00242365 00012358 4577.54 23.03.2007 00416467 00046687 6776.31 10.05.2007 00576373 00015463 578.00 19.04.2007 00785214 00053417 65465.00 13.12.2006 00265432 00065743 6534.67 16.05.2007
00546315 00035476 656.34 29.05.2007 00675436 00015334 7878.45 04.05.2007 00353466 00087227 654.24 11.11.2006 00534267 00067854 52346.00 15.05.2007 00243535 00078921 4532.54 22.04.2007 00783432 00063223 548.19 17.05.2007 00623556 00054342 5346.32 17.03.2007 00234354 00065233 4534.65 08.05.2007
Nach Aufruf von /START-EXECUTABLE-PROGRAM (E=BSP2C,L=EDT.BEISPIELE)
wird dann (am 4.5.2007) in etwa folgende Ausgabe zu sehen sein:
% BLS0523 ELEMENT 'BSP2C', VERSION '@', TYPE 'L' FROM LIBRARY ':A:$USER.EDT .BEISPIELE' IN PROCESS % BLS0524 LLM '$LIB-ELEM$EDT$BEISPIELE$$BSP2C$$', VERSION ' ' OF '2007-05-04 12 :22:24' LOADED Start Beispiel2 Kdnr.: 00345781, Rechn.nr.: 00027349, Betrag: 21500.00 Euro Kdnr.: 00242365, Rechn.nr.: 00012358, Betrag: 4577.54 Euro Kdnr.: 00785214, Rechn.nr.: 00053417, Betrag: 65465.00 Euro Kdnr.: 00353466, Rechn.nr.: 00087227, Betrag: 654.24 Euro Kdnr.: 00623556, Rechn.nr.: 00054342, Betrag: 5346.32 Euro Ende Beispiel 2 % CCM0998 CPU TIME USED: 0.3276 SECONDS