Seite 1 von 2

Übergabe von Strings per Pointer an Proceduren

Verfasst: 29.09.2004 18:49
von lrhe
Hallo,
komme mit den Pointer's nicht weiter. Hab leider in der Hilfe und im Forum nicht soviel gefunden:

Möchte einen(mehrere) String(s) im Hauptprogramm per Pointer an eine Procedur übergeben, sodass sie dort direkt modifiziert werden können. Klappt noch so, egal wie ich's probiere. Hier im Bsp. scheitert der Aufruf der Proc mit "String erwartet...":

Code: Alles auswählen

;Test Übergabe Stringpointer an Procedure
str.s="abcdefg"
;-----------------------
Procedure mytest(*mystr.s)
  tmp.s=""
  tmp.s=Left(*mystr,2)      ;"ab" aus 'str' in tmp legen
  Debug *mystr +", "+tmp
  tmp=tmp+"12345"           ;tmp auf "ab12345" ergänzen
  Debug *mystr +", "+tmp
  *mystr=tmp                ;tmp zurück in 'str'
  Debug *mystr +", "+tmp
EndProcedure
;------------------------
mytest(@str)                ;Übergabe Pointer, Fehler!!!  :twisted: 
result=MessageRequester("Test",str,0) ;soll "ab12345" liefern
End
Eigentlich wollte ich auch LinkedLists per Pointer übergeben, hab aber gelesen, dass das nicht geht?! Ziel ist die Über-/Bearb./Rückgabe langer Datenfelder, vielleicht ja auch als Array mit Pointer?! Die String-Übergabe hab ich nun alternativ verwenden wollen, um das Feld als TokenString zu übergeben und in der Prozedur um Elemente zu ergänzen.
Danke für Eure Hilfe und Tip's!!!
Gruß, Lutz

PS: PB-Version 3.3 (leider noch so'ne ältere TOPOS-KaufCD-Version)

Edit by NicTheQuick: Code-Tags gesetzt

Verfasst: 29.09.2004 19:01
von wichtel
Versuche es mal mit der Übergabe eines Pointers auf eine Struktur mit Strings. Dann sollte es gehen.

Code: Alles auswählen


Structure DATEN
  feld1$
  feld2$
  feld3$
  feld4$
EndStructure


nurso.DATEN

  

Procedure MachWas(*p.DATEN)
  *p\feld1$="Das"
  *p\feld2$="ist"
  *p\feld3$="ein"
  *p\feld4$="Test"
EndProcedure



Debug nurso\feld1$
Debug nurso\feld2$
Debug nurso\feld3$
Debug nurso\feld4$

MachWas(@nurso)

Debug nurso\feld1$
Debug nurso\feld2$
Debug nurso\feld3$
Debug nurso\feld4$




Verfasst: 29.09.2004 19:05
von NicTheQuick
Das geht leider nicht so einfach, wie du dir das vorstellst. Hier wäre meine Variante. Das Problem ist wohl, dass die Stringfunktionen mit der Pointervariante nicht so wirklich arbeiten können. Man muss also immer noch [c]PokeS()[/c] und [c]PeekS()[/c] nehmen.

Code: Alles auswählen

;Test Übergabe Stringpointer an Procedure
Global str.s
str.s="abcdefg"
;-----------------------
Procedure mytest(*mystr.STRING)
  Protected tmp.s
  tmp = PeekS(*mystr, 2)
  Debug PeekS(*mystr) + ", " + tmp
  tmp = tmp + "12345"          ; tmp auf "ab12345" ergänzen
  Debug PeekS(*mystr) + ", " + tmp
  PokeS(*mystr, tmp)
  Debug PeekS(*mystr) + ", " + tmp
EndProcedure
;------------------------
mytest(@str)                ; Übergabe Pointer, Fehler!!!  :twisted:
result = MessageRequester("Test", str, 0) ; soll "ab12345" liefern
End

Verfasst: 29.09.2004 19:28
von lrhe
Danke für eure schnellen Antworten. Mein 3.3 Compiler scheitert aber auch beim probieren des Bsp. mit PeekS schon an der Zeile zum Aufruf der Funktion und sagt:

mytest(@str) ---> liefert: Bad parameter type: a string is expected

Übergebe ich nicht mit @var einen pointer auf var? Das ist dann zwar ein long, aber dafür hab ich doch im Kopf der Procedur den *, damit er weiß, dass ein Pointer kommt?
Über die Struktur werd' ich's nochmal separat probieren, mach das ganze m.E. aber etwas kompliziert.

Verfasst: 29.09.2004 19:41
von Falko
Dann fehlt vermutlich am Anfang des Codes noch folgender Teil.

Code: Alles auswählen

Structure STRING
 s.s
EndStructure
MfG Falko

Verfasst: 29.09.2004 19:48
von Deeem2031
Falko hat geschrieben:Dann fehlt vermutlich am Anfang des Codes noch folgender Teil.

Code: Alles auswählen

Structure STRING
 s.s
EndStructure
MfG Falko
STRING ist doch eine vordefinierte Structure...

Verfasst: 29.09.2004 19:52
von lrhe
Na, hoffentlich missverstehen wir uns da nicht: will einfach nur einen String, deklariert im o.g. Beispiel über str.s mittels Pointer an eine Funktion zur Bearbeitung übergeben. Da ist vielleicht nur ein Schreibfehler?!
Wie holt ihr euch denn mehrere Funktionsergebnisse zurück? Nur über globale Variablen, die in der Prozedur weitergelten? Das will ich vermeiden, da ich verschiedene Stringvariablen an die eine Funktion übergeben will.
Gruß,
Lutz

Verfasst: 29.09.2004 20:01
von Falko
Deeem2031 hat geschrieben:
Falko hat geschrieben:Dann fehlt vermutlich am Anfang des Codes noch folgender Teil.

Code: Alles auswählen

Structure STRING
 s.s
EndStructure
MfG Falko
STRING ist doch eine vordefinierte Structure...
Ich habe mir den Ordner Purebasic "CD TOPO-Version Ver. 3.3" mal auf meine Platte kopiert und den obigen Code ausgeführt. Danach ist .STRING
nicht in einer Structure definiert und deshalb der Fehler. Fügt man die Structur unter PB 3.3 hinzu, arbeitet es genauso wie in PB 3.91.

MfG Falko

Verfasst: 29.09.2004 20:12
von lrhe
Hui, hab grad geantwortet aber sie taucht nicht auf, passiert sowas ab und zu?

Also, ihr seid Helden!!! :D
Es klappt mit der Struktur .STRING und dem PeekS. Aber ganz normal ist das doch nicht, was man da für Verrenkungen tun muss. Nun, funktionieren tut's.
Gibt's so'n Trick mit der Struktur auch für Array's oder LinkedLists?

Nochmal vielen Dank!
Lutz

Verfasst: 29.09.2004 20:50
von NicTheQuick
Bei Arrays ist es ganz einfach Werte zu ändern.

Aber erstmal ein Beispiel um mehrere Werte von einer Procedure zurückzubekommen. Sinnlos, aber sicherlich nützlich. (Hmmm, unlogischer Satz)

Code: Alles auswählen

Structure IR_Ex
  Text.s
  Length.l
  Ok.l
EndStructure
Procedure InputRequester_Ex(Title.s, Message.s, DefaultString.s, *Out.IR_Ex)
  Protected Result.s
  Result.s = InputRequester(Title, Message, DefaultString)
  If *Out
    *Out\Text = Result
    *Out\Length = Len(Result)
    If *Out\Length
      *Out\Ok = #True
    Else
      *Out\Ok = #False
    EndIf
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

InputRequester_Ex("Hallo", "Gib was ein.", "(da steht nix)", @Result.IR_Ex)

If Result\Ok
  MessageRequester("Hallo", "Es wurde folgender Text eingegeben:" + #LFCR$ + Result\Text + #LFCR$ + "Er hat die Länge " + Str(Result\Length) + " Bytes.")
Else
  MessageRequester("Hallo", "Es wurde nichts eingegeben")
EndIf
Und hier nun das Beispiel für Arrays:

Code: Alles auswählen

#Entries = 10

Structure TestStruc
  Long.l
  String.s
  Float.f
EndStructure

Dim Array.TestStruc(#Entries - 1)

Procedure ReadArray(*Array.TestStruc, Entries.l)
  While *Array And Entries
    Debug *Array\Long
    Debug *Array\String
    Debug *Array\Float
    Entries - 1
    *Array + SizeOf(TestStruc)
  Wend
EndProcedure

Procedure WriteArray(*Array.TestStruc, Entries.l)
  Protected a.l
  While *Array And Entries
    a + 1
    *Array\Long = a
    *Array\String = "Value: " + Str(a)
    *Array\Float = 1 / a
    *Array + SizeOf(TestStruc)
    Entries - 1
  Wend
EndProcedure

WriteArray(@Array(), #Entries)
ReadArray(@Array(), #Entries)
Bei LinkedLists ist es problematisch, da du hier nur auslesen und ändern kannst, aber keine Elemente hinzufügen oder löschen kannst. Das geht höchstens bedingt. Aber diese Bedingung will ich hier erstmal nicht aufführen. Du kannst dir auch mal anschauen, was ich dir mit der Konstanten [c]#Modus[/c] sagen will.

Code: Alles auswählen

#Entries = 10

Structure TestStruc
  Long.l
  String.s
  Float.f
EndStructure

NewList LL.TestStruc()

For a.l = 1 To #Entries
  If AddElement(LL())
    LL()\Long = a
    LL()\String = "Value: " + Str(a)
    LL()\Float = 1 / a
  EndIf
Next

Procedure ReadLinkedList(*FirstElement.TestStruc)
  While *FirstElement <> 8
    Debug *FirstElement\Long
    Debug *FirstElement\String
    Debug *FirstElement\Float
    *FirstElement = PeekL(*FirstElement - 8) + 8
  Wend
EndProcedure

Procedure ChangeLinkedList(*FirstElement.TestStruc)
  While *FirstElement <> 8
    *FirstElement\Long * 100
    *FirstElement\String = "Value: " + Str(a)
    *FirstElement\Float = 1 / *FirstElement\Long
    *FirstElement = PeekL(*FirstElement - 8) + 8
  Wend
EndProcedure

#Modus = 0


If #Modus
  ReadLinkedList(FirstElement(LL()) + 8)
Else
  FirstElement(LL())
  ReadLinkedList(@LL())
EndIf

If #Modus
  ChangeLinkedList(FirstElement(LL()) + 8)
Else
  FirstElement(LL())
  ChangeLinkedList(@LL())
EndIf

Debug "----------------------------------------"
If #Modus
  ReadLinkedList(FirstElement(LL()) + 8)
Else
  FirstElement(LL())
  ReadLinkedList(@LL())
EndIf
Viel Spaß! :allright: