Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 20 Arbeiten mit variablen langen Argumentlisten – <stdarg.h>
  gp 20.1 Makros in <stdarg.h> – va_list, va_arg, va_start und va_end
  gp 20.2 Argumentliste am Anfang oder Ende kennzeichnen
  gp 20.3 vprintf, vsprintf und vfsprintf


Galileo Computing - Zum Seitenanfang

20.2 Argumentliste am Anfang oder Ende kennzeichnen  toptop

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:

Abbildung
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;
}

Abbildung
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.

 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de