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 17 Strukturen
  gp 17.1 Struktur deklarieren
  gp 17.2 Initialisierung und Zugriff auf Strukturen
  gp 17.3 Strukturen als Wertübergabe an eine Funktion
  gp 17.4 Strukturen als Rückgabewert einer Funktion
  gp 17.5 Strukturen vergleichen
  gp 17.6 Arrays von Strukturen
  gp 17.7 Strukturen in Strukturen (Nested Structures)
  gp 17.8 Kurze Zusammenfassung zu den Strukturen
  gp 17.9 Union
  gp 17.10 Aufzählungstyp enum
  gp 17.11 Typendefinition mit typedef
  gp 17.12 Attribute von Strukturen verändern (nicht ANSI C)
  gp 17.13 Bitfelder
  gp 17.14 Das offsetof-Makro


Galileo Computing - Zum Seitenanfang

17.6 Arrays von Strukturen  toptop

Bei Arrays von Strukturen gilt dasselbe Prinzip wie im Abschnitt zuvor dargestellt. Die Wertzuweisung funktioniert ebenfalls wie bei den normalen Arrays, nämlich mithilfe des Indizierungsoperators ([]). Hierzu ein Beispiel:

/* struct_arr1.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct index {
   int seite;
   char titel[30];
};
int main(void) {
   int i;
   struct index lib[3];
   lib[0].seite=312;
   strcpy(lib[0].titel, "Arrays von Strukturen");
   lib[1].seite=320;
   strcpy(lib[1].titel, "Strukturen in Strukturen");
   lib[2].seite=900;
   strcpy(lib[2].titel, "Anhang");
   for(i=0; i<3; i++)
      printf("Seite %3d\t %-30s\n", lib[i].seite, lib[i].titel);
   return EXIT_SUCCESS;
}

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 17.4   Array von Strukturen

Die Abbildung verdeutlicht dies nochmals. Auch hierbei erfolgt die Initialisierung der einzelnen Werte über den Punkteoperator. Ein Fehler, der dabei gern gemacht wird, ist folgende falsche Wertübergabe:

// falsche Position des Feldindex
strcpy(lib.titel[1], "Hallo");         //falsch
strcpy(lib[1].titel, "Hallo");         //richtig

Der Variablenname der Struktur lautet schließlich lib und nicht titel.

Jetzt soll das Listing zur Adressverwaltung erweitert werden. Diesmal wird das Programm so umgeschrieben, dass es mit Arrays von Strukturen ausgeführt wird:

struct adres {
   /*Variablen*/
} adressen[100];

In dieser Struktur von Arrays lassen sich somit 100 Daten von Adressen speichern. Hierzu das vollständige Listing:

/* struct_arr2.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 30
static int x = 0;
struct adres {
   char vname[MAX];
   char nname[MAX];
   long PLZ;
   char ort[MAX];
   int geburtsjahr;
} adressen[100];
void Eingabe(int nr, struct adres neu[]) {
   printf("Vorname : ");
   fgets(neu[nr].vname, MAX, stdin);
   printf("Nachname : ");
   fgets(neu[nr].nname, MAX, stdin);
   printf("Postleitzahl: ");
   do {
      scanf("%5ld",&neu[nr].PLZ);
   } while(getchar()!= '\n');
   printf("Wohnort : ");
   fgets(neu[nr].ort, MAX, stdin);
   printf("Geburtsjahr : ");
   do {
      scanf("%4ld",&neu[nr].geburtsjahr);
   }while(getchar()!= '\n');
}
void Suche(struct adres search[], char buchstabe, int nr) {
   int i;
   for(i = 0; i <= nr; i++) {
      if(search[i].nname[0] == buchstabe) {
         printf("\n\nGefunden unter Buchstabe "
                ":\"%c\"\n\n", buchstabe);
         printf("Vorname......:%s",search[i].vname);
         printf("Nachname.....:%s",search[i].nname);
         printf("Postleitzahl.:%ld\n",search[i].PLZ);
         printf("Ort..........:%s",search[i].ort);
         printf("Geburtsjahr..:%d\n", search[i].geburtsjahr);
         printf("\n\tWeiter mit <ENTER>\n");
         getchar();
      }
   }
}
void Ausgabe(struct adres all[],int nr) {
   int i;
   for(i = 0; i < nr; i++) {
      printf("Vorname.........:%s",all[i].vname);
      printf("Nachname........:%s",all[i].nname);
      printf("Postleitzahl....:%ld\n",all[i].PLZ);
      printf("Ort.............:%s",all[i].ort);
      printf("Geburtsjahr.....:%d\n\n",all[i].geburtsjahr);
      if((!(i%2))&& i!=0) {
         printf("\n\tWeiter mit <Enter>\n\n");
         getchar();
      }
   }
}
void Sort(struct adres sort[], int nr) {
   int i,j;
   struct adres *temp;
   temp = (struct adres *)malloc(sizeof(struct adres *));
   if(NULL == temp) {
      printf("Konnte keinen Speicher reservieren...\n");
      return;
   }
   for(i = 0; i < nr; i++) {
      for(j=i+1;j<nr;j++) {
         if(strcmp(sort[i].nname, sort[j].nname) > 0) {
            *temp=sort[j];
            sort[j]=sort[i];
            sort[i]=*temp;
         }
      }
   }
   printf(".....Sortiert!!\n\n");
}
int main(void) {
   int auswahl;
   char c;
   do {
      printf("-1- Neue Adresse eingeben\n");
      printf("-2- Bestimmte Adresse ausgeben\n");
      printf("-3- Alle Adressen ausgeben\n");
      printf("-4- Adressen sortieren\n");
      printf("-5- Programm beenden\n");
      printf("\nIhre Auswahl : ");
      scanf("%d",&auswahl);
      /* fflush(stdin); */
      getchar();
      switch(auswahl) {
         case 1 : Eingabe(x++,adressen);
                  break;
         case 2 : printf("Anfangsbuchstabe d. Nachnamen :");
                  do {
                     scanf("%c",&c);
                  } while(getchar()!= '\n');
                  Suche(adressen,c,x);
                  break;
         case 3 : Ausgabe(adressen,x);
                  break;
         case 4 : Sort(adressen,x);
                  break;
         case 5 : printf("Ende....\n");
                  break;
         default: printf("Falsche Eingabe\n");
      }
   }while(auswahl <5);
   return EXIT_SUCCESS;
}

Der erste Funktionsaufruf des Programms lautet:

Eingabe(x++, adressen);

Damit wird die Funktion Eingabe() zur Eingabe eines Adresssatzes aufgerufen. Als Argument wird dieser Funktion die globale Variable x und die Struktur adressen vom Typ struct adres übergeben. Die globale Variable x dient als Zähler und Indexfeld, wie viele und welche Strukturen gespeichert wurden. Der Funktionskopf sieht so aus:

void Eingabe(int nr, struct adres neu[])

Wenn Sie das Buch genau durchgelesen haben, wissen Sie, dass Sie auch folgende Schreibweise hätten verwenden können:

/* struct adres *neu und struct adres neu[]==call-by-reference */
void Eingabe(int nr, struct adres *neu)

Jetzt werden die ersten Daten in die Struktur eingegeben:

printf("Vorname : ");
fgets(neu[nr].vname, MAX, stdin);

fgets() liest den Vornamen des ersten Adresssatzes ein. Genauso werden auch die nächsten Daten an den einzelnen Strukturelementen übergeben. Danach können Sie einen zweiten Adresssatz eingeben.

Benötigen Sie z.B. den Nachnamen des 20. Adresssatzes (falls vorhanden), können Sie diesen wie folgt ausgeben lassen:

printf("%s", adressen[19].nname);

Die zweite Funktion des Programms lautet:

Suche(adressen, c, x);

Sie stellt eine primitive Suchfunktion nach dem Anfangsbuchstaben des Nachnamens dar. Die Funktion erhält als Argument die Anfangsadresse des ersten Strukturarrays, den Anfangsbuchstaben des Nachnamens (c) und den Indexzähler für die Anzahl der vorhandenen Strukturen (x).

void Suche(struct adres search[], char buchstabe, int nr)

Die Suche selbst ist relativ einfach aufgebaut:

for(i = 0; i <= nr; i++) {
      if(search[i].nname[0] == buchstabe)

In der for-Schleife wird die Anzahl der vorhandenen Adressen hochgezählt, um jeden Adresssatz mit dem eingegebenen Anfangsbuchstaben des Nachnamens zu vergleichen. Als Beispiel sei der Buchstabe »M« gegeben. Der Programmablauf sieht damit folgendermaßen aus:

for...i=0
if(search[0].nname[0] == 'M')
falls ja, werden dessen Daten ausgegeben
for..i++ ..i<=nr
if(search[1].nname[0] == 'M')
falls ja, werden dessen Daten ausgegeben
for..i++..i<=nr
if(search[2].nname[0] == 'M')
u.s.w.

Diese Suchfunktion sucht nur anhand des ersten Buchstabens des Nachnamens. Bei der Suche nach ganzen Namen ist die Implementierung nicht viel komplizierter. Dazu verwenden Sie am besten die Funktion strcmp() aus der Headerdatei <string.h>. Die Funktion Ausgabe() ist die einfachste von allen. Hiermit wird lediglich der Indexzähler hochgezählt, um alle vorhandenen Adressen auf dem Bildschirm auszugeben. Als etwas schwieriger dürfte sich die Sortierfunktion erweisen:

void Sort(struct adres sort[], int nr)

So wird ein Zeiger temp vom Typ struct adres * definiert:

struct adres *temp;
temp = (struct adres *)malloc(sizeof(struct adres *));

Dieser dient als temporärer Zwischenspeicher dem Austausch zweier Strukturen. Damit dieser Zwischenspeicher auch verwendet werden kann, muss Speicherplatz von der Größe der Struktur reserviert werden. Danach wird die Struktur mit dem Algorithmus »Selektion Sort« nach dem Anfangsbuchstaben des Nachnamens sortiert:

   for(i = 0; i < nr; i++) {
      for(j=i+1;j<nr;j++) {
         if(strcmp(sort[i].nname, sort[j].nname) > 0) {
            *temp=sort[j];
            sort[j]=sort[i];
            sort[i]=*temp;
         }
      }
   }

Bei den Strukturen von Arrays tritt irgendwann das gleiche Problem wie bei den Arrays auf. Nach 100 Adressen ist bei diesem Programmbeispiel Schluss. Dann müssen Sie sich wieder um neuen Speicherplatz Gedanken machen. Vom Aufwand einmal abgesehen, sind Strukturarrays eine erhebliche Bremse für ein Programm. Beispielsweise das Sortieren: Alle Elemente einer Struktur müssen erst in einen temporären extra reservierten Speicher kopiert werden. Danach müsste Speicherplatz für neue Elemente der Struktur reserviert werden. Jetzt können Sie die Daten aus dem temporären Speicher wieder zurückkopieren, und zwar in den neu angelegten Speicher für Strukturen von Arrays. Von dem Fall, dass ein Element mitten in der Liste gelöscht werden soll, ganz zu schweigen. Schließlich müssen Sie diese Lücke auch wieder füllen. Somit müssten Sie z.B. alle Daten hinter dem gelöschten Element eine Position nach vorn setzen. Wenn dies bei einer Datenbank mit mehreren tausend Adressen vorgenommen wird, wäre die Laufzeit katastrophal. Wie Sie diesen Aufwand umgehen und sich das Leben einfacher machen können, erfahren Sie in Kapitel 23, Dynamische Datenstrukturen.

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