20.2 Argumentliste am Anfang oder Ende kennzeichnen
 
Diese vier Makros werden Sie jetzt anwenden. Es soll eine Funktion geschrieben werden, welche eine variable Anzahl von Argumenten erhält. Die Argumente (Ganzzahlen) werden dabei alle zu einer Summe addiert. Hier das Listing:
/* vargs1.c */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int add(int zahlen, ...) {
va_list zeiger;
int zahl;
va_start(zeiger,zahlen);
do {
zahl = va_arg(zeiger,int);
zahlen += zahl;
} while(zahl != 0);
va_end(zeiger);
return zahlen;
}
int main(void) {
int erg;
printf("%d\n",add(11,12,13,0));
printf("%d\n",add(99,66,33,22,11,0));
erg = add(10, 13, 11, 0) + add(9, 8, 11, 0);
printf("%d\n",erg);
return EXIT_SUCCESS;
}
Zuerst der Aufruf der Funktion mit:
printf("%d\n",summe(11,12,13,0));
So wird die Funktion mit den Argumenten 11, 12, 13 und 0 aufgerufen. Die Zahl 0 am Ende stellt die Abbruchbedingung dar. Dies alles nun aber etwas genauer: Zuerst wird mit
va_list zeiger;
ein abstrakter Datentyp deklariert, welcher für die Verarbeitung der weiteren Funktion benötigt wird. Mit
va_start(zeiger,zahlen);
wird die Liste initialisiert. Man könnte auch sagen, der Datentyp zeiger verweist auf die Anfangsadresse der ersten Zahl der Argumentliste. Anschließend wird in der do while-Schleife mit
zahl=va_arg(zeiger,int);
der nächste Wert in der Argumentliste an die Variable zahl übergeben. In diesem Beispiel ist dies die Zahl 12. Diese Zahl wird zu dem ersten Wert von zahlen (11) addiert.
Ist die Bedingung der Schleife wahr (zahl != 0), fährt das Programm mit zahl=va_arg(zeiger,int) und dem nächsten Wert (13) fort und addiert diesen wieder mit zahlen. Beim nächsten Durchgang ist die while-Bedingung unwahr (zahl==0), und die Liste wird beendet mit
va_end(zeiger);
Anhand des ersten Funktionsaufrufs können Sie sich dies grafisch so vorstellen:
 Hier klicken, um das Bild zu Vergrößern
Abbildung 20.1
Zugriff einzelner Werte bei einer variablen Argumentliste
Jetzt soll das Programm so umgeschrieben werden, dass mit einer bestimmten Anzahl von Argumenten gearbeitet wird:
/* vargs2.c */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void print_zahlen(int anzahl, ...) {
va_list zeiger;
int zahl;
int i;
printf("Es werden %d Zahlen ausgegeben\n",anzahl);
va_start(zeiger,anzahl);
for(i = 1; i <= anzahl; i++) {
zahl=va_arg(zeiger,int);
printf("%d\t",zahl);
}
printf("\n");
va_end(zeiger);
}
int main(void) {
print_zahlen(4,3,2,4,7);
print_zahlen(6,11,22,33,44,55,66);
return EXIT_SUCCESS;
}
Das Programm ist ähnlich aufgebaut wie im Beispiel zuvor, nur dass hier als Abbruchbedingung das erste Argument verwendet wurde. Mit dem Funktionsaufruf
print_zahlen(6, 11, 22, 33, 44, 55, 66);
wird durch das erste Argument gekennzeichnet, dass die Funktion mit 6 Argumenten vom Typ int aufgerufen wird. Dies ist auch die Abbruchbedingung für die for-Schleife in der Funktion print_zahlen().
Diese Makros sind natürlich noch deutlich vielseitiger, als Beispiel sei die Funktion strcat() zum Anhängen eines Strings an einen anderen genannt. Häufig würden Sie sicherlich gern mehrere Strings auf einmal an einen anderen hängen. Dabei mussten Sie bislang immer mehrere strcat()-Aufrufe ausführen. Mit dem eben gezeigten Beispiel kann dies jetzt in einem Schritt realisiert werden:
strxcat(3, string, string1, string2);
Hiermit werden die beiden Strings string1 und string2 an den String string gehängt. Die Anzahl der Strings wird am Anfang der Argumentliste gekennzeichnet. Hierzu das Listing:
/* strxcat.c */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define MAX 50
void strxcat(int n_strings, ...) {
va_list zeiger;
char *quelle, *ziel, *p;
va_start(zeiger,n_strings);
/* Nun auf den Zielstring */
ziel = va_arg(zeiger,char *);
p = ziel;
/* Am Ende vom Zielstring */
ziel+=strlen(ziel);
if( (ziel-p) > MAX) {
printf("!!!Max. Anzahl Zeichen Überschritten!!!\n");
return;
}
while(--n_strings > 0) {
/* Quelle einlesen */
quelle = va_arg(zeiger, char *);
/* Jetzt Zeichen für Zeichen an ziel */
while(*quelle) {
*ziel++ = *quelle++;
if( (ziel-p) > MAX) {
printf("!Max. Zeichen ueberschritten!\n");
exit(EXIT_FAILURE);
}
}
}
*ziel = '\0';
}
int main(void) {
char string[MAX] = "Test : ";
char string2[] = " Und";
strxcat(3, string, "hallo " , "welt");
printf("%s\n",string);
strxcat(5, string, string2, " noch", " ein", " Test");
printf("%s\n",string);
/*Und nun ein Fehler mit Absicht*/
strxcat(4, string , " Ueberlauf", " von", " MAX");
printf("%s\n",string);
return EXIT_SUCCESS;
}
 Hier klicken, um das Bild zu Vergrößern
Abbildung 20.2
Mehrere Strings auf einmal aneinander hängen
Hier wurde auch eine Sicherung eingebaut, um sich vor so genannten Pufferüberläufen zu schützen.
|