Stapel => push
-
Hi Leute!
Also wir haben bei uns nun Stack's bzw. Stapel eingeführt. Das gesamte Prinzip ist logisch und leicht und das freut natürlich jeden, der zum Ersten mal damit in Kontakt kommt.
Wir sollen nun ein Programm schreiben, wo wir Zahlen auf den Stapel tun, Elemente löschen, neue Stapel erstellen ect.
Das Problem: Ich weiß nicht, wie ich in diesem Programm beispielsweise die anweisung "push" aufschreuiben soll. Ich nahm mir auch als Beispiel den Code auf dieser URL:
http://www.cplusplus.com/reference/stl/stack/push.html
und habe versucht, es in mein Programm zu implementieren, doch irgendwie bekam ich immer nur Fehler.
Deswegen die Frage, ob mir jemand sagen könnte, wie das in meinem Programm auszusehen hat und warum in dieser Art und Weise?? Wäre echt Cool, da noch einige weitere Stapel-Programme gemacht werden müssen.#include <stdio.h> #include <stack> #include <stdlib.h> struct TStackA { void** info; int maxGroesse; int pos; }; TStackA push(void* info, TStackA oldStack) { } /********************************************************************** ********* * Das Ein-/Ausgabeverhalten der main-Funktion darf nicht verändert werden. * e <Enter> beendet das Programm. * p <Zahl> <Enter> speichert <Zahl> auf dem Stapel. *********************************************************************** ********/ int main(int argc, char* argv[]) { int* val; char command[8]; TStackA stack; stack = create(); while(*command != 'e') { printf("cmd? "); scanf("%s",command); switch(*command) { case 'p' : val = (int*)malloc(sizeof(int)); printf("val? "); scanf("%d",val); stack = push(val,stack); break; } } }
_____
Legende:
info -> Zeiger auf ein eindimensionales Feld, das bei der Erzeugung
des Stapelspeichers durch create Platz für 10 Einträge bieten soll.maxGroesse -> speichert die maximale Anzahl der Einträge, die im Feld
info gespeichert werden können – zu Beginn also 10
pos -> Position des letzten auf dem Stapelspeicher abgelegten
Elements im Feld info.
_____MFG Majin_Clodan
-
Sieht mir eher nach C als C++ aus (
void*
-> *schauder*)...Wie hast du denn deinen Stack implementiert? Als Array, als verkettete Liste? Du musst einfach am Ende noch ein Element anhängen. Also bei einer Liste ein neues erstellen und den Zeiger darauf im Stack speichern, bei einem Array wenn notwendig den gesamten Bereich reallokieren.
-
Öhmmm...
KP.^^Der Code, den ihr hier seht, sind Vorgaben, die wir verwenden müssen.
Das Zahlenelement, welches auf den Stapel gelegt wird, ist nur eine normale Variable d.h.:
int* val;
=> ohne ArrayDort ,wo es raufgelegt werden soll, ist:
stackAnsonsten habe ich nicht so viel verstanden, was du geschrieben hast.^^'
MFG Majin_Clodan
-
Dein Code ist bis auf
#include <stack>
reinstes C und nicht C++. Deshalb schaudert mich auchvoid*
, da man das in C++ kaum jemals braucht, und wenn, dann wirklich nur, um Speicheradressen ohne Typ zu speichern.Naja, ich habe dich nach der Datenstruktur gefragt, die dem Stack zugrunde liegt. Da gibt es nämlich mehrere Möglichkeiten, und zwei davon sind dynamisches Array oder verkettete Liste.
Ich vermute zwar, du benutzt ein Array. Trotzdem kann ich dir gerade nicht weiterhelfen, und zwar weil ich zu wenig weiss. Zum Beispiel, wofür stehen die Member des
TStackA
-Structs (besonders dervoid
-Zeiger)? Wie hängt dieser mit einemint*
, den du pushen willst, zusammen? Wie soll der Stack nachher aussehen?
-
Also die Member der Struktur stand in meinem ersten Post in der Legende:
info -> Zeiger auf ein eindimensionales Feld, das bei der Erzeugung
des Stapelspeichers durch create Platz für 10 Einträge bieten soll.maxGroesse -> speichert die maximale Anzahl der Einträge, die im Feld
info gespeichert werden können – zu Beginn also 10
pos -> Position des letzten auf dem Stapelspeicher abgelegten
Elements im Feld info.Und damit vieleicht nicht noch irgendwelche Informationen fehlen, poste ich mal die gesamte aufgabe(für den Fall der Fälle!):
info ist ein Zeiger auf ein eindimensionales Feld, das bei der Erzeugung des Stapelspeichers durch create Platz für 10 Einträge bieten soll. Jeder Eintrag bietet Platz für einen Zeiger (void*) auf die gespeicherte Information.
maxGroesse speichert die maximale Anzahl der Einträge, die im Feld info gespeichert werden können – zu Beginn also 10.
pos ist die Position des letzten auf dem Stapelspeicher abgelegten Elements im Feld info.
Falls bereits die maximale Anzahl möglicher Elemente im Feld info gespeichert ist, dann soll beim Speichern eines weiteren Elements durch push ein um 50% größeres Feld info erzeugt werden, das die bisher gespeicherten Elemente und das neu zu speichernde Element aufnimmt.
Mehr Informationen habe ich auch nicht d.h. mehr kann ich auch nicht sagen.
MFG Majin_Clodan
-
Tut mir leid, das habe ich irgendwie übersehen. Aber dass
info
auf irgendeine Information zeigen soll, von der man nicht weiss, was sie für einen Typ hat, finde ich trotzdem merkwürdig. Deshalb bin ich auch kritisch gegenübervoid*
. Aber da es hier wahrscheinlich eher um das grundsätzliche Prinzip geht, kann ich das noch verstehen (auch wenn es meines Erachtens eine schlechte Aufgabestellung für einen Anfänger ist).Also, du willst das wahrscheinlich in C programmieren (oder gibt sich die Aufgabenstellung als C++ aus? - Ich hoffe nicht.)
Jetzt hast du dein Array (Feld) mit anfangs 10 Einträgen. Beim Aufruf von
push()
wird nun der erste Eintrag geschrieben und die Positionpos
um eins nach vorne verschoben. Zudem solltest du nicht jedes Mal einen neuen Stack erstellen, sondern den bestehenden modifizieren. Dazu übergibst du einen Zeiger, also ungefähr:void push(void* new_info, TStackA* stack) // Stack als Zeiger { stack.info[pos++] = new_info; }
Kommst du soweit mit?
pos
ist ja am Anfang 0, also das erste Element. Beim Einfügen wird es gerade inkrementiert (pos++
gibt aber noch den alten Wert 0 zurück), sodass die nächste Einfügung eine Stelle weiter hinten erfolgt.Jetzt kommt noch die Sonderbehandlung. Dabei prüfst du, ob die maximale Grösse (Kapazität) erreicht wurde. Falls ja, legst du mit
realloc()
ein neues Array an, das 1.5 Mal so gross ist. Nicht vergessen, neue Kapazität anzupassen.
-
Also ich komme teils mit. O.O
Ich habe mal getestet und erfahren, dass das Programm in C++ geschrieben werden muss, da, wenn ich es als c-Programm kompilieren will, bekomme ich nur Fehler.Ist doch eine Ecke rasanter, als ich dachte. O.o Jetzt entstehen wieder einige Fragen mehr...
Am Besten, wir Fragen mal unseren Übungsleiter, wie man das dort macht.Trotzdem THX Nexus!
Falls weitere Fragen zu diesem Stack sind, schreibe ich wieder in dieses Thema, da ich im Moment erstmal müde bin und zweitens ich morgen oder so eh noch nicht durchblicken werde.^^'
MFG Majin_Clodan
-
Kannst du deinen Übungsleiter auch gerade fragen, wieso ihr nicht C++ programmiert, wenn das schon so dargestellt wird?
Finde ich nämlich wie gesagt etwas fragwürdig.Nein, wenn du willst, kannst du dich ja mal erkundigen, warum man nicht
cout
stattprintf()
,cin
stattscanf()
verwendet. Oder wieso man immer noch die alten C-Header mit der Endung .h hat (in C++ wären C-Header wenigstens mit einem c vornedran und ohne Endung, also<cstdio>
und<cstdlib>
). Aber nicht, dass du deswegen Probleme bekommst...P.S. Den C++-Header
<stack>
brauchst du nur, wenn du auf die fertige Klasse stack zugreifen willst, also in deinem Falle nicht.
-
So:
Wir sollen das Programm in C programmieren.
Die vollständigen Vorgaben sehen nun so aus. Hat sich nicht viel geändert, außer das die C++-bibliothek nicht mehr da ist:#include <stdio.h> #include <stdlib.h> struct TStackA { void** info; int maxGroesse; int pos; }; TStackA stapel; int anzahl = 0; TStackA create() { } TStackA push(void* info, TStackA oldStack) { } TStackA pop(TStackA oldStack) { } void* top(TStackA stack) { } /******************************************************************************* * Das Ein-/Ausgabeverhalten der main-Funktion darf nicht verändert werden. * e <Enter> beendet das Programm. * p <Zahl> <Enter> speichert <Zahl> auf dem Stapel. * o <Enter> entfernt das oberste Element vom Stapel. * t <Enter> Gibt den Integerwert an der Stapelspitze aus. *******************************************************************************/ int main(int argc, char* argv[]) { int* val; char command[8]; TStackA stack; printf("%d",stapel.info); stack = create(); while(*command != 'e') { printf("cmd? "); scanf("%s",command); switch(*command) { case 'p' : val = (int*)malloc(sizeof(int)); printf("val? "); scanf("%d",val); stack = push(val,stack); break; case 'o' : val = (int*)top(stack); if(val) free(val); stack = pop(stack); break; case 't' : if((val = (int*)top(stack))) printf("%d ",*val); break; } } }
Nun haben wir uns heute hingesetzt und versucht, das Programm nun zum Laufen zu bringen, doch wir haben hierbei ein Problem:
Wir wollen in der funktion "TStackA create()" einen neuen Stapel erstellen. Unsere codes sahen zum Schluss so aus:if(anzahl == 0) stapel.maxGroesse = 10; stapel.info=2; stapel.pos = 0; return stapel;
Das Problem hierbei ist, dass in der Struktur die Variable "info" vom Typ "void" ist. Das heißt, dass man hierbei immer einen Fehler bekommt, wenn der Wert nicht(!) 0 ist:
stapel.info=2;
Wie kann man diese Problematik umgehen?? Mein Tutor sagte mal was zu etwas, was "malloc" heißt, aber kp was das ist und wie man das implementieren soll. O.o
Hoffe, es ist nicht zu viel Text zum Lesen, da mein Beitrag doch arg lang ist. Ist aber nur die Vorgabe so lang.^^'
MFG Majin_Clodan
-
Majin_Clodan schrieb:
Nun haben wir uns heute hingesetzt und versucht, das Programm nun zum Laufen zu bringen, doch wir haben hierbei ein Problem:
Wir wollen in der funktion "TStackA create()" einen neuen Stapel erstellen.Wollt ihr nicht eine Funktion
TStackA* create(void)
schreiben, die dynamisch Speicher anfordert und einen Zeiger darauf zurückgibt? Ist meiner Ansicht nach einheitlicher, da wahrscheinlich auch spätere Operationen per Zeiger passieren und passt auch zumalloc()
.Wegen
malloc()
: Damit kannst du Speicher anfordern, schau mal hier. Denk dran, dass du den Speicher wieder mitfree()
freigeben musst.Majin_Clodan schrieb:
Das Problem hierbei ist, dass in der Struktur die Variable "info" vom Typ "void" ist. Das heißt, dass man hierbei immer einen Fehler bekommt, wenn der Wert nicht(!) 0 ist:
stapel.info=2;
Wie kann man diese Problematik umgehen?? Mein Tutor sagte mal was zu etwas, was "malloc" heißt, aber kp was das ist und wie man das implementieren soll.
Der Typ ist
void*
, nichtvoid
. Man kann keine Variablen vom Typvoid
haben.void*
ist ein typenloser Zeiger - also ein Zeiger, bei dem man nicht weiss, auf was für einen Typen er zeigt (int
,double
, ...).Ich denke, die Aufgabenstellung ist so gemeint, dass man mittels
malloc()
Speicher für einenint
reserviert und diesen dann der Variableninfo
zuweist. Auf der von mir verlinkten Seite sollte sich die Verwendung der manuellen Speicherverwaltung einigermassen erklären.Aber
void*
macht nur Sinn (aus C-Sicht), wenn sich dahinter mehrere Typen verbergen können. Und dann musst du noch irgendwo speichern, was für ein Typ nun tatsächlich genutzt wird, sonst weisst du ja nicht, wie du auf den Wert hinter dem Zeiger zugreifen kannst. Wenn du in deinem Stack nurint
s haben sollst, nimmst du besser einenint*
.
-
Moin!
Also ich habe mir mal einige tutorials, auch wegen dem, was intern geschieht, durchgelesen und es wird langsam logisch, was hier alles geschieht. xD Naja, wenn man sowas bisher noch nicht kannte und man auf einmal damit konfrontiert wird. xDTrotzdem schaffe ich es aber irgendwie nicht, Speicher zu reservieren.
Also mein "create" sieht nun so aus:
TStackA create() { stapel.info = (void **)malloc(sizeof(int)); // Reservierung Speicherbereich in Groesse "int" stapel.info = 4; //Stapelinformation, welche auf Stapel gelegt wird stapel.maxGroesse; //Stapelgroesse stapel.pos = 0; //Feldposition return stapel; //RG von Veranderung des Stapels }
Also bei er Zeile, wo ich Speicherbereich reserviere, kommt kein Fehler. Nun dacht ich mir, testest du es mal und legst einen int-Wert von 4 dort rein. Klappt aber nicht d.h. in der Zeile:
stapel.info = 4; //Stapelinformation, welche auf Stapel gelegt wird
bekomme ich den folgenden Fehler:
error: invalid conversion from 'int' to 'void*'*Ich verstehe das nicht. Ich habe doch einen gültigen Speicherbereich reserviert oder nicht?? Wieso kann ich diesen Wert nicht dort rein speichern?? ?.?
MFG Majin_Clodan
-
Die Fehlermeldung sagt ja alles. Du probierst ein int einem void** zuzuweisen, was ohne casten nicht geht. (Und auch nicht viel Sinn macht..)
-
Nun info ist ein Zeiger auf einen Zeiger im Speicherbereich deines Stapels und du reservierst Speicher für genau ein Element der Größe int und versuchst dann dem Zeiger einen int Wert zuzuweisen, das kann nicht gehen. Wahrscheinlich geht es aber um folgendes Prinzip:
int iStapelGröße = 100 // Das ist die Anzahl der Elemente die maximal auf den Stack gepusht werden können int* pStapel = (int*) malloc( sizeof ( int ) * iStapelGröße ); //hier wird Speicher reserviert int **info = &pStapel; //info zeigt nun auf das erste element im stapel //Push //Zuweisung: **info = 4; //nächstes freies Element wählen: info = &(*info++); // nächste Zuweisung: **info=3; ...
-
So,
habe es nun endlich hinbekommen.Jetzt gibt es nur noch ein kleines Problem, welches in einer weiteren Aufgabe ist. Es ist eigentlich fast alles gleich. Der einzigste Unterschied ist der, dass die Struktur nun so aussieht:
struct TStackP { void* info; TStackP* p; };
Mein Programm sieht bis jetzt so aus. Nicht wundern, falls es wieder viel aussieht. Ich gehe nur auf ein paar Zeilen ein.
#include <stdio.h> #include <stdlib.h> struct TStackP { void* info; TStackP* p; }; int zaehler = 0; TStackP stapel; void** zAufInfo = &stapel.info; //Zeiger auf void* info im Stapel -> I TStackP create() { stapel.info = (void *)malloc(10 + sizeof(int)); // Reservierung Felder des Array vom Typ int! <-------------- void** zAufInfo = &stapel.info; return stapel; } TStackP push(void* info, TStackP oldStack) { oldStack.info = (void *)malloc(10 + sizeof(int)); // Reservierung 1 Felder des Array vom Typ int! <-------------- zAufInfo[zaehler] = info; // I ++zaehler; return oldStack; } TStackP pop(TStackP oldStack) { zAufInfo[zaehler] = NULL; //Oberstes Stapelelement gelöscht --zaehler; //Dekrementierung oldStack.p[zaehler-1]; return oldStack; } void* top(TStackP stack) { if(zaehler <= 0) { printf("Der stapel ist leer"); exit(EXIT_FAILURE); } return zAufInfo[zaehler]; } /******************************************************************************* * Das Ein-/Ausgabeverhalten der main-Funktion darf nicht verändert werden. * e <Enter> beendet das Programm. * p <Zahl> <Enter> speichert <Zahl> auf dem Stapel. * o <Enter> entfernt das oberste Element vom Stapel. * t <Enter> Gibt den Integerwert an der Stapelspitze aus. *******************************************************************************/ int main(int argc, char* argv[]) { int* val; char command[8]; TStackP stack; stack = create(); while(*command != 'e') { printf("cmd? "); scanf("%s",&command); switch(*command) { case 'p' : val = (int*)malloc(sizeof(int)); printf("val? "); scanf("%d",val); stack = push(val,stack); break; case 'o' : val = (int*)top(stack); if(val) free(val); stack = pop(stack); break; case 't' : if((val = (int*)top(stack))) printf("%d ",*val); break; } } }
Man muss sich die vorgaben so vorstellen, dass in allen Funktionen außer der main nichts stand.
Bei diesem Programm schaff ich es nicht, etwas auf meinen Stapel zu tun. Ich bekomme zwar keine Fehlermeldung, wenn ich etwas raufsetze, aber wenn ich es sehen will, was dort ist, sehe ich nichts, als wäre dieser nicht da. O.O
Ich kann die Elemente auch löschen und ab einem bestimmten Punkt, wenn die Menge der elemente 0 ist und ich wieder was löschen will, wird das Programm beendet, doch das bringt mir ja nicht viel.^^'Also das Problem war ja meines erachtens, dass "info" in der Struktur kein Zeiger auf Zeiger mehr war. Dementsprchend bastelte ich mir einen und dieser zeigt dann auf dieses info in meiner Struktur:
void** zAufInfo = &stapel.info;
Wieso? Naja, weil ich später, wenn ich Elemente auf meinen Stapel tun wollte, immer Fehler bekam.
Meine push-Anweisung sieht dann so aus:zAufInfo[zaehler] = info
Hier wird die Information "info" an die Stelle "zaehler" im feld eingefügt.
So weit so gut. Wenn ich nun aber sehen will, was ich auf dem Stapel habe, sehe ich ja nichts. In meinem "top" habe ich dann dafür das:
return zAufInfo[zaehler];
danach dann soll es ja per printf ausgegeben werden, doch das macht es nicht.
Was habe ich falsch gemacht? Etwas falsches mit meinem "Zeiger auf Zeiger" oder so??
______
Legende in der Struktur:
info => speichert einen Zeiger auf die Information zu dem heweiligen Eintrag
p => dient der Verkettung der Stapelelemente=> wusste selber kaum, was p mir sagen soll und deswegen umgehe ich es einfach oder in wie fern könnte man es gebrauchen??
MFG Majin_Clodan
PS: so viel Text in einem Beitrag. xD
-
Hallo Komilitone(hab die gleiche aufgabe
)...also ich hab das Problem, dass der Compiler schon beim Aufruf der Funktion "create" einen Fehler meldet "syntax error before "create" ".
Ich seh überhaupt nich durch...muss ich vorher noch etwas definieren bzw. festlegen??
-
fischkopp schrieb:
Hallo Komilitone(hab die gleiche aufgabe
)...also ich hab das Problem, dass der Compiler schon beim Aufruf der Funktion "create" einen Fehler meldet "syntax error before "create" ".
Ich seh überhaupt nich durch...muss ich vorher noch etwas definieren bzw. festlegen??
Dann zeig den Code mal her. Du hast doch nicht etwa ein ; bei der Klassendefinition vergessen, oder?
-
Hallo Programmierpraktikum-Geschädigte und nette Menschen, die uns helfen,
Auch mir geht es so... Egal wie ich den Quelltext gestalte, immer kommt bei mir "Syntax-Error before create". Kann das am Compiler liegen (benutze DEV-C++)?? Ich mein, ich bekomm gar nicht die Fehlermeldungen, die schon erwähnt wurden, weil halt schon immer vorher ein Fehler auftritt. Hier beispielsweise mein create Funktion zu TStackA
#include <stdio.h> #include <stdlib.h> struct TStackA { void** info; int maxGroesse; int pos; }; TStackA stapel; // egal was ich mache kommt hier ein Fehler bzw. int anzahl = 0; // unten bei TStackA creat() TStackA create() { stapel.info = (void **)malloc(sizeof(int)); // Reservierung Speicherbereich in Groesse "int" stapel.info = 4; //Stapelinformation, welche auf Stapel gelegt wird stapel.maxGroesse; //Stapelgroesse stapel.pos = 0; //Feldposition return stapel; //RG von Veranderung des Stapels }
Vielen Dank für eure Hilfe im Voraus!
-
@BartMan
Das Programm, dass du bekommen hast ist als c Dokument gespeichert. Editiere mal die Endung auf *.cpp, dann kommt keine Meldung beim create mehr.
-
In C müssen Funktionen, die keine Parameter haben, das explizit durch
void
angeben.TStackA create(void)
-
hab das gleiche problem
die vorgabe ist c und nicht c++ und lehvis wird sicher auch nur ein c programm annehmen. also bringt es nichts das ding auf .cpp zu ändern
sonst könntest du ja gleich die c++ klassen dafür nehemen
in c++ könntest du sogar das struct weg lassen.wäre eine möglichkeit:
typedef struct TStackA { void** info; int maxGroesse; int pos; }TStackA;
in C brauchst du immer ein typedef (,oder?)
diese aufgabe spiegelt leider auch die vorlesung des prof´s B. wieder. er mischt ständig c mit c++ und das was in C ist entspricht nicht mal dem C99