ein Kapitel zurück                                           ein Kapitel weiter

Kommen wir wieder zurück zu unseren Zeigern. Dieses Kapitel wird für sie wahrscheinlich ein sehr schweres. Legen wir los mit dem Thema 'Zeiger auf Zeiger'. Hier der Syntax vom Zeiger auf Zeiger...

int **ptrptr;
char **cpointer;
float **fptrptr;


Nun was heißt jetzt eigentlich Zeiger auf Zeiger? Das heißt eigentlich man hat einen Zeiger der auf einen Zeiger zeigt, der auf eine Variable zeigt und auf diese Variable zurückgreifen kann. Nun Ihre erste Frage wird wohl sein welchen Zweck so etwas haben. Nun wie würden sie zum Beispiel folgendes nach Alphabet sortieren (mal abgesehen von strcmp())....

"Zeppelin" , "Auto" , "Amerika" , "Programmieren"

In Zeiger Teil 3 haben sie gelernt das '*ptr' Dasselbe ist wie 'ptr[0]'. Beide zeigen auf den Anfang Ihrer vom Compiler vergeben Adresse. Unabhängig was darin steht. Nun gleiches gilt für...

**ptrptr und *ptrptr[0]

Somit haben wir einen Zeiger auf ein Feld. Und jetzt unsere zu sortierenden Zeichenketten...

char *sort[]={"Zeppelin" ,"Auto", "Amerika", "Programmieren" };

Nun wie greifen wir jetzt auf die einzelnen Elemente zu? Dazu ein kleines Beispiel....

/*Download:zeig1.c*/
#include <stdio.h>

int main()
{
char *sort[] = {"Zeppelin", "Auto", "Amerika", "Programmieren"};


printf("%s\n",sort[1]);
printf("%s ",(sort[2]+2));
printf("%s %s\n",(sort[0]+6),sort[2]);
printf("%s\n",(sort[3]+5-2));
return 0;
}

Die Zugriffweise erfolgt ähnlich wie bei den Mehrdimensionalen Arrays. Die erste Ausgabe...

printf("%s\n",sort[1]);

..gibt das Wort 'Auto' auf dem Bildschirm aus. Daher können wir davon ausgehen das ....

sort[0]="Zeppelin"
sort[1]="Auto"
sort[2]="Amerika"
sort[3]="Programmieren"


...sind. Mit der zweiten Anweisung....

printf("%s ",(sort[2]+2));

wir das Wort 'erika' ausgegeben. Das kann man so lesen: mit 'sort[2]' zeigt ,unser 1. Zeiger, auf den Anfang von 'Amerika' also auf 'A' und jetzt kommt noch das '+2' hinter dem Feldindex hinzu und unser 2 Zeiger der ohne '+2' weiterhin auch auf den Anfang von Amerika gezeigt hätte, zeigt jetzt auf den 3.Buchstaben des Wortes 'Amerika' also auf 'e' oder genauer auf die Adresse von 'e'. Mit '%s' wird veranlasst das der String dann auf den Bildschirm ausgegeben wird. Mit auf dem Anfang zeigen meine ich natürlich den Anfang der Adresse, aber wir wollen jetzt nicht alles unnötig verkomplizieren. Genauso läuft es bei der nächsten Ausgabe auch ab. Die Schreibweise....

printf("%s\n",(sort[3]+5-2));

...dient natürlich nur zur Demonstration dass es so auch geht. Natürlich lässt sich das leichter lesen mit..

printf("%s\n",(sort[3]+3));

Ich möchte Ihnen das Programm noch mal an Hand von Adressen demonstrieren.....

/*Download:zeig2.c*/
#include <stdio.h>

int main()
{
char *sort[] = {"Zeppelin", "Auto", "Amerika", "Programmieren"};


printf("%p = %c\n",**sort,**sort);
printf("%p = %c\n",*sort[0],*sort[0]);
printf("%p = %c\n",*(sort[0]+0),*(sort[0]+0));

printf("%p = %s\n",sort[0],sort[0]);
printf("%p = %s\n",*sort,*sort);

printf("%p = %s\n",(sort[0]+1),(sort[0]+1));
printf("%p = %s\n",(sort[0]+2),(sort[0]+2));

printf("*sort = %p, **sort = %p\n",*sort,**sort);
printf("sort[0] = %p, *sort[0] = %p\n",sort[0],*sort[0]);
return 0;
}

Bei den ersten drei Ausgaben....

printf("%p = %c\n",**sort,**sort);
printf("%p = %c\n",*sort[0],*sort[0]);
printf("%p = %c\n",*(sort[0]+0),*(sort[0]+0));


...benutzen wir immer die Adresse und den Inhalt auf die der 2.Zeiger zeigt. Was uns die Ausgabe auch bestätigt. Anschließend benutzen wir nur einen Zeiger bei....

printf("%p = %s\n",sort[0],sort[0]);
printf("%p = %s\n",*sort,*sort);


Der Inhalt bei Benutzung von einem Zeiger ist natürlich der selbe wie bei der Benutzung von zweien. Aber wie sie sehen wenn sie das Programm übersetzen haben wir hier eine andere Adresse!! Die Ausgabe von.....

printf("*sort = %p, **sort = %p\n",*sort,**sort);
printf("sort[0] = %p, *sort[0] = %p\n",sort[0],*sort[0]);


...bestätigt uns das ganze nochmals. Den benötigt jeder einzelne Zeiger auch seinen Speicherplatz und somit auch eine eigene Adresse. Ich weiss das ist schwer! Ich versuche es nochmals anders zu Erklären....

*(*(Variable+x)+y)

Wir zeigen hiermit auf das y-te Zeichen im x-ten String. Bei unserem Programm z.B....

*(*(sort+1)+2)

...oder auch...

*(*(sort[1])+2)

Hiermit zeigen wir auf das 2-te Zeichen im 1-ten String das wäre somit das 't' vom String 'Auto'.

So nun wollen wir mal Stringfelder nach Alphabet sortieren. Dabei werden nicht die ganze Textzeile verlagert und unnötig hin.-und-herkopiert sondern wir müssen lediglich die Zeiger in die richtige Reihenfolge bringen....

/*Download:zeig3.c*/
#include <stdio.h>
#include <string.h>

int main()
{
char *sort[] = {"Zeppelin", "Auto", "Amerika", "Programmieren"};
int i,j;
char *temp;

for(i=0; i<4; i++)
{
for(j=i+1; j<4; j++)
{
if((strcmp(sort[i],sort[j])>0))
{
temp=sort[i];
sort[i]=sort[j];
sort[j]=temp;
}
}
}
for(i=0;i<4;i++)
printf("%s\n",sort[i]);

return 0;
}

Jetzt haben sie ihren ersten Sortier - Algorithmus kennen gelernt. Man nennt diesen SELEKTION - SORT. Diese Zeilen sortieren unsere Felder mit Zeigern....

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


Zuerst suchen wir das kleinste Element und setzen es am Anfang. Anschließend das zweitkleinste u.s.w. Das heißt wir vergleichen das 1.Element mit allen anderen. So finden wir das kleinste Element. Dann vergleichen wir das 2.Element mit allen vor ihm liegenden etc. Hier der Ablauf des Programms(Selection - Sort)...

Reihenfolge :"Zeppelin","Auto","Amerika","Programmieren"
1. Ist "Zeppelin > "Auto"(sort[0]
Tausche "Zeppelin" und "Auto"
Reihenfolge :"Auto","Zeppelin","Amerika","Programmieren"
2. Ist "Auto" > "Amerika"(sort[0]
Tausche "Auto" und "Amerika"
Reihenfolge :"Amerika","Zeppelin","Auto","Programmieren"
3. Ist "Amerika" > "Programmieren"(sort[0]
Damit haben wir das "kleinste" Wort am Anfang stehen!
Reihenfolge :"Amerika","Zeppelin","Auto","Programmieren"
4. Ist "Zeppelin" > "Auto"(sort[1]
Tausche "Zeppelin" und "Auto"
Reihenfolge :"Amerika","Auto","Zeppelin","Programmieren"
5. Ist "Auto" > "Programmieren"(sort[1]
Damit haben wir das zweitkleinste Element an der richtigen Stelle.
Reihenfolge :"Amerika","Auto","Zeppelin","Programmieren"
6. Ist "Zeppelin" > "Programmieren"(sort[2]
Tausche "Zeppelin" und "Programmieren"
Reihenfolge :"Amerika","Auto","Programmieren","Zeppelin"
Sortieren fertig!!!!


Zum besseren Verständnis zu diesem Thema noch ein kurzer Abschnitt dazu:

Um zum Beispiel einen Zeiger auf ein Array zuzuweisen macht man diese ja Beispielsweise so..........

char text[] = "unknow Text";
char *ptr;

ptr=text; //ptr zeigt jetzt auf die Anfangsadresse von dem array text


Das wichtigste ist was ich immer sage ist das Zeiger für Adressen da sind und sonst nichts. Beispielsweise bedeutet........

char *text[500];

...nichts anderes als ein char-Array mit 500 char-Zeigern. Genaugesagt kann jeder dieser 500 Zeiger auf einen String (char-Array) zeigen. Was ist der Vorteil daran?
Wenn wir z.B. Zeichenketten sortieren wollen, können wir doch mit Hilfe der Zeiger auf die Anfangsadresse des Strings wesentlich effiktiver (schneller) die Daten sortieren als wenn wir dies mit dem kompletten String machen würden. Da ja nur ein Zeiger auf den String benutzt wird.

Und anstatt zu Schreiben...........

char *sort = "Zeppelin";
char *sort2 = "Auto" ;
char *sort3 = "Amerika";
char *sort4 = "Programmieren";


...ist doch diese Schreibweise......

char *sort[]={"Zeppelin" ,"Auto", "Amerika", "Programmieren" };

....viel effektiver. Wir haben hier 4 Zeiger auf ein char-Array, die im Prinzip nichts anderes machen als auf die Anfangsadresse eines jedes einzelnen Wortes zu zeigen.

Jetzt will ich Ihnen etwas sinnvolleres Beispiel zeigen wie man Zeiger auf ein Array häufig verwendet...

/*Download:zeig4.c*/
#include <stdio.h>
#include <string.h>

char Name[30];
char Strasse[30];
char plzort[25];

char *anrede[] = {"Sehr geehrter ",
"Sehr geehrte ",
"Sehr geehrte Damen & Herren ",
"Hallo ",
"Lieber ",
"Liebe "};

char *ende[] = {"Mit freundlichen Grüssen\n\n\t",
"Es grüßt Sie \n\n\t",
"MfG ",
"cu ",
"Bis bald",
"Hasta la vista, Baby"};

static char yourname[30];

int main()
{
int c, i, z, x=1, spalten=0, zeilen=0;
char buffer[1000];

printf("An wen geht der Brief ?\n");
printf("-----------------------\n\n");
printf("\tName : ");
gets(Name);
printf("\tStrasse : ");
gets(Strasse);
printf("\tPLZ u. Ort : ");
gets(plzort);

printf("\n\nAnrede \n");
printf("------\n");
printf("-1-Er -2-Sie -3-Firma\n");
printf("-4-Bekannter -5-Freund -6-Freundin : ");
scanf("%d",&i);fflush(stdin);
printf("Dein Name : ");
gets(yourname);
printf("\n\n\n");

buffer[0]='\t';

while((c=getchar()) != '#')
{
spalten++;
/*Falls Newline aber in der Spalte noch keine 45 Zeichen*/
if(c=='\n' && spalten!=45)
c=' ';
/*Falls grössergleich 45 Spalten UND Leerzeichen, dann Newline*/
if(spalten>=45 && c==' ')
{
spalten=0;
c='\n';
}
/*Zeichen an buffer[] übergeben*/
buffer[x++]=c;
/*Falls Newline mit Tabulator einrücken*/
if(c=='\n')
buffer[x++]='\t';

}
for(z=0; z<20; z++) /*20xNewline*/
printf("\n");

printf("Anschrift:\n"); /*Es folgt Eingabe Anschrift*/
puts(Name);
puts(Strasse);
puts(plzort);

printf("\n\n%s %s\n\n",anrede[i-1],Name);

printf("%s",buffer);

printf("\n%s\n\n\t%s\n",ende[i-1],yourname);

return 0;
}

Dies Programm soll eine Art Briefvorlage darstellen. Sie brauchen lediglich Adresse, ihren Namen und die Umgangssprache auswählen und anschließend den Brief schreiben. Das Programm bringt dann Brief in sauberer Form auf dem Bildschirm. Bei der Umgangsprache haben wir unseren Zeiger auf ein Array. Die Eingabe für die Umgangsprache machen wir mittels...

printf("-1-Er -2-Sie -3-Firma\n");
printf("-4-Bekannter -5-Freund -6-Freundin : ");
scanf("%d",&i);fflush(stdin);


Die Ausgabe erfolgt dann mittels.....

printf("\n\n%s %s\n\n",anrede[i-1],Name);

und

printf("\n%s\n\n\t%s\n",ende[i-1],yourname);


Ich glaube dazu muss ich jetzt nichts mehr sagen oder? Es wird solange im Brieftext eine Eingabe erwartet bis sie das Zeichen '#' und ENTER drücken. Der Brieftext wird in unserem Array 'buffer[1000]' geschrieben mit 'buffer[x++]=c;'. Achtung unser Buffer hat nur Platz für 1000 Zeichen! Diesen geben wir mit 'printf("%s",buffer)' aus. Probieren sie an dem Programm ruhig etwas herum. Da sind noch viele Löcher in der Briefformatierung. z.B. Punkte, Kommas, Trennzeichen....können alleine am Anfang einer neuen Zeile stehen. Mit Zeiger auf Feldern können sie auch Fehlermeldungen auf dem Bildschirm ausgeben. Hier ein kleines Beispiel....

char *fehlermeldung[] = {
   "Keine Eingabe\n",
   "Zahl kleiner wie oder ist Null!!",
   "Wertbereichsüberschreitung!!\n",
   "Keine Zahl?\n",
   "Eingabe OK!\n",
   "Zu wenig Speicherplatz",
   "Zugriffe verweigert" };


Zugreifen könne sie auf die einzelnen Fehlermeldung mit dem Feldindex von Nr.[0] - [6]. Z.B 'Keine Zahl' ist 'fehlermeldung[4]'.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf