Dynamische Speicherverwaltung - realloc Problem

paul10

Mitglied
Hallo,
Ich muss ein Programm für die Schule schreiben.
Dabei funktioniert auch alles soweit.

Nur wenn ich mehr als 1 Element hinzufüge bekomme ich leider nur Fehler :(
Ich habe schon einiges probiert und auch schon einige Tutorials gelesen, hat mir leider nicht weiter
geholfen.

Das Programm verwaltet ein Adressebuch:
Code:
#include <stdlib.h>
// Wird für Ein/Ausgabe gemacht
#include <stdio.h> 
#include <string.h>

/**
  * Im struct ADDRESS wird die Adresse der Person gespeichert.
  */
typedef struct{
	int plz;
	int hausNr;
	char strasse[100];
	char ort[100];
}ADDRESS;

/**
  * Im struct PERSON werden die Daten zur Person gespeichert. Zudem wird noch ein ADDRESS struct gespeichert
  * 
  */
typedef struct{
	int id;
	char vorname[50];
	char nachname[100];
	char telefon[50];
	ADDRESS ad;
}PERSON;

// Prototypendefinition
int del(PERSON *pr, int psize);
int add(PERSON *pr, int psize);
int ls(PERSON *pr, int psize);

/**
  * In der Main-Methode wird dem Benutzer anzeigt was er zu tun hat,  die Werte zu berechnen eingelesen und die entsprechenden Methoden werden aufgerufen.
  *
  * @param argc Anzahl der Parameter die übergeben wurde
  * @param argv Char-Array in dem die übergebenen Parameter stehen
  */
int main( int argc, char** argv )
{
	char c,x;
	// Speicher für die Daten wird reserviert
	PERSON *ipoint = (PERSON*)malloc(1*sizeof(PERSON));

	int psize = 0;
	
	// Konnte kein Speicher reserviert werden, dann wird das Programm abgebrochen
	if( ipoint == NULL)
	{
		printf("Fehler bei Speicherreservierung!\n");
		return -1;
	}
	
	printf("Willkommen zu meinem Adressbuch-Verwaltungsprogramm!\n\n");
	printf("Wollen Sie loeschen(d), neuer Eintrag(n), eintraege Listen(l) oder Programm beenden(e)\n");
	scanf("%c", &c);

	// Schleife die solange läuft, wie der Benutzer Daten eingeben will.
	do{
		// Dementsprechend, was der Benutzer eingegeben hat, wird in der switch-case entschieden
		switch( c )
		{
			case 'd':
				psize = del(ipoint, psize);
				break;
			case 'n':
				psize = add(ipoint, psize);
				break;
			case 'l':
				ls(ipoint, psize);
				break;
			case 'e':
				return 1;
			default:
				printf( "Falsche Eingabe!!\n" );
		}

		// Benutzer wird nach einer Eingabe gefragt
		printf("Wollen Sie loeschen(d), neuer Eintrag(n), eintraege Listen(l) oder Programm beenden(e)\n");
		scanf("%c", &c);
		fflush(stdin);
	}while(c != 'e' ); // do-While Schleife für nochmal berechnen

	return 1;
}

/**
  * In der Funktion del kann ein Struct gelöscht werden. Dazu wird dem Benutzer die ID des jeweiligen Eintrages gezeigt.
  * Durch Eingabe der ID, kann das Element dann anschließen gelöscht werden.
  */
int del(PERSON *pr, int psize)
{
	int c, i=0,x;
	fflush(stdin);
	printf("\nWelchen Eintrag wollen Sie löschen?\n");

	// Elemente werden dem Benutzer angezeigt
	for(;i < psize; i++)
	{
		printf("\n------------------------\n");
		printf("ID: %d\n", pr[i].id);
		printf("Nachname: %s\n", pr[i].nachname);
		printf("Vorname: %s\n", pr[i].vorname);
		printf("------------------------\n");
	}
	// ID wird vom Benutzer eingefragt.
	printf("\n***\nBitte ID eingeben:");
	scanf("%d", &x);
	fflush(stdin);

	// Wenn Eingabe im Wertebereich war.
	if( x <= psize)
	{
		// entsprechendes Element wird gelöscht
		free(pr+x);
	}

	psize--;
	return psize;
}

/**
  * In der Methode add kann ein neues Element hinzugefügt werden
  */
int add(PERSON *pr, int psize)
{
	char c[100];
	int x;
	// Speicher für ein weiteres Element wird reserviert
	pr = (PERSON*)realloc( pr, (psize+1) * sizeof(PERSON));

	// Ist die Speicherreservierung fehlgeschlagen, dann wird die Methode beendet
	if( pr == NULL )
		return -1;

	// id wird psize zugewiesen
	pr[psize].id = psize;

	// Die Daten für die Person werden vom Benutzer eingelesen
	printf("Nachname: ");
	scanf("%s", &c);
	fflush(stdin);
	strcpy(pr[psize].nachname, c);
	
	printf("Vorname: ");
	scanf("%s", &c);
	fflush(stdin);
	strcpy(pr[psize].vorname, c);

	printf("Telefonnummer: ");
	scanf("%s", &c);
	fflush(stdin);
	strcpy(pr[psize].telefon, c);
	
	printf("Ort: ");
	scanf("%s", &c);
	fflush(stdin);
	strcpy(pr[psize].ad.ort, c);

	printf("Strasse: ");
	scanf("%s", &c);
	fflush(stdin);
	strcpy(pr[psize].ad.strasse, c);

	printf("Hausnummer: ");
	scanf("%d", &x);
	fflush(stdin);
	pr[psize].ad.hausNr = x;

	printf("PLZ: ");
	scanf("%d", &x);
	fflush(stdin);
	pr[psize].ad.plz = x;

	// Ein Element mehr->psize wird um 1 erhöht
	psize = psize +1;
	return psize;
}

int ls(PERSON *pr, int psize)
{
	int i=0;

	// Wurde noch kein Element hinzugefügt, bzw. alle bestehenden gelöscht
	if( psize == 0 )
	{
		printf("\n\nNO ELEMENTS IN STRUCT!\n");
		return -1;
	}

	// Existieren noch Elemente, dann werden diese ausgegeben
	printf("\n\nLISTE DER ELEMENTE:\n %d", psize);

	for(;i < psize; i++)
	{
		printf("------------------------\n");
		printf("\tID: %d\n", pr[i].id);
		printf("\tNachname: %s\n", pr[i].nachname);
		printf("\tVorname: %s\n", pr[i].vorname);
		printf("\tTelefonnummer: %s\n", pr[i].telefon);
		printf("\tOrt: %s\n", pr[i].ad.ort);
		printf("\tStrasse: %s\n", pr[i].ad.strasse);
		printf("\tHausnummer: %d\n", pr[i].ad.hausNr);
		printf("\tPLZ: %d\n", pr[i].ad.plz);
		printf("------------------------\n");
	}

	return 1;
}

Ich würde mich über eine schnelle Antwort freuen
und bedanke mich schon ganz herzlich im vorraus******

MfG
 
Zuletzt bearbeitet:
So hab ich jetzt probiert mit
PERSON *ipoint = (PERSON*)malloc(1*sizeof(PERSON));

jetzt ist es möglich ein Element hinzuzufügen
reserviere ich mir dann aber mit realloc für das nächste Element Speicher, dann dürfte ich wieder
auf die falsche Speicherstelle zugreifen :(

mfg

und zum Debugger: Das Programm wird nicht unterbrochen, erst bei der Funktion ls wird dann einfach nur Blödsinn ausgegeben...
 
Zuletzt bearbeitet von einem Moderator:
Hi.
NULL und malloc(0*...) ist nicht das Gleiche.
malloc darf NULL zurückgeben wenn als Argument 0 angegeben wurde. Oder es gibt einen Zeiger auf 0 Bytes Speicher zurück...

Aber warum sollte man eine Person anlegen, wenn man überhaupt keine Daten hat? Initialisiere doch einfach ipoint mit NULL - dafür brauchst du doch keine Funktion aufrufen...

@paul10: Geh doch im Debugger einfach Zeile für Zeile durch und schau dir genau an was passiert. So groß ist dein Programm doch nicht...

\edit: Hab mir dein Programm mal näher angeschaut.

Bemerkungen:
C:
  printf("Nachname: ");
  scanf("%s", &c);
  fflush(stdin);
  strcpy(pr[psize].nachname, c);
Erstmal ist fflush auf Eingabeströme nicht definiert. (http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351)

Von statischen Array kann man keine Adresse ermitteln. Deswegen verwendet man den & Operator nicht bei Arrays (bei dem c). (ich erhalte eine Warnung weil das Format und der Typ nicht passt)

Und warum machst du das so kompiliziert? Lies doch einfach den Wert direkt in die Struktur ein.

Außerdem hast du keine Fehlerprüfung gemacht. Du solltest psize nur inkrementieren wenn auch alle Werte korrekt eingelesen wurden.

Dann übergibst du den Funktionen add und del eine Kopie des Zeigers ipoint. D.h. nachdem die Funktion zurückgekehrt ist, ist der Wert des Zeigers ipoint unverändert. Du müßtest die Adresse von ipoint übergeben (einen Zeiger auf den Zeiger), damit der Wert in der Funktion geändert werden kann.
C:
int add(PERSON **ppr, int psize) {
  ...
}

add(&ipiont, psize);

Die del Funktion ist noch komplett falsch. Erstens darf x nicht <= psize sein, sondern muß echt kleiner sein. Dann kannst du nicht einfach ein beliebiges Element mit free löschen. Du mußt vielmehr alle Elemente die hinter dem zu löschenden Eintrag stehen um 1 Position nach links schieben (siehe memmove).

Gruß
 
Zuletzt bearbeitet:
Zurück