Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von Mok »

Hallo.
Ich hab schon seit einiger zeit ein Brett vorm Kopf und komm selber nicht auf den Fehler, daher bitte ich euch, mir zu helfen.
Also, hier ist meine Stack-Include (von mir nach PB übersetzt, Quelle ist die Musterlösung einer C-Hausübung)

Code: Alles auswählen

EnableExplicit

Macro _ret
  ProcedureReturn
EndMacro

Structure Stack
  *Val
  *Next.Stack
EndStructure

Procedure InitStack()
  Protected.Stack *Temp
  *Temp = AllocateMemory(SizeOf(Stack))
  _ret *Temp
EndProcedure

Procedure CountStack(*Stack.Stack)
  Debug "____Called."
  Protected.Stack *Temp
  Protected.i Count
  
  If *Stack = #Null : _ret 0 : Else
    *Temp = *Stack\Next
    
    While *Temp <> #Null
      Debug "____Inner Loop"
      Count = Count + 1
      *Temp = *Temp\Next
    Wend
    Debug "____Outer Loop"
    _ret Count
  EndIf
EndProcedure

Procedure IsStackEmpty(*Stack.Stack)
  _ret (CountStack(*Stack) = 0)
EndProcedure

Procedure Push(*Stack.Stack, *Item)
  Protected.Stack *Temp
  
  If *Stack = #Null : _ret #False : Else
  
  *Temp = InitStack()
  *Temp\Val = *Item
  *Temp\Next = *Stack\Next
  *Stack\Next = *Temp
  
  _ret #True : EndIf
EndProcedure

Procedure Pop(*Stack.Stack)
  Protected.Stack *Temp 
  Protected *VAL0__
  
  If IsStackEmpty(*Stack) Or *Stack = 0 : _ret #False : Else
  
  *Temp = *Stack\Next
  *VAL0__ = *Temp\Val
  *Stack\Next = *Temp\Next
  FreeMemory(*Temp)
  
  _ret *VAL0__ : EndIf
EndProcedure

Procedure FreeStack(*Stack.Stack)
  FreeMemory(*Stack)
EndProcedure

Define.Stack *MyStack = InitStack() ;Aufruf OK
Define.i Item = 5
Debug Push(*MyStack,@Item) ;Rückgabewert ist 1 => Aufruf OK
Debug "---"
Debug Pop(*MyStack) ;Rückgabewert ist eine Adresse => Aufruf OK
FreeStack(*MyStack) ;Aufruf OK
Debug "---" ;Das wird noch gedruckt
Debug IsStackEmpty(*MyStack) ;Hier wird aufgrund des Aufrufs von IsStackEmpty() und weiters durch den Aufruf von CountStack() nichts ausgegeben.
Debug Push(*MyStack,@Item)
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von STARGÅTE »

Der Grund ist du erzeugst ein zyklischen Bezug:
Das heißt:

Code: Alles auswählen

While *Temp <> #Null
      Debug "____Inner Loop"
      Count = Count + 1
      *Temp = *Temp\Next
    Wend
Dort ist zB:
*Temp = 4063608
*Temp\Next wäre zB 4071056
Aber der näche also *Temp\Next\Next wäre wieder 4063608
Somit gibs da n Schleife.

Checke also noch mal das setzen deiner Next-Pointer ...
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von Mok »

@STARGÅTE: Irgendwann muss *Next ja mal auf Null zeigen, weil sonst hätte man ja nen unendlichen Stack
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von STARGÅTE »

Jo, vllt bei anderen,
Aber in deinem Code gibs eben nKreisbezug.

Weil das 1. zum 2. Zeigt und das 2. zum 1. ...
das wird nie null, weil immer nur 2 elemente beteilig sind, die sich immer wieder gegenseitig aufrufen.

das wird also dort nicht irgendwann null
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von helpy »

Hallo,

Denke den ganzen Aufbau nochmal durch!

1. FreeStack wird so nicht funktionieren, sondern zu einem Memory-Leak führen, denn mit jedem Push erzeugst Du mit InitStack ein neues Stack-Element, das mit AllocateMemory() neuen Speicher beansprucht. Deshalb musst Du bei FreeStack auch eine Schleife einbauen, die jedes Stack-Element durchgeht und den zugehörigen Speicher freigibt.

2. Schau Dir Push() genau an! Die beiden Zeilen

Code: Alles auswählen

  *Temp\Next = *Stack\Next
  *Stack\Next = *Temp
erzeugen bereits einen Zirkelschluss!

3. Ein Stack (Stapel) funktioniert doch so, dass Du mit Push() ein Element AUF den Stapel legst und mit Pop() das letzte Element vom Stapel wieder runter holst. Wenn *Stack.Stack immer auf das erste Element (den Stapel-Anfang) zeigt, dann brauchst Du doch immer eine Schleife, um das letzte Element zu ermitteln und da das neue dran zu hängen (Push) bzw. das letzte Element vom Stapel runter zu holen (Pop). Den Sonderfall "Leerer Stack" muss man entsprechend behandeln.
==> Also beide Prozeduren Push() und Pop() noch mal neu durchdenken und überarbeiten!

lg,
guido
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von Mok »

Ich lauf irgendwie nur im Kreis. Je mehr ich verbessern will, desto schlimmer wird's. Dabei ist es doch eine Übersetzung einer Musterlösung und die sollte eigentlich in Ordnung sein. :roll:
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von helpy »

Falls Du keine fix-fertige Lösung von jemand anderem suchst, sondern etwas lernen möchtest, dann schläfst Du mal eine Nacht drüber und versuchst es morgen ganz von vorne ;-)

... evt zeichnest Du Dir den Stack auf Papier und welcher Zeiger (Next) wohin zeigt.
... dann gehst Du alles Schritt für Schritt durch.

lg,
guido
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von Mok »

helpy hat geschrieben:Falls Du keine fix-fertige Lösung von jemand anderem suchst[...]
as hab ich auch nie getan...
Push & Pop müssten doch so funktionieren:

Code: Alles auswählen

Procedure Push(*Stack.Stack, *Item)
  Protected.Stack *Temp
  
  If *Stack = #Null : _ret #False : Else
  
  *Temp = InitStack()
  *Temp\Val = *Item
  If IsStackEmpty(*Stack)
    *Temp\Next = #Null
  Else
    *Temp\Next = *Stack\Next
  EndIf
  *Temp = *Stack
  
  _ret #True : EndIf
EndProcedure

Procedure Pop(*Stack.Stack)
  Protected.Stack *Temp 
  Protected *Value
  
  If IsStackEmpty(*Stack) Or *Stack = #Null : _ret #False : Else
  
  *Value = *Stack\Val
  *Stack = *Stack\Next
  
  _ret *Value : EndIf
EndProcedure
Tunse aber nicht :freak:
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von mk-soft »

Nicht das "Next" speichern, sondern das Previous" speichern.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: Schleife in Prozedur: 1. Aufruf OK, 2. Aufruf endlos

Beitrag von Mok »

mk-soft hat geschrieben:Nicht das "Next" speichern, sondern das Previous" speichern.
Das Previous kann nicht existieren, weil es im Stack nur ein Next gibt (FILO)
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Antworten