Ich habe folgendes Programm in C getippt um den Umgang mit einem Stack
(LIFO -> Last In First Out) zu verstehen?
Mein Programm bittet um 10 Ganzzahlen (Array Feld 0 bis Feld 9) und gibt
diese anschließend wieder aus (Array Feld 9 bis Feld 0).
Habe ich in meinem einfachen Demobeispiel LIFO korrekt umgesetzt?
Vielen Dank!
Do Ma schrieb:> Mein Programm bittet um 10 Ganzzahlen (Array Feld 0 bis Feld 9) und gibt> diese anschließend wieder aus (Array Feld 9 bis Feld 0).>> Habe ich in meinem einfachen Demobeispiel LIFO korrekt umgesetzt?
Na ja.
Es kommt zwar das richtige raus, aber einen Stack würde ich das noch
nicht nennen wollen.
Bei einem richtigen Stack kannst du wahlfrei zwischen
* auf den Stack pushen
* vom Stack popen
wechseln, ohne dass da was durcheinander kommt.
Dein Programm ist zwar im Prinzip ein Stack, aber nur für den Sonderfall
der Operationen
* 10 Werte werden auf den Stack gepusht
* danach werden die 10 Werte wieder vom Stack gepopt.
Diesen Sonderfall behandelt es richtig, von einem richtigen Stack ist
das aber noch weit entfernt.
Ist ein bischen so, wie
Gleichungen lösen ist eigentlich ganz einfach
Gegeben die Gleichung
2x = 10
dann lautet die Lösung: x = 5
Das Ergebnis ist zwar im Prinzip richtig, aber der Lösungsweg ist nicht
allgemein genug angegeben, dass man diese Lösung als "er hat verstanden
wie man Gleichungen löst" akzeptieren könnte.
rein formal schon: du liest das zuerst aus, was zuletzt reingeschrieben
wurde.
Etwas näher an der Idee des LIFO wäre man dran, wenn man neben dem Feld
auch den aktuellen Index halten würde (initalisiert mit 0) und den beim
Abelegn erhöht und beim Entnehmen erniedrigt.
Typischerweise würde man das alles dann auch funktional etwas
formalisieren und nicht händisch in der Schleife auf das Feld zugreifen
zum Ablegen bzw. Entnehmen, sondern das über Funktionen realisieren
(push/pop), die dann auch Fehler abfangen könnten wie Über- oder
Unterlauf.
Wie darf ich die Auswahl ziwschen PUSH und POP verstehen? Ich dachte,
LIFO ist nur erfüllt, wenn ich zuerst schreibe und dann in umgekehrter
Richtung lese.
@Karl Heinz Buchegger
Wenn ich dich richtig verstanden habe, dann sollte es möglich sein,
etwas aus dem Stapel "zu ziehen" oder "hinein zu schieben" oder?
Do Ma schrieb:> Wie darf ich die Auswahl ziwschen PUSH und POP verstehen
z.b. so (pseudocode):
1
stack.push(5);
2
stack.push(3);
3
stack.push(0);
4
echo stack.pop();
5
stack.push(4);
6
stack.pop();
7
echo stack.pop();
würde als ausgabe "0 3" ergeben
d.h. es ist komplett egal in welcher reihenfolge daten auf den stack
gepusht oder vom stack gepopt werden. die implementierung sollte sich
dann auch darum kümmern, dass bei einem pop ohne vorhergendem push ein
fehler auftritt, der dann behandelt werden kann/muss...
Welche der obigen Anweisungen sollte denn bitte die 5 vom Stack lesen
und ausgeben? Keine.
Die 5 bleibt einfach auf dem Stack liegen. Das kann je nach
Ausführungsumgebung durchaus zu massiven Problemen führen. In dem
Beispiel mit Pseudocode hat es natürlich keine Seiteneffekte, außer eben
der Tatsache, dass zum Schluss die 5 auf dem Stack liegengeblieben ist.
Der Stack ist auch bildlich als Stapel zu verstehen. Wenn man morgens
fünf Zettel auf den Stapel legt und im Laufe des Tages vier Zettel
wieder entfernt, bleibt eben ein Zettel übrig. Macht man das jeden Tag,
erhöht sich der Stapel um einen Zettel.
Do Ma schrieb:> @Daniel F.>> Warum würde dein Pseudocode die 5 nicht mehr ausgeben?
Niemand hindert dich daran am Ende des Progamms einen Code einzufügen,
welcher alle noch nicht gepopten Elemente vom Stack holt und den
Benutzer vor dem Bildschirm darüber aufklärt, dass er nicht alles was er
gepusht hat auch wieder gepopt hat.
Do Ma schrieb:> Wie darf ich die Auswahl ziwschen PUSH und POP verstehen? Ich dachte,> LIFO ist nur erfüllt, wenn ich zuerst schreibe und dann in umgekehrter> Richtung lese.
Was heißt denn LIFO?
Last in - First Out
Das bedeutet nichts anderes als dass du beim Popen die einzelnen Zahlen
in der umgekehrten Reihenfolge bekommst. Aber das sagt ja nichts darüber
aus, dass die Operationen nicht abwechselnd erfolgen können.
Du hast einen Stapel Teller.
Buffetgäste welche sich Teller holen, kriegen immer die Teller zuerst
die du zuletzt auf den Stapel gelegt hast. Und zwar in der umgekehrten
Reihenfolge. Kein Mensch zwingt dich abzuwarten, bis keine Teller mehr
da sind. Du kannst jederzeit neue Teller (einzeln) auf diesen Stapel
legen. Dann kriegen eben die Gäste diese neuen aufgelegten Teller
zuerst.
Nimm an auf deinem Teller stehen Zahlen. Du baust den Stapel mit 5
Teller auf
Tisch | 1
Tisch | 1 2
Tisch | 1 2 3
Tisch | 1 2 3 8
Tisch | 1 2 3 8 15
Teller 15 ist als letztes aufgelegt worden.
Jetzt kommt ein Gast und holt sich einen Teller. Er kriegt Teller Nr.
15, weil das der war, den du zum Schluss aufgelegt hast.
Dein Stapel Teller sieht daher jetzt so aus
Tisch | 1 2 3 8
Noch ein Gast holt sich einen Teller. Er kriegt die Nr 8 und der
verbleibende Stapel sieht so aus
Tisch | 1 2 3
jetzt kommst du aus der Küche und legst noch 3 Teller auf den Stapel: 23
5 und 9
erst die 23
Tisch | 1 2 3 23
dann die 5
Tisch | 1 2 3 23 5
und zum Schluss die 9
Tisch | 1 2 3 23 5 9
kommt jetzt ein Gast, und holt sich einen Teller, kriegt er die 9. 9 ist
als letztes aufgelegt worden
Tisch | 1 2 3 23 5
der nächste kriegt 5
Tisch | 1 2 3 23
usw. usw.
Das Prinzip ist jetzt zwar korrekt implementiert, aber die
Strukturierung des ganzen Programms bereitet mir noch erhebliche
Bauchschmerzen.
1. Die Funktion pop() sollte bei der obigen Implementierung eher
pop_and_print() oder so heißen. Besser ist es jedoch, die Ausgabe im
Hauptprogramm und nicht in pop() durchzuführen, da dadurch eine klare
Aufteilung der Aufgaben realisiert wird.
2. Die Vermischung von Zugriffen auf array1[] und counter1 aus dem
Hauptprogramm und aus Funktionen heraus ist ungünstig.
3. Für die Auswahl der durchzuführenden Aktion bieten sich switch/case
eher an als ein Grab von if-Anweisungen.
ja, schon eher.
Wenn du jetzt auch noch die printf aus push und pop rausnimmst und zum
Aufrufer verlegst und bei pop den gelesenen Wert zurückgibst, anstatt
ihn in der Funktion gleich zu verwursten, sieht das schon aus, wie man
sich einen LIFO so vorstellt.
Dann könnte man noch Fehlerbehandlung machen, sowie push, pop, das Feld
und den Zähler in einen eigenen Quelltext verfrachten (static für die
Variablen), damit der Aufrufer nicht direkt an das Feld herankommt ohne
die Funktionen, und der Drop ist gelutscht.
Klaus Wachtler schrieb:> sowie push, pop, das Feld>> und den Zähler in einen eigenen Quelltext verfrachten (static für die>> Variablen)
Was meinst du damit genau?
Do Ma schrieb:> Umbau Nr. 1:
nicht gut.
Du musst die Dinge voneinander trennen!
Einen Stack zu haben ist eine Sache.
Werte vom Benutzer eingeben zu lassen ist eine andere Sache.
Die beiden haben nichts miteinander zu tun. Also solltest du sie auch
nicht miteinander vermischen. Die Push bzw. Pop Funktionen übernehmen
einen Wert bzw. liefern einen Wert. Das ist ihre Aufgabe. Wo dieser Wert
her kommt, geht sie nichts an.
> void push(int var)> {> if(var!=-1)> {> array[counter]=var;> counter++;> }> }
hier muss die Überprüfung rein!
1
voidpush(intvar)
2
{
3
if(counter<FELDGROESSE)
4
{
5
array[counter]=var;
6
counter++;
7
}
8
}
und beim pop genauso. Wenn deine I/O Funktionen zusätzlich noch prüfen
ob Platz im Stack ist, dann ist das löblich. Aber in erster Linie muss
der Stack auf sich selber aufpassen und Fehlbedienung verhindern. Es ist
ja schliesslich nicht in Stein gemeisselt, dass der Stack nur von einem
Benutzer gefüllt wird. Der Stack kann, darf und will gar nicht wissen,
wo die Werte herkommen. Aber: Er muss die Nebenbedingung - Stack voll -
berücksichtigen.
1
...
2
if(counter<FELDGROESSE)
3
{
4
...
5
}
6
elseif(counter>=FELDGROESSE)
7
{
8
...
9
}
das ist doppelt gemoppelt. Der else Zweig wird sowieso immer nur dann
ausgefühtr, wenn die Bedingung im if nicht zutrifft. Wenn counter aber
nicht kleiner als FELDGROESSE ist, dann kann counter nur noch größer
oder gleich sein. Eine andere Möglichkeit gibt es nicht! Schreibst du
die Bedingung trotzdem noch einmal hin, dann machst du dir erstens mehr
Arbeit als notwendig und zweitens läufst du Gefahr, dass du dir dabei
einen Fehler, und sei es nur ein banaler Tippfehler, einhandelst.
Und lass dir ein paar vernünftige Begriffe für deine Variablen
einfallen! array, counter, FELDGROESSE, das kann alles und nichts sein.
Der geneigte Leser hat es hier mit einem Stack zu tun! Erinnere ihn bei
jeder Zeile daran.
Das Array mit den Werten, welches den Stack bildet, kann man zb
wunderbar "stack" nennen. Der counter ist allgemein als der
"StackPointer" bekannt und die Arraygröße ist der alles entscheidende
Punkt für die "STACK_SIZE"
1
#define STACK_SIZE 5
2
intStack[STACK_SIZE];
3
intStackPointer;
4
5
6
voidpush(intValue)
7
{
8
if(StackPointer<STACK_SIZE)
9
{
10
Stack[StackPointer]=Value;
11
StackPointer++;
12
}
13
}
Ob und wie man im push auf die Fehlersituation reagiert, ist
Ansichtssache. In Produktionscode würde das so sicher nicht gehen. Die
Fehlersituation muss gemeldet werden. Wie das genau passiert, hängt dann
auch von den Codingrichtlinien der einzelnen Firmen ab. Aber ein erster
Ansatz wäre mal ein Returnwert, den der Aufrufer abfragen kann.
In dieser konkreten Implementierung, nämmlich dass die Kennzeichnung des
aktuellen Stapelelements durch den Index mit einer Schrittweite von eins
erfolgt, mag der Unterschied nicht deutlich werden.
Bei vielen anderen Arten, einen Stack zu implementieren, wird jedoch ein
Zeiger direkt auf den adressierten Speicher verwendet. Dann hängt die
Schrittweite von der Größe der auf dem Stack abzulegenden Daten ab;
diese muss nicht einmal einheitlich sein. Folglich ist dann ggf. sogar
die Schrittweite variabel.
Be einigen Prozessoren gibt es auch keine Äquivalenz zwischen den
möglichen Zählerdatentypen (z.B. Integer bzw. int) und Pointertypen,
z.B. den x86 in segementierter Betriebsart.
Stackpointer werden nicht nur auf Hochsprachenebene verwendet, sondern
bei sehr vielen Prozessoren auch auf Low-Level-Ebene, d.h.
Unterprogrammaufrufe bewirken ein automatisches Speichern des aktuellen
Programmzeigers (bzw. der Speicheradresse der nächsten folgenden
Anweisung) auf dem Stack. Aus diesem Bereich kommt auch die
ursprüngliche Definition des Begriffs Stackpointer. Bei Prozessoren,
deren Stackpointer gleichzeitig als Register adressierbar ist, heißt er
häufig SP. Einige Prozessoren (z.B. ARM) haben sogar mehrere
Stackpointer für unterschiedliche Betriebsarten.
Interessanterweise heißt der Programmzeiger meist "Program Counter" und
nicht "Program Pointer". Insofern gibt es schon eine gewisse
Vermischung der beiden Begriffe "Zähler" und "Zeiger".
Umbau Nr. 2:
Welche if-Bedingung in der Funktion print_elem() ist notwendig, um eine
Ausgabe bei der Auswahl der Funktion pop() bei leerem Stack zu
verhindern (bei leerem Stack ist der stackpointer 0)? Die Bedingung
stackpointer >= 0 liefert Pseudowerte bei leerem Stack.
Die anderen Bereiche im Programm sollten jetzt korrekt sein!?
1
#include<stdio.h>
2
#include<stdlib.h>
3
#define STACK_SIZE 5
4
5
intstack[STACK_SIZE]={};
6
intstackpointer=0;
7
8
intvalue_push()
9
{
10
intvar;
11
printf("\nWelchen Wert wollen Sie auf den Stapel legen?\n\n");
- push() und pop() liefern keinen Status zurück, anhand dessen man sehen
kann, ob die Stackoperation funktioniert hat.
- push_value() bewirkt die Eingabe einer Zahl und hat nichts mit einer
"push"-Operation zu tun.
- print_stack() vermischt Zugriffe auf den Stack und Benutzerausgaben.
- print_elem() gibt eine beliebige Zahl aus, deren Herkunft nicht
unbedingt ein Stackelement sein muss. Somit ist der Name
missverständlich.
printf("Fuer die Funktion PUSH druecken Sie bitte <1>\n");
11
printf("Fuer die Funktion POP druecken Sie bitte <2>\n");
12
printf("Fuer die Stack-Ansicht druecken Sie bitte <3>\n");
13
printf("Um das Programm zu beenden druecken Sie bitte <4>\n\n");
14
printf("Auswahl: < >\b\b");
15
scanf("%d",&auswahl);
16
switch(auswahl)
17
{
18
case1:fw_value_push=value_push();
19
push(fw_value_push);
20
break;
21
case2:fw_pop=pop();
22
print_elem(fw_pop);
23
break;
24
case3:print_stack();
25
break;
26
case4:end=1;
27
break;
28
}
29
}
30
printf("\n********** Das Programm wurde beendet ***********\n\n");
31
system("PAUSE");
32
return0;
33
}
Man kann es mit der Zerlegung in Teilfunktionen auch übertreiben.
Bringen dir hier die Funktionen value_push() bzw. print_elem()
irgendwelche Vorteile?
Ich würde mal sagen: nein.
Ausser, dass du das Wissen über die Bedienung deines Programm möglichst
weit quer über das Programm verstreust, bringen sie dir nichts.
Warum nicht ganz banal
printf("Fuer die Funktion PUSH druecken Sie bitte <1>\n");
10
printf("Fuer die Funktion POP druecken Sie bitte <2>\n");
11
printf("Fuer die Stack-Ansicht druecken Sie bitte <3>\n");
12
printf("Um das Programm zu beenden druecken Sie bitte <4>\n\n");
13
printf("Auswahl: < >\b\b");
14
scanf("%d",&auswahl);
15
16
switch(auswahl)
17
{
18
case1:
19
printf("Wert: ");
20
scanf("%d",&value);
21
push(value);
22
break;
23
24
case2:
25
value=pop();
26
printf("%d\n",value);
27
break;
28
29
case3:
30
print_stack();
31
break;
32
}
33
}
34
35
printf("\n********** Das Programm wurde beendet ***********\n\n");
36
system("PAUSE");
37
return0;
38
}
So. Und wenn du jetzt noch zu deinem Benutzer nett bist, dann machst du
dir noch 2 Funktionen:
int isStackFull()
int isStackEmpty()
und abhängig von diesen beiden Funktionen bietest du nämlich deinem
Benutzer dann die momentan nicht möglichen Menüpunkte gar nicht mehr an.
Welchen Sinn soll es denn haben, wenn der Benutzer einen Menüpunkt
auswählen kann, nur damit du ihm nachher sagst, dass die Operation gar
nicht mehr geht. Das ist ein bischen so wie ein BUtton auf den man
draufdrückt und dann taucht ein Text auf "Drücken sie hier nicht drauf"
printf("Fuer die Funktion PUSH druecken Sie bitte <1>\n");
11
if(!isStackEmpty())
12
printf("Fuer die Funktion POP druecken Sie bitte <2>\n");
13
printf("Fuer die Stack-Ansicht druecken Sie bitte <3>\n");
14
printf("Um das Programm zu beenden druecken Sie bitte <4>\n\n");
15
printf("Auswahl: < >\b\b");
16
scanf("%d",&auswahl);
17
18
switch(auswahl)
19
{
20
case1:
21
if(!isStackFull())
22
{
23
printf("Wert: ");
24
scanf("%d",&value);
25
push(value);
26
}
27
break;
28
29
case2:
30
if(!isStackEmpty())
31
{
32
value=pop();
33
printf("%d\n",value);
34
}
35
break;
36
37
case3:
38
print_stack();
39
break;
40
}
41
}
42
43
printf("\n********** Das Programm wurde beendet ***********\n\n");
44
system("PAUSE");
45
return0;
46
}
Und sei mit deinen Texten etwas weniger geschwätzig. Texte sollen
ausreichend lang, aber auch nicht zu lang sein. Kein Mensch liest halbe
Romane. Benutzer tendieren dazu, lange Texte nicht mehr wahrzunehmen
sondern aus Gewohnheit irgendwo draufzudrücken.
Wenn ein Programm hochfährt und es meldet sich mit
1
Willkommen zum Stacktestprogramm Version 2.48,
2
geschrieben im Frühjahr 2012 vom Superprogrammierer xyz
3
als Vorbereitung zur Diplomarbeit seines Bruders.
4
Ich danke meinen Eltern für den Support, meinen Großeltern
5
fuer den neuen Computer und nicht zuletzt meiner Tante, die
6
das Mittagessen gemacht hat!
7
(C) 2012 xyz@gmx.de
dann weiß jeder Programmierer, dass es sich um ein Anfängerprogramm
handelt. Denn genau solche Begrüssungsnachrichten sind ein Markezeichen
dafür. Erst kommt eine halbe Seite Begrüßung und dann hat der
Programmierer nicht mehr weiter gewusst. Diese Begrüßungsmasken bei
gekauften Programmen haben einen anderen Zweck. Sie sollen den Benutzer
ein bischen beschäftigen, bis das Programm 25 DLLs und 68 Datendateien
nachgeladen hat. Kommerzielle Programme haben einen etwas größeren
Umfang und brauchen ein wenig Zeit um zu laden. Und damit der Benutzer
Feedback hat, dass da tatsächlich etwas passiert, macht man so einen
Splashscreen rein.
Ich versuche mit nur einer Funktion die Menüpunkte und Funktionen push()
und pop() ein- und auszublenden.
Wie es aussieht, denke ich falsch um die richtige else if-Bedingung zu
finden.
1
stack_state()
2
{
3
if(stackpointer<STACK_SIZE)
4
{
5
return0;
6
}
7
elseif(stackpointer)//Welche Bedingung ist dafuer notwendig?
>Das ist ein bischen so wie ein BUtton auf den man>draufdrückt und dann taucht ein Text auf "Drücken sie hier nicht drauf"
Lach. Das taucht tatsächlich immer wieder mal als Gag auf.
1
stack_emty()
2
{
3
if(stackpointer<STACK_SIZE)
4
{
5
return0;
6
}
7
elseif(stackpointer>=STACK_SIZE)
8
{
9
return1;
10
}
11
}
Ein Stack ist nicht dann leer, wenn weniger Elemente darin sind als er
fassen kann, sondern dann wenn mindestens ein Element darin ist. Das ist
ein Unterschied. Kannst Du erklären welcher? Denk dran: EmPty wird
gebraucht um zu entscheiden ob man was herunterholen kann.
1
stack_full()
2
{
3
if(stackpointer>0)
4
{
5
return0;
6
}
7
else
8
{
9
return1;
10
}
11
}
Ebenso ist ein Stack nicht dann voll wenn er mehr als ein Element enhält
sondern wenn er genauso viele Elemente enthält, wie er fassen kann.
Denke daran: "Full" wird gebraucht um zu entscheiden ob man noch was
drauf-stapeln darf.
Uups.
>Ein Stack ist nicht dann leer, wenn weniger Elemente darin sind als er
fassen kann, sondern dann wenn mindestens ein Element darin ist.
muss natürlich heissen:
Ein Stack ist nicht dann leer, wenn weniger Elemente darin sind als er
fassen kann, sondern dann wenn kein Element darin ist.
>Dann werde ich die Funktionen einfach stack_state1() und stack_state2()>nennen. Somit ist die Gläserfrage beseitigt. :-)
So geht das leider nicht. Ich fürchte ich habe Dich mit meiner
humorvollen Ausdrucksweise dazu verleitet anzunehmen, das kein
sachlicher Grund für eine kritische Betrachtung vorliegt. Das aber ist
durchaus nicht der Fall.
Widersprüche in Software sind immer und absolut zu vermeiden!
Es geht nicht darum wie die Funktionen heissen, sondern was sie tun. Das
sind zwei völlig verschiedene Dinge. Idealerweise passt der
Funktionsname zu dem was sie tut. Aber das was die Funktione tut muss
auch zu dem passen wie sie verwendet werden.
Du brauchst keine Funktion, die Dir ihrem Namen und ihrer Verwendung
nach sagen soll, ob der Stack voll ist, die aber im Gegensatz dazu prüft
ob Elemente im Stack sind und nicht ob der Stack tatsächlich voll ist.
Genauso brauchst Du keine Funktion, die Dir ihrem Namen und ihrer
Verwendung nach sagen soll ob der Stack leer ist, die aber im Gegensatz
dazu prüft, ob weniger Elemente darin sind als sie fassen kann.
Das habe ich aber schon geschrieben und das sollte Dir auch die Logik
sagen.
1
stack_empty()
2
{
3
if(stackpointer==0)// nur wenn kein Element auf dem Stack ist, dann ist er auch tatsächlich "leer" resp. "empty"
4
{
5
return0;
6
}
7
else{
8
return1;
9
}
10
}
1
stack_full()
2
{
3
if(stackpointer==SIZE)// nur wenn alle Elemente belegt sind, ist der Stack auch tatsächlich "voll" resp. "full".
4
{
5
return0;
6
}
7
else
8
{
9
return1;
10
}
11
}
Im übrigen, weichst Du von der üblichen Deutung von 0 als Falsch und 1
als Wahr ab. Da das aber Konvention ist, mag es so hingehen.
Im übrigen ist der Name "stack_state1" anstatt "stack_full" ohnehin die
schlechtere Wahl. Es ist ja nicht mehr erkennbar, auf welchen Zustand
geprüft wird.
Wenn Du Dir Deine Implementierungen anschaust und was sie zurückliefern,
dann wird Dir vielleicht klarer was ich meine.
Stackbelegung 0 1 2 .... 20 21 STACKGRÖSSE
Stack_Full F W W .... W W W
Stack_Empty W W W .... W W F
Wobei Wahr = W = 0
und Falsch = F = 1
gelten soll.
Eigentlich aber sollte das so aussehen.
Stackbelegung 0 1 2 .... 20 21 STACKGRÖSSE
Stack_Full F F F .... F F W
Stack_Empty W F F .... F F F
Nimm einmal an, Du erhieltest die Aufgabe den Stack in einer Datei zu
sichern, falls er Daten entält.
Deine Stack-Empty Funktion kannst Du nicht verwenden, da sie solange
Wahr liefert wie der Stack nicht voll ist.
Hingegen kannst Du meine Stack-Empty Funktion verwenden, das sie wahr
liefert, sobald mindestens ein Element enthalten ist.
Das gleiche macht zwar Deine Stack_Full Funktion (nur negiert) aber
stelle Dir mal Code vor der lautet:
if (Stack_Full () == Wahr)
Sichere_Stack_In_Datei ();
Jeder der das liest, wird annehmen, das die Daten nur dann gesichert
werden wenn der Stack voll ist. Aber Deine Aufgabe war ja den Stack auch
zu sichern, wenn er zwar Elemente enthält aber weniger als hineinpassen.
Auch so funktioniert das zwar, aber man muss dazu die Funktion selbst
erstmal studieren. Erstmal liest sich das wie ein Widerspruch!
Das ist keine gute Praxis. Es führt zu Verwirrung.
Klar, was ich meine?
Tippfehler:
Es muss heissen:
Hingegen kannst Du meine Stack-Empty Funktion verwenden, das sie falsch
liefert, sobald mindestens ein Element enthalten ist.
Da steht:
1. Wenn der Stack leer ist, kannst Du Daten hinein-pushen. Häh?
Darauf Du: Naja. Die Funktion liefert auch wahr, wenn der Stack nicht
leer ist. Darauf ich: Und wenn er voll ist? Du: Dann liefert sie Falsch.
Ich: Aha. Warum dann nicht:
1
if(stack_full()==0)
schreiben? Das ist viel klarer (Abgesehen von der 0 = Wahr
Verwechselung)
2. Wenn der Stack voll ist, kannst Du Daten heraus-poppen. Häh?
Darauf Du: Naja. Die Funktion liefert auch wahr wenn der Stack nicht
voll ist. Ich: Und wenn er leer ist? Du: Dann liefert sie Falsch. Ich:
Aha. Warum dann nicht:
1
if(stack_empty()==1)
schreiben? Das ist viel klarer.
Naja. Hoffe das ist von Nutzen. Wenn nicht ignoriere es.
:-)
Besser. Und wenn Du Dir jetzt noch von einem freundlichen Nachbarn ein
"p" ausleihst und "Empty" schreibst sind auch die
Rechtschreibfetischisten (wie ich) befriedigt. :-)
Da ich keine Antworten mehr erhalten habe, gehe ich davon aus, dass die
aktuelle Umsetzung in Ordnung ist.
Vielen DANK für eure Hilfe!!!
Der nächste Schritt ist der Umbau zu FIFO. Kann ich dazu das aktuelle
Programm verwenden?
Do Ma schrieb:> Der nächste Schritt ist der Umbau zu FIFO. Kann ich dazu das aktuelle> Programm verwenden?
theoretisch könntest du eine fifo-queue auf basis deines stacks
implementieren. nach dem umbau des ganze wirst du aber erkennen, dass
vom ursprünglichen programm nicht mehr viel übrig geblieben ist.
daher mein tipp: fang von vorne an, davon hast du wesentlich mehr
Do Ma schrieb:> Da ich keine Antworten mehr erhalten habe, gehe ich davon aus, dass die> aktuelle Umsetzung in Ordnung ist.
Nein, Du hast nur einen Teil der Ratschläge umgesetzt. Da macht es
einfach keinen Sinn, als Bittsteller aufzutreten: "Lieber Do Ma, würdest
Du bitte bitte bitte noch diese oder jene Korrektur einbauen?"