Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C Speicherzugriffsfehler bei verketteter Liste (https://www.delphipraxis.net/155356-c-speicherzugriffsfehler-bei-verketteter-liste.html)

Hybrid666 20. Okt 2010 08:49

C Speicherzugriffsfehler bei verketteter Liste
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich muss für mein info II Labor eine Aufgabe bearbeiten, bei der Daten in eingelesen werden, in eine einfach verkettete liste gespeichert werden sollen, in eine Binärdatei geschrieben werden sollen, liste soll gelöscht werden und aus der Datei neu aufgebaut werden.

Das Einlesen funktioniert, die Daten werden erfolgreich ausgegeben (also sind wirklich in der liste), die Datei wird korrekt gespeichert und die liste wird erfolgreich gelöscht. Nur beim einlesen der Datei gibt es probleme.

Hier erstmal alle Dateien:

malloc1.c:
Code:
/* Dateiname: malloc1.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "prodlist.h"
#include "prodinfo.h"


int main (void)
{
   int anzahl, count;
   char buffer [20];
   ProdListe * liste;
   ProdInfo * temp;
   initListe (&liste);
   printf ("Anzahl der Produkte: ");
   fgets (buffer, 19, stdin);
   sscanf (buffer, "%i", &anzahl);
   for (count = 0; count < anzahl; count++) {
      einfuegenListe (&liste, einlesenProdukt ());
   }
   SaveList ("DATA.DAT", liste);
   while ((temp = naechstesProdukt (&liste)) != NULL) {
      ausgebenProdukt (temp);
   }
   KillList (&liste);
   initListe (&liste);
   ReadList ("DATA.DAT", &liste);
   while ((temp = naechstesProdukt (&liste)) != NULL) {
      ausgebenProdukt (temp);
   }
   return 0;
}
prodinfo.h:
Code:
#ifndef PRODINFO_H_

#define PRODINFO_H_

typedef

    struct prodinfo { char name [20];

                      double preis;

    }

ProdInfo;

#endif



void ausgebenProdukt (ProdInfo * prod);

/* Ausgeben der Produktinformation am Bildschirm */



ProdInfo * einlesenProdukt (void);

/* Einlesen der Produktinformation,

   Beschaffen von Speicher für die Info

   und Rueckgabe eines Zeigers auf die Info */
prodinfo.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "prodinfo.h"

ProdInfo * einlesenProdukt (void) {
   ProdInfo * new;
   char buffer [100];
   new = malloc (sizeof (ProdInfo));
   printf ("Bitte Produktnamen eingeben: ");
   fgets (new->name, 19, stdin);
   printf ("Bitte Preis eingeben: ");
   fgets (buffer, 99, stdin);
   sscanf (buffer, "%lf", &new->preis);
   return new;
}

void ausgebenProdukt (ProdInfo * prod) {
   printf ("Produktname: %sPreis: %lf\n", prod->name, prod->preis);
}
prodlist.h:
Code:

#include "prodinfo.h"



#ifndef PRODLIST_H_

#define PRODLIST_H_

typedef

    struct prodliste {

        ProdInfo * info;

        struct prodliste * next;



    } 

ProdListe;

#endif  

    void initListe (ProdListe ** liste);

    /* Angegebene Liste wird initialisiert mit NULL */

 

    void einfuegenListe (ProdListe ** liste, ProdInfo * produkt);

    /* Angegebenes Produkt wird in die gegebene Liste eingefuegt */



    ProdInfo * naechstesProdukt (ProdListe ** liste);

    /* Das naechste Produkt in der Liste wird zurueckgegeben,

       die Liste wird fortgeschaltet, so dass sie jetzt auf die

       Restliste ohne das zurückgegebene Element zeigt

    */

     

   void SaveList (char * FileName, ProdListe * liste);

   void ReadList (char * FileName, ProdListe ** liste);

   void KillList (ProdListe ** liste);
prodlist.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "prodlist.h"
#include "prodinfo.h"

static ProdListe * pos;

void initListe (ProdListe ** liste) {
   *liste = NULL;
   pos = NULL;
}

void einfuegenListe (ProdListe ** liste, ProdInfo * produkt) {
   ProdListe * ref;
   if (*liste == NULL) {
      *liste = malloc (sizeof (ProdListe));
      (*liste)->next = NULL;
      (*liste)->info = produkt;
      pos = *liste;
   } else {
      ref = *liste;
      while (ref->next != NULL) { ref = ref->next; }
      ref->next = malloc (sizeof (ProdListe));
      ref->next->next = NULL;
      ref->next->info = produkt;
   }
}

ProdInfo * naechstesProdukt (ProdListe ** liste) {
  ProdInfo * res;
  if (pos != NULL) {
    res = pos->info;
    pos = pos->next;
    return res;
  } else { return NULL; }
}

void SaveList (char * FileName, ProdListe * liste) {
   FILE * fp;
   ProdListe * ref;
   fp = fopen (FileName, "wb");
   ref = liste;
   while (ref != NULL) {
      fwrite ((*ref).info, sizeof (ProdInfo), 1, fp);
      ref = ref->next;
   } 
   fclose (fp);
}

void ReadList (char * FileName, ProdListe ** liste) {
  FILE * fp;
  ProdInfo * r;
  KillList (liste);
  *liste = NULL;
  fp = fopen (FileName, "rb");
  while (fread (r, sizeof (ProdInfo), 1, fp) > 0) {
    //printf ("\n\n%s%lf", r->name, r->preis);
    einfuegenListe (liste, r);
  }
  fclose (fp);
}

void KillList (ProdListe ** liste) {
  if (*liste != NULL) {
    if ((*liste)->next != NULL) { KillList (&(*liste)->next); } 
    free ((*liste)->info);
    free ((*liste));
    *liste = NULL;
  }
}
ich habe rausgefunden, das in der ReadFile Routine der Speicherzugriffsfehler beim aufruf von einfuegenListe auftritt. Aber warum? das einfügen hat davor ja auch funktioneirt und die liste sollte beim aufruf von readfile komplett leer (=NULL) sein.

Wäre echt super wenn da jemand was zu sagen könnte (auch wenns nur ideen sind warum es nicht geht).
Compilen tut das ganze ohne probleme. Und der bequemlichkeit halber von euch lade ich die sourcefile in den Anhang hoch, so müsst ihr falls ihrs probieren wollt nichtmehr kopieren und einfügen ;).

Ach und bitte nichts über funktionsnamen, etc meckern, die sind vorgegeben (ich bin auch nicht zufrieden), ebenso wie die Prototypen in den .h files (die sind auch vorgegeben).

Bin für jede hilfe dankbar!

hybrid666


EDIT:

also ich habe nun mal die einfuegenListe so editiert:
Code:
void einfuegenListe (ProdListe ** liste, ProdInfo * produkt) {
   ProdListe * ref;
   if (*liste == NULL) {
      printf ("Liste ist NULL\n");
      *liste = malloc (sizeof (ProdListe));
      printf ("Speicher allokiert...\n");
      (*liste)->next = NULL;
      printf ("Naechstes Element genullt\n");
      (*liste)->info = produkt;
      printf ("Info auf Produkt gesetzt\n");
      pos = *liste;
      printf ("pos gesetzt\n");
   } else {
      printf ("liste nicht NULL\n");
      ref = *liste;
      printf ("ref auf liste gesetzt!\n");
      while (ref->next != NULL) { ref = ref->next; }
      printf ("schleife durchgelaufen\n");
      ref->next = malloc (sizeof (ProdListe));
      printf ("speicher allokiert\n");
      ref->next->next = NULL;
      printf ("next genullt\n");
      ref->next->info = produkt;
   }
}
Das Programm stürzt ab, da es bei ReadFile beim aufruf von einfuegen liste die liste, die durch initliste genullt wurde, als nicht Null erkennt, sofort in die else bedingung läuft und dann bei der while schleife abstürzt (ist klar, da next ja nciht existiert!). Aber warum ist die liste nicht null? ich hab sie sogar vorsichtshalber in der readfile funktion genullt (*liste = NULL).
Ich weiß nimmer weiter...


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:42 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz