ein Kapitel zurück                                           ein Kapitel weiter

vprintf und vfprintf

Wir haben in den beiden Kapiteln zuvor gesehen wie es möglich war durch va_arg die variablen Parameter einzeln zu verarbeiten. Mit den beiden Funktionen vprintf und vfprintf können wir nun die Ganze Liste in einem Stück übernehmen. Das heißt nun das wir dazu den Makronamen va_arg, der den nächsten Parameter der Liste liest, nicht mehr benötigen. Hier erst der Syntax von vprintf...

int vprintf(char *format, va_list name);

Nun wir wollen damit die Funktion printf nachbilden. Wenn sie z.B. eingeben in der Funktion main....

myprintf("Dies ist eine eigene Creation von printf\n");

wird dieser Text auf dem Bildschirm genauso ausgegeben wie mit printf("Dies i.....");

Hier ist der Code dazu....

/*Download:varg5.c*/
#include <stdio.h> #include <stdarg.h> static void myprintf(char *string, ...) { va_list argzeiger; va_start(argzeiger,string); vprintf(string,argzeiger); va_end(argzeiger); } int main() { char hallo[] = "Hallo vprintf\n"; myprintf("Hier ein Beispiel von vprintf...."); myprintf("\n"); myprintf("%d * %d = %d\n",10,10,10*10); myprintf("%s",hallo); return 0; }

Der einzige Unterschied zu den Beispielen in den Kapiteln zuvor ist das hier anstatt va_arg(...) die Funktion vprintf benutzt wird die den ganzen String mit einem Stück übernimmt. Natürlich macht das Programm jetzt wenig Sinn. vprintf eignet sich sehr gut um eigene Fehlermeldungsroutinen zu schreiben. Hierzu ein Beispiel....

/*Download:varg6.c*/
#include <stdio.h> #include <stdarg.h> #include <stdlib.h> const char error1[] = "Wert ist größer als 100\n"; const char error2[] = "Wert ist größer als 200\n"; const char error3[] = "Wert ist negativ (<0)!!\n"; const char noerror[]= "Alles OK\n"; static void fehler(int kennung, const char *format, ...) { va_list vargzeiger; va_start(vargzeiger,format); switch(kennung) { case 0 : printf("\nAchtung : "); vprintf(format,vargzeiger); break; case 1 : printf("\nFehler : "); vprintf(format,vargzeiger); break; case 2 : printf("\nProgrammabbruch : "); vprintf(format,vargzeiger); exit(1);break; case 3 : vprintf(format,vargzeiger); break; default : printf("\nFalscher Funktionsaufruf\n"); break; } va_end(vargzeiger); } int main() { int gesamt=0,neuezahl,x; char plusminus; printf("Zahl eingeben : "); scanf("%d",&gesamt); fflush(stdin); while(1) { fflush(stdin); x=1; printf("Diese Zahl '+' oder '-' Rechnen :\n"); printf("(Oder '=' um d. Programm zu beenden und das Ergebnis auzugeben!)\n"); printf("Eingabe > "); scanf("%c",&plusminus); switch(plusminus) { case '+' : printf("Zahl zum addieren eingeben : "); scanf("%d",&neuezahl); fflush(stdin); gesamt+=neuezahl; break; case '-' : printf("Zahl zum subbtrahieren eingeben : "); scanf("%d",&neuezahl); fflush(stdin); gesamt-=neuezahl; break; case '=' : printf("Das Gesamtergebnis beträgt %d\n",gesamt); fehler(2,"Saubere Beendigung\n"); break; default : fehler(1,"Eingabe: '+', '-' oder '=' für Ende\n"); x=0; break; } if(x) { if(gesamt>100 && gesamt<200) fehler(0,error1); else if(gesamt>200) fehler(1,error2); else if(gesamt<0) fehler(2,error3); else fehler(3,noerror); } } return 0; }

Das sieht doch schon besser aus, oder? Damit können wir jederzeit mit der Eingabe...

fehler(kennungsummer,"Blablabla->String<-blabla");

Auf dem Bildschirm ausgeben, je nachdem welche Kennungsnummer sie an der Funktion fehler(..) übergeben. Dies können sie natürlich beliebig weiter ausbauen. Jetzt bräuchten wir dazu noch eine Funktion womit wir die Fehlermeldungen in eine Art Logdatei schreiben. Am besten mit Datum und Uhrzeit. Solch eine Funktion gibt es zum Glück auch. Hier der Syntax...

int vfprintf(FILE *datei, char *format, va_list argzeiger);

Dies Funktion benötigt außer dem Format und der variablen langen Argumentenliste noch den FILE - Zeiger auf eine Datei die sie zuvor noch öffnen müssen (fopen). Dies ist recht praktisch, somit können sie wenn sie ein Programm für eine Firma schreiben die Messungen macht und jemand versucht diese Messungen zu manipulieren (Fehler löschen) überwachen in dem sie diese Fehlermeldungen im Hintergrund in eine Datei schreiben. Oder wann das letzte mal auf ein Programm zugegriffen wurde.......

Unsere main-Funktion bleibt die selbe wie schon im Programm zuvor. Wir bearbeiten nur unsere Funktion fehler...

/*Download:varg7.c*/
#include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <time.h> const char error1[] = "Wert ist größer als 100\n"; const char error2[] = "Wert ist größer als 200\n"; const char error3[] = "Wert ist negativ (<0)!!\n"; const char noerror[]= "Alles OK\n"; static void fehler(int kennung, const char *format, ...) { FILE *logdatei; struct tm *zeit; time_t jetzt; char zeitdaten[30]; va_list vargzeiger; va_start(vargzeiger,format); if((logdatei=fopen("fehler.log","a+")) == NULL) fprintf(stderr,"Fehler beim öffen von \"fehler.log\" !!\n"); time(&jetzt); zeit=localtime(&jetzt); sprintf(zeitdaten,"%02d.%02d.%04d %02d:%02d ", (*zeit).tm_mday,(*zeit).tm_mon,(*zeit).tm_year+1900, (*zeit).tm_hour,(*zeit).tm_min); switch(kennung) { case 0 : printf("\nAchtung : "); vfprintf(logdatei,zeitdaten,vargzeiger); vfprintf(logdatei,format,vargzeiger); vprintf(format,vargzeiger); break; case 1 : printf("\nFehler : "); vfprintf(logdatei,zeitdaten,vargzeiger); vfprintf(logdatei,format,vargzeiger); vprintf(format,vargzeiger); break; case 2 : printf("\nProgrammabbruch : "); vfprintf(logdatei,zeitdaten,vargzeiger); vfprintf(logdatei,format,vargzeiger); vprintf(format,vargzeiger); exit(1); break; case 3 : vprintf(format,vargzeiger); break; default : printf("\nFalscher Funktionsaufruf\n"); break; } va_end(vargzeiger); fclose(logdatei); }

Lassen sie sich nicht von den Zeitfunktionen verwirren. Ich komme noch zu diesem Thema. Die Interessieren uns jetzt noch nicht. Zuerst öffnen wir mit fopen unsere fehler.log - Datei und hängen am Ende der Datei falls schon vorhanden unsere neuen Eintrag hin. Anschließend ermitteln wir die aktuelle Zeit und das Datum und schreiben diese mittels...

sprintf(zeitdaten,"%02d.%02d.%04d %02d:%02d ",
(*zeit).tm_mday,(*zeit).tm_mon,(*zeit).tm_year+1900,
(*zeit).tm_hour,(*zeit).tm_min);

...in unser char - Array zeitdaten. Mit sprintf sind sie in der Lage Formatiert in einen String zu schreiben. Der Syntax von sprintf ist...

int sprintf(const char *ziel, const char *quelle, ...);

Diese Funktion eignet sich besonders gut dazu wenn man Zahlen in einen String schreiben soll. Die Funktion schreibt außerdem noch am Ende ein das '\0' - Zeichen.

Jetzt schreiben wir je nachdem welche Kennung wir als ersten Parameter an die Funktion fehler() übergeben haben mittels..

vfprintf(logdatei,zeitdaten,vargzeiger);
vfprintf(logdatei,format,vargzeiger);
vprintf(format,vargzeiger);

..als erstes die Zeitdaten in unsere "fehler.log" - Datei. Gleich neben den Zeitdaten schreiben wir noch welcher Fehler gemacht wurde in unsere Logdatei. Mit vprintf() geben wir anschließend diese Fehlermeldung auch noch auf dem Bildschirm aus. Mit vfprintf() ist es sehr einfach ohne großen Aufwand in eine Datei zu schreiben.

Jetzt gibt es eigentlich nur noch die Funktion vsprintf die ähnlich funktioniert wie sprintf. Hierzu erstmal der Syntax...

int vsprintf(const char *puffer,const char *format,va_list argzeiger);

Damit können sie eine variabel lange Argumentliste formatiert in einen String schreiben. Hierzu ein kurzes Beispiel...

/*Download:varg8.c*/
#include <stdio.h> #include <stdarg.h> #include <math.h> static void float2string(char *string, char *dezimal, ...) { va_list argzeiger; va_start(argzeiger,dezimal); vsprintf(string,dezimal,argzeiger); va_end(argzeiger); } int main() { char string[100]; float zahl = 20; float2string(&string,"string-> %.2f <-string",sqrt(zahl)); printf("%s",string); return 0; }

Aufgabe :

Schreiben sie ein Programm das folgende Variablen ....

char c = '/';
int prozent=100;
int teiler = 3;
float schnitt = 33.34;
char string[] = "und das als String";

...ausgibt als einen String....

100% / 3 = 33,34% und das als String

...a la...printf("%s",puffer); Das heißt diese ganze Zeile soll in einem String (Array) stehen. Hier gehts zur Lösung!

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf