dynamische speicherreservierung fuer arrays
-
Hy!
also bin noch anfänger, bitte nicht gleich mit fach chinesisch auf mich zurennen!und auch nicht "das geht so viel einfacher... ", denn ich habe vorschriften von meinem prof die ich einhalten muss.
das problem ist, dass ich, sobald ich das programm kompiliere und ablaufen lassen will, kackt er einfach ab, und es kommt diese debug fehler meldung von windoof.
also ich poste einfach am besten noch die aufgabenstellung
Dynamischer Speicher
Realisieren Sie als Modul ein LIFO (Stack) für Strings mit folgender Schnittstelle:-> int push(char *string); speichert einen String; Ergebnis 0, wenn kein Speicherplatz
vorhanden (auf einem PC praktisch nicht möglich).
-> int empty(void); prüft, ob der Stack leer ist.
-> char *top(void); liefert den "obersten" (jüngsten) String. Erzeugt
Programmabbruch, wenn Stack leer.
-> int pop(void); beseitigt den "obersten" string; Ergebnis 0, wenn der Stack danach
leer ist. Kein Effekt, wenn er bereits vorher leer ist.
-> void clear(void); beseitigt alle Einträge.Der Stack soll mit einem dynamischen Array realisiert werden, der bei Bedarf in
Blöcken von 10 erweitert und ggf. auch wieder verkleinert wird. Jedes Arrayelement
ist vom Typ char * und zeigt auf einen dynamisch angelegten String passender
Größe. Man benötigt dazu einen Zeiger vom Typ char **, die Anzahl der Einträge und
die Kapazität des Arrays. Vergessen Sie nicht, bei pop() und clear() auch den
Speicher für die Strings freizugeben!das LIFO modul:
// lifo.c // #define _CRT_SECURE_NO_DEPRECATE #include <string.h> #include <malloc.h> #include <stdlib.h> #include <stdio.h> #include "lifo.h" #define BLOCK 10 char **pp_string = NULL; int count = 0; /* int push(char *string); speichert einen String; Ergebnis 0, wenn kein Speicherplatz vorhanden (auf einem PC praktisch nicht möglich). */ int push(char *string) { int ret = 1; if((count % BLOCK) == 0) { // 0, wenn alle Speicherplaetze bereits voll pp_string = (char **)realloc(pp_string, (count + BLOCK) * sizeof(char *)); // reserviert Speicherplatz fuer BLOCK neue Zeiger if(pp_string = NULL) // wenn NULL, dann Speicherplatz nicht vorhanden -> return 0 ret = 0; } pp_string[count] = (char *)malloc(1 + strlen(string)); // erstellt Speicherplatz fuer den uebergebenen String + /0 strcpy(pp_string[count], string); // kopiert uebergebenen String in Speicherplatz pp_string[++count] = NULL; // setzt Zeiger auf nächsten/letzten Speicherplatz, also NULL return ret; } /* int empty(void); prüft, ob der Stack leer ist. */ int empty(void) { // gibt 0 zurueck, wenn leer int ret; if(pp_string[0] == NULL) // prueft ob erster Speicherplatz leer ist ret = 0; else ret = 1; return ret; } /* char *top(void); liefert den "obersten" (jüngsten) String. Erzeugt Programmabbruch, wenn Stack leer. */ char *top(void) { if(empty() == 0) exit(0); else return(pp_string[count - 1]); } /* int pop(void); beseitigt den "obersten" string; Ergebnis 0, wenn der Stack danach leer ist. Kein Effekt, wenn er bereits vorher leer ist. */ int pop(void) { int ret; if(!(empty() == 0)) { if((count - 1) % BLOCK == 0) { free(pp_string[count]); } else pp_string[count - 1] = NULL; } if(empty() == 0) ret = 0; else ret = 1; return ret; } /* void clear(void); beseitigt alle Einträge. */ void clear(void) { if(!(empty() == 0)) for(--count; count > 0; count--) free(pp_string[count]); } char *get(int handler) { if(!empty()) { printf("Stack is empty ->exit\n"); exit(0); } return pp_string[handler]; }
das TESTPROGRAMM:
// main.c // #include <stdio.h> #include <stdlib.h> #include "lifo.h" int main (void) { int vLoop; int tmp; //Strings zuweisen if (!push ("Text1")) exit(0); if (!push ("Text2")) exit(0); if (!push ("Text3")) exit(0); if (!push ("Text4")) exit(0); if (!push ("Text5")) exit(0); if (!push ("Text6")) exit(0); if (!push ("Text7")) exit(0); if (!push ("Text8")) exit(0); if (!push ("Text9")) exit(0); if (!push ("Text10")) exit(0); if (!push ("Text11")) exit(0); //Testweise Abrufen der Strings printf("Abrufen aller Strings\n"); for (vLoop = 0; vLoop < 11; vLoop++) { printf ("%s\n",get (vLoop)); } getchar(); printf("Aufruf von top()\n"); printf ("%s\n",top()); getchar(); printf("Aufruf von pop()\n"); if (!pop()) printf("Stack is now empty\n"); else printf("Stack is not empty\n"); getchar(); //Testweise Abrufen der Strings printf("Abrufen aller Strings, auch den schon befreiten\n"); for (vLoop = 0; vLoop < 11; vLoop++) { printf ("%s\n",get (vLoop)); } getchar(); printf ("Erneutes beschreiben des letzen Platzes\n"); if (!push ("Text11: Erneutes beschreiben")) exit(0); printf("Abrufen aller Strings\n"); for (vLoop = 0; vLoop < 11; vLoop++) { printf ("%s\n",get (vLoop)); } getchar(); printf ("\nClear, beseitigen aller Einträge\n"); clear(); printf("Abrufen aller Strings\n"); if (!empty()) printf("Stack is now empty\n\n"); getchar(); printf ("Erneutes beschreiben des letzen Platzes\n"); if (!push ("Text1: Erneutes beschreiben")) exit(0); printf("Abrufen aller Strings\n"); for (vLoop = 0; vLoop < 1; vLoop++) { printf ("%s\n",get (vLoop)); } getchar(); return 0; }
Ich find einfach nix, und mit dem Debugger komm ich einfach noch nicht zurecht. Wenn er mir ja wenigstens ne Fehlermeldung beim Kompilieren ausspucken würde, aber so
Schonmal vielen vielen vielen Dank!
-
lifo.c, Zeile 26.
Außerdem sollst du den Rückgabewert von realloc nicht casten. Das hat aber nichts mit dem Fehler zu tun.
-
MFK schrieb:
Außerdem sollst du den Rückgabewert von realloc nicht casten.
... und überprüfen ob der 0 ist. bei 'malloc' ebenso.
-
Bezüglich malloc/realloc: http://www.c-plusplus.net/forum/viewtopic.php?t=206606
Ich habe den Code nur mal überflogen und kann dir den Bug auch nicht nennen, aber isoliere doch erstmal die Stelle an der es kracht (z.B. durch auskommentieren und sukzessives Entkommentieren). Debuggen lernen solltest du auf jeden Fall.
Ansonsten ein paar Dinge die mir auffallen:
#include <string.h> #include <malloc.h> #include <stdlib.h> #include <stdio.h>
malloc.h solltest du nicht einbinden müssen wenn du die stdlib.h eingebunden hast.
int push(char *string) { int ret = 1; if((count % BLOCK) == 0) { // 0, wenn alle Speicherplaetze bereits voll pp_string = (char **)realloc(pp_string, (count + BLOCK) * sizeof(char *)); // reserviert Speicherplatz fuer BLOCK neue Zeiger if(pp_string = NULL) // wenn NULL, dann Speicherplatz nicht vorhanden -> return 0 ret = 0; } pp_string[count] = (char *)malloc(1 + strlen(string)); // erstellt Speicherplatz fuer den uebergebenen String + /0 strcpy(pp_string[count], string); // kopiert uebergebenen String in Speicherplatz pp_string[++count] = NULL; // setzt Zeiger auf nächsten/letzten Speicherplatz, also NULL return ret; }
Hier überprüfst du zwar auf NULL, springst aber im Falle von NULL nicht direkt raus (sondern setzt nur ret) und würdest im Zweifelsfall eben jene NULL dereferenzieren. Das ist albern
int empty(void) { // gibt 0 zurueck, wenn leer int ret; if(pp_string[0] == NULL) // prueft ob erster Speicherplatz leer ist ret = 0; else ret = 1; return ret; }
Ich würde bei einer Funktion mit dem Namen "empty" erwarten, dass sie mir wahr zurückliefert wenn das Ding leer ist, und nicht umgekehrt.
Weiter hab ich nicht gelesen
-
Tim schrieb:
int empty(void) { // gibt 0 zurueck, wenn leer int ret; if(pp_string[0] == NULL) // prueft ob erster Speicherplatz leer ist ret = 0; else ret = 1; return ret; }
Ich würde bei einer Funktion mit dem Namen "empty" erwarten, dass sie mir wahr zurückliefert wenn das Ding leer ist, und nicht umgekehrt.
...und die könnte auch noch viel einfacher sein:
int empty (void) { return pp_string[0] == 0; }
bzw.
#define empty() (pp_string[0] == 0)
-
lifo-freak schrieb:
Tim schrieb:
int empty(void) { // gibt 0 zurueck, wenn leer int ret; if(pp_string[0] == NULL) // prueft ob erster Speicherplatz leer ist ret = 0; else ret = 1; return ret; }
Ich würde bei einer Funktion mit dem Namen "empty" erwarten, dass sie mir wahr zurückliefert wenn das Ding leer ist, und nicht umgekehrt.
...und die könnte auch noch viel einfacher sein:
int empty (void) { return pp_string[0] == 0; }
Ich könnte mir vorstellen, dass die explizitere Variante für einen Anfänger lesbarer ist. Das "Anfänger" kann man da fast sogar streichen. Und nach Compiler sollte das Ergebnis eh gleich aussehen.
lifo-freak schrieb:
bzw.
#define empty() (pp_string[0] == 0)
Oh, wieder mal ein Macro ohne Grund. Brav.
-
Tim schrieb:
Oh, wieder mal ein Macro ohne Grund. Brav.
stimmt. diesmal ist es wirklich doof, denn er müsste noch ein 'extern char **pp_string;' hinschreiben. also vergesst das mit dem makro.
-
MFK schrieb:
lifo.c, Zeile 26.
Außerdem sollst du den Rückgabewert von realloc nicht casten. Das hat aber nichts mit dem Fehler zu tun.
Danke danke!!! Super
DAs ganze ist jetzt zwar noch nicht fehlerfrei, aber es kann ausgeführt werden!zu der Funktion empty:
die pop() Funktion gibt schon 0 zurück, wenn der Stack leer ist, also hab ich das mit der empty Funktion genauso gemacht. Klar ist es eigentlich bescheuert, aber da liegt der "Fehler" schon bei meinem Prof. Aber auch wurst.Die ret / returns hab ich umgewandelt. dachte erst, man darf pro funktion nur ein return haben, egal ob mit if-cases verbaut und so.
vielen dank auf jedenfall. hoffe den rest bekomme ich jetzt auch noch hin!
-
Tim schrieb:
int push(char *string) { int ret = 1; if((count % BLOCK) == 0) { // 0, wenn alle Speicherplaetze bereits voll pp_string = (char **)realloc(pp_string, (count + BLOCK) * sizeof(char *)); // reserviert Speicherplatz fuer BLOCK neue Zeiger if(pp_string = NULL) // wenn NULL, dann Speicherplatz nicht vorhanden -> return 0 ret = 0; } pp_string[count] = (char *)malloc(1 + strlen(string)); // erstellt Speicherplatz fuer den uebergebenen String + /0 strcpy(pp_string[count], string); // kopiert uebergebenen String in Speicherplatz pp_string[++count] = NULL; // setzt Zeiger auf nächsten/letzten Speicherplatz, also NULL return ret; }
Hier überprüfst du zwar auf NULL, springst aber im Falle von NULL nicht direkt raus (sondern setzt nur ret) und würdest im Zweifelsfall eben jene NULL dereferenzieren. Das ist albern
Hier wird aber nicht auf NULL geprüft, sondern NULL zugewiesen.
Deshalb hat das Ganze wahrscheinlich auch nicht funktioniert:)}-Tux-{
-
}-Tux-{ schrieb:
Hier wird aber nicht auf NULL geprüft, sondern NULL zugewiesen.
Deshalb hat das Ganze wahrscheinlich auch nicht funktioniert:)Ha, total übersehen