Zum Inhalt springen

Dynamisches Zeiger-Array mit Zeigern auf Chararrays -> ich dreh durch!


Ferris

Empfohlene Beiträge

Hallo

Ich hab hier ein kleines Problem, dass mich langsam in den Wahnsinn treibt.

In dem Programm sollen Buchtitel erfasst werden, und zwar in einem dynamischen Array. Da die Buchtitel strings sind, brauche ich ein Array, was wieder Zeiger auf char-Arrays beinhaltet. Solange ich das ganze in main mache, gibt es auch keine Probleme.

Das Programm ist ANSI-C, nur die Kommentare sind C++.


#include<stdio.h>

#include<string.h>

#include<stdlib.h>


int main(void){


  char** pt_pt_Buecher;

  char Temp[30];

  int Index = 0;


  //....bla

  scanf("%s", Temp);

  if(Index==0){

    pt_pt_Buecher=(char**)malloc(1*sizeof(char*));

  }

  else{

    pt_pt_Buecher=(char**)realloc(pt_pt_Buecher, (1+Index)*sizeof(char*));

  }

  *pt_pt_Buecher=(char*)malloc((strlen(Temp)+1)*sizeof(char));

  strcpy(*pt_pt_Buecher[Index], Temp);

  Index++;


   //...bla


   return 0;

}
Jetzt will ich aber die Buchtiteleingabe und Speicherallozierung in einer Funktion haben und übergebe das Array und den Index an die Funktion.

void input_record(char ***Buch, int Index){


   char Temp[30];



   scanf("%s", Temp);

   if(Index==0){

     *Buch=(char**)malloc(1*sizeof(char*));

   }

   else{

     *Buch=(char**)realloc(*Buch, (1+Index)*sizeof(char*));

   }

   **Buch=(char*)malloc((strlen(Temp)+1)*sizeof(char));

   strcpy(*Buch[Index], Temp);

}


int main(void){


  char** pt_pt_Buecher;

  char Temp[30];

  int Index = 0;


  //...bla

  input_record(&pt_pt_Buecher, Index);

  Index++;

  //...bla

}

Wenn ich hier nun den ersten string erfasse, funktioniert auch alles. Beim zweiten string funktioniert auch noch die Zeile mit realloc, das daruffolgende malloc allokiert den Speicher jedoch nicht an der Stelle, wo ich will und strcpy kopiert meinen temporären string ins Nirvana.

Wo ist der Haken???

Danke und Gruss

Ferris

[ 28. März 2001: Beitrag editiert von: Ferris ]

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo maddin

Ich habe Deinen Vorschlag mal aufgegriffen und meine Buchtitel in eine einfach verkettete Liste gepackt.


#include<stdio.h>

#include<stdlib.h>

#include<ansi_c.h>


struct Daten{

  char Titel[30];

  struct Daten *Next;

};


struct Daten *First;



//Funktionsprototypen

void Satz_anfuegen(char*);



int main(void){


  char Temp[30];


  //....

  scanf("%s", Temp);

  Satz_anfuegen(Temp);

  //...


  return 0;

}



void Satz_anfuegen(char Temp[]){


   struct Daten *pt_Temp;


   if(First==NULL){

     First = malloc(sizeof(*First));

     strcpy(First->Titel, Temp);

     First->Next = NULL;

   }

   else{

     pt_Temp = First;

     while(pt_Temp->Next != NULL){

       pt_Temp = pt_Temp->Next;

     }

     pt_Temp->Next = malloc(sizeof(*pt_Temp));

     pt_Temp = pt_Temp->Next;

     strcpy(pt_Temp->Titel, Temp);

     pt_Temp->Next = NULL;

   }

 }

Was mich bei der Sache stört ist, dass meine Struktur und der Strukturzeiger First global sind. Eine andere Möglichkeit habe ich bisher jedoch nicht gefunden.

Wenn ich meine Struktur und den Struktur zeiger in main deklariere, kann ich den Strukturzeiger nicht an eine Funktion übergeben, weil es ihn ja praktisch noch garnicht gibt.

Muss ich erst einmal eine leere Struktur initialisieren oder gibt es da vielleicht doch eine andere Möglichkeit?

Hat da jemand ne Idee?

Gruss

Ferris

[ 29. März 2001: Beitrag editiert von: Ferris ]

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich habe es normalerweise immer so gemacht, das ich eine struktur liste erstellt habe und darin einen zeiger auf das erste listenelement hatte. den funktionen müssen dann allerdings noch die liste übergeben bekommen.

dadurch ist der zeiger nicht mehr global.

ps: ich hatte auch noch irgendwo den code, ich weiß bloß nicht mehr genau wo. ich kann ja mal suchen wenn du willst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hatte zwar leider keine Zeit mich länger mit dem Problem zu beschäftigen, aber könntest du die Struct def. und den First pointer nicht lokal als Static deklarieren? Denn außerhalb der anfuegen funktion wird die Struktur ja nicht verwendet. Und bei jedem Funktionsaufruf hätte der First pointer auch wieder den selben wert (Anfang der Liste.) Und nur weil die Struktur in main unbekannt ist, ändert sich ja nichts an der Datenspeicherung, so daß in der anfuegen funktion alles beim alten wäre.

Grüße Ketzer

p.s. Warum ab dem 2. Mal realloc?

Zum suchen etc. habe ich schon oft im nach hinein gemerkt das ein previous pointer manchmal hifreich ist, aber wenig mehr aufwand verursacht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

das problem ist, das man den zeiger auf das erste element immer brauch, wenn man auf die liste zugreifen will. also nicht bloß bei der funktion zum anfügen sondern auch bei vielleicht noch folgenden funktionen zum suchen oder, oder ...

ps: ich habe die erfahrung gemacht, das zum suchen ein baum eine sehr gute wahl ist. und der macht auch bloß geringfügig mehr arbeit.

pps: meine zweite erfahrung ist, das es am allereinfachsten ist die stl zu verwenden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

ich habe meine code zwar nich mehr gefunden, aber ich hab mal deinen überarbeitet:


struct Daten

{

  char Titel[30];

  struct Daten *Next;

};


typedef struct Liste

{

  struct Daten First;

}Liste;


//Funktionsprototypenvoid

Satz_anfuegen(Liste*, char*);


int main(void)

{

  char Temp[30];

  Liste* p_list = (Liste*) malloc (sizeof (Liste) );

  p_list->First = NULL;

  //....

  scanf("%s", Temp);

  Satz_anfuegen(list, Temp);

  //...  return 0;

}

void Satz_anfuegen(Liste* list char Temp[])

{

    struct Daten *pt_Temp;

    if(list->First==NULL)

    {

     list->First = malloc(sizeof(*First));

     strcpy(list->First->Titel, Temp);

     list->First->Next = NULL;

    }

    else

    {

      pt_Temp = list->First;

      while(pt_Temp->Next != NULL)

      {

        pt_Temp = pt_Temp->Next;

      }

      pt_Temp->Next = malloc(sizeof *pt_Temp));

      pt_Temp = pt_Temp->Next;

      strcpy(pt_Temp->Titel, Temp);

      pt_Temp->Next = NULL;

    }

 }

dadurch verschwindet der globale zeiger auf die daten.

[ 30. März 2001: Beitrag editiert von: maddin ]

Link zu diesem Kommentar
Auf anderen Seiten teilen

<BLOCKQUOTE><font size="1" face="Verdana, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von Ketzer:

Ich hatte zwar leider keine Zeit mich länger mit dem Problem zu beschäftigen, aber könntest du die Struct def. und den First pointer nicht lokal als Static deklarieren? Denn außerhalb der anfuegen funktion wird die Struktur ja nicht verwendet. Und bei jedem Funktionsaufruf hätte der First pointer auch wieder den selben wert (Anfang der Liste.) Und nur weil die Struktur in main unbekannt ist, ändert sich ja nichts an der Datenspeicherung, so daß in der anfuegen funktion alles beim alten wäre.

Link zu diesem Kommentar
Auf anderen Seiten teilen

malloc Vs. realloc:

Nein die daten gehen definitiv nicht verloren. Sonst hätte keine meiner Listen funktioniert. Durch ein 2. aufrufen von malloc bekommst du lediglich einen zweiten Speicherbereich zugewiesen, der völlig unabhängig von ersten ist.

keine Global Variablen:

Also die struktur definition würde ich eigendlich in eine eigene *.h packen, allerdings lohnt sich dies bei dem begrenzten Umfang der Sruktur wohl nicht so.

 main()

{

DATEN *First;

anfuegen(temp,First);

}

Durch die Übergabe den Pointers, braucht dieser nicht mehr Global zu sein.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo maddin

Ich werde aus Deinem code nicht so ganz schlau. :)

An zwei Stellen meckert auch der compiler.

Das eine war wohl nur ein Tipfehler.

Satz_anfuegen(list, Temp);

sollte wohl

Satz_anfuegen(p_list, Temp); heissen

Aber die Zuweisung:

p_list->First = NULL;

kann irgendwie nicht gehen. Wenn ich das richtig verstehe ist doch First selbst eine Struktur vom Typ Daten in einer Struktur vom Typ Liste. Kann ich NULL an eine Struktur zuweisen? Mein compiler sagt ne. In der Funltion selber bekomme ich die gleiche Fehlermeldung. Ich probiers weiter...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo Ketzer

Wenn ich in meinem code ganz oben das realloc durch malloc ersetze sind die Daten bei mir futsch. Wahrscheinlich weil ich dann das malloc auf *Buch anwende und *Buch immer gleich ist.

Da müsste dann wohl auch über einen Index gehen. Werde ich nachher auch mal ausprobieren, bin aber jetzt erstmal zwei Stündchen in der Stadt, mein neues C++ Buch abholen. Urlaub ist schon was feines. :)

Mit Stroustrup hatte ich mich wohl etwas übernommen und das Buch finde ich auch zu chaotisch und nicht gerade geeignet für den Einstieg in C++.

PS: Kann es sein, dass es Standard ist, so eine Struktur für eine Liste global zu halten? In allen Büchern, die ich hab ist das nämlich so.

Link zu diesem Kommentar
Auf anderen Seiten teilen

ohh,

der stern macht es aus. die struktur Liste

sollte keine struktur vom typ Daten enthalten sondern einen zeiger auf eine Struktur von typ daten. dann sollte das aber zumindest gehen. den ersten fehler hast du ja schon richtig erkannt. so ist das halb, wenn man zu faul ist den sch*** selber zu machen und sich code kopiert

Link zu diesem Kommentar
Auf anderen Seiten teilen

<BLOCKQUOTE><font size="1" face="Verdana, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von Ketzer:

malloc Vs. realloc:

Nein die daten gehen definitiv nicht verloren. Sonst hätte keine meiner Listen funktioniert. Durch ein 2. aufrufen von malloc bekommst du lediglich einen zweiten Speicherbereich zugewiesen, der völlig unabhängig von ersten ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

das wäre nicht nur sehr umständflich sondern aúch sehr unklug, da mir jetzt kein weg einfallen würde, wie man etwas unbekannter übergeben soll. beipiel:


void funktion (struct Struktur* pt)

{

  struct Struktur

  {

    // ...

  }

  // ...

}

die funktion bekommt zwar einen zeiger auf eine struktur übergeben, kennt die struktur aber noch nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Original erstellt von Ferris:

<STRONG>Ich hab mir das nochmal durch den Kopf gehen lassen. :) Du sprichst jetzt von Listen. Mein erstes Beispiel war aber keine Liste sondern ein dynamisches Array. Und da muss ich realloc nehmen. Den Rückgabewert von malloc an das Array über Index zurückgeben, so wie ich mir das dann vorgestellt hab, kann auch nicht gehen, da es diesen Teil des Arrays ja noch garnicht gibt. </STRONG>

Oh, sorry. Nach dem im 2. Code Segment von Verkettentenlisten "gesprochen" wurde, habe ich dem obigen Beispiel keine Beachtung mehr geschenkt. Ich hatte mich schon gefragt welche Daten dir bei der Liste abhanden kommen können!?!?! Denn eigendlich fordert man ja nur neuen Speicherplatz an. Und da dort noch nix steht kann auch nix gelöscht werden.

Alles lokal: Doch das geht

void was_weiss_ich(void *first)

{

struct blabla {}

//Anschließender Typecast auf Typus "struct blabla"

}

Grüße Ketzer

p.s. Wobei ich die Struktur nicht lokal halten würde, da sie logisch nicht lokal ist.

(Wird halt nicht nur in einer Funktion benutzt)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...