Seite 1 von 2

String ByReference an Procedure übergeben

Verfasst: 08.04.2010 17:56
von nalor
Hallo!

Hoffe es kann mir jemand erklären wie ich einen String ByReference an eine Prozedur übergeben kann - ich möchte einfach den geänderten String dann nach der Rückkehr aus der Prozedur in der Originalen Variable haben (und eben kein ProcedureReturn dafür verwenden).
Meine Versucht über Pointer das gewünschte zu erreichen scheitern leider alle - auch nach Lektüre von http://forums.purebasic.com/german/view ... p?p=247032 bin ich nicht wirklich schlauer.

Hier mein kleines Beispiel:

Code: Alles auswählen

Procedure test_str(*sTest.String)
Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
Debug "P-TEST:"+ *sTest\s
*sTest\s="TEST225555555555555555555555555555555552"

Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
Debug "P-TEST2:"+ *sTest\s

EndProcedure

sText.s
*Text = @sText
*TestString2.String=@*Text

Debug "TEST_STR Anfang: >"+*TestString2\s+"<"
Debug "Adresse: >"+Str(*TestString2)+"<"
Debug "Adresse 2: >"+Str(@*TestString2\s)+"<"
*TestString2\s="123456789"

Debug ""
Debug "TEST_STR Mitte: >"+*TestString2\s+"<"
Debug "Adresse: >"+Str(*TestString2)+"<"
Debug "Adresse 2: >"+Str(@*TestString2\s)+"<"
Debug ""
Debug "Prozedur"
test_str(*TestString2)
Debug "Prozedur Ende"
Debug ""
Debug "TEST_STR Ende: >"+*TestString2\s+"<"
Debug "Adresse: >"+Str(*TestString2)+"<"
Debug "Adresse 2: >"+Str(@*TestString2\s)+"<"

Debug ""
Debug "TEST_STR2 GANZ Ende: >"+sText+"<"
Debug "Adresse: >"+Str(@sText)+"<"
Der in der Prozedur geänderte String ist auch nach dem Ende der Prozedur schön über "*TestString2\s" ansprechbar - aber wie kriege ich den dann wieder in sText rein? Man sieht im Debugger dass die Speicherverwaltung die Stringadresse verändert weil der String länger wird... daher klappts am Ende mit sText dann nicht mehr. Hoffe es hat da jemand eine Idee dazu.

Meine erst Idee war eigentlich die hier:

Code: Alles auswählen

Procedure test_str(*sTest.String)
Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
Debug "P-TEST:"+ *sTest\s
*sTest\s="TEST225555555555555555555555555555555552"

Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
Debug "P-TEST2:"+ *sTest\s

EndProcedure

sText.s
*Text = @sText

*TestString2.String=@*Text

Debug "TEST_STR Anfang: >"+sText+"<"
Debug "Adresse: >"+Str(@sText)+"<"
*Text=@sText
Debug "Adresse 2: >"+Str(@*Text)+"<"
sText="123456789"

Debug ""
Debug "TEST_STR Mitte: >"+sText+"<"
Debug "Adresse: >"+Str(@sText)+"<"
*Text=@sText
Debug "Adresse 2: >"+Str(@*Text)+"<"
Debug ""
Debug "Prozedur"
test_str(@sText)
Debug "Prozedur Ende"
Debug ""
Debug "TEST_STR Ende: >"+sText+"<"
Debug "Adresse: >"+Str(@sText)+"<"
*Text=@sText
Debug "Adresse 2: >"+Str(@*Text)+"<"
Aber auch wenn es mir irgendwie einfacher erscheinen würde die Variablenadresse einfach mit "@Variablenname" an die Prozedur zu übergeben - so funktioniert es leider überhaupt nicht: "Ungültiger Speicherzugriff" in der Prozedur :(

Kann zwar die Prozedur etwas verändern

Code: Alles auswählen

Procedure test_str(*sTest.String)
Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
*Test.String=@*sTest

Debug "P-TEST:"+ *Test\s
*Test\s="TEST225555555555555555555555555555555552"

Debug "P-Adresse Proc1: >"+Str(*sTest)+"<"
Debug "P-Adresse Proc2: >"+Str(@*sTest\s)+"<"
Debug "P-TEST2:"+ *Test\s
und kriege dann keinen ungültigen Speicherzugriff mehr - aber nach der Rückkehr aus Prozedur befindet sich trotzdem nur Müll in sText....

Wie gehts richtig? Stehe da irgendwie auf der Leitung!

Danke!

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:10
von ts-soft
wenns denn kein poke sein soll:

Code: Alles auswählen

Procedure StringByRef(*string)
  Protected *mystring.String = @*string
  Debug *mystring\s
  *mystring\s = "Hallo die Enten"
EndProcedure

Define.s test = "bla"

StringByRef(@test)
Debug test

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:20
von STARGÅTE
nee TS das geht nicht, denn der Pointer des eigentlichen Strings ändert sich:
Wenn man zB in der Procedure was sehr langes schreibt.

Code: Alles auswählen

Procedure StringByRef(*string)
  Protected *mystring.String = @*string
  Debug *mystring\s
  *mystring\s = "bla"+space(100000)
EndProcedure

Define.s test = "bla"
StringByRef(@test)
Debug test
Daher muss man die Position des Pointers selber übergeben, damit er ggf verändert werdne kann:
Aber diesen Pointer kann man leider nicht einfach der urspünglichen Variable zuweisen.

Ich würde halt mit FIX-Strings arbeiten, das ist am einfachsten.

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:25
von ts-soft
Was geht denn daran nun nicht. Dein Code funtioniert genauso wie mein Snippet
und der Purifier zeigt auch kein Überschreiben von Speicher an, den der Stringmanager
ja automatisch erweitern sollte.

Solange es keine ProcedureDLL ist sollte es IMHO funktionieren.

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:32
von STARGÅTE
Was geht denn daran nun nicht.
Ähh, test ist nach dem beschreiben von 100'000 Leerzeichen leer !

wenns bei mir nicht so ist, hast du glück weil eben platz war ...

In der Procedure, wird nur die Variable *string
verändert, aber nicht außen das @test
und damit wird test ungültig

Es wird also nix irgendwo überschrieben oder erzeugt ein IMA, aber der Pointer von test wo der String stand ist nicht mehr da

Hier noch mal mit mehr Zeichen:

Code: Alles auswählen

Procedure StringByRef(*string)
  Protected *mystring.String = @*string
  Debug "Übergabe: "+Str(*string)
  Debug "Länge innerhalb:"+Str(Len(*mystring\s))
  *mystring\s = "bla"+space(10000000)
  Debug "Nach verändern: "+Str(*string)
  Debug "Länge innerhalb:"+Str(Len(*mystring\s))
EndProcedure

Define.s test = "bla"
Debug "Länge außerhalb:"+Str(Len(test))
StringByRef(@test)
Debug "Länge außerhalb:"+Str(Len(test))
Länge außerhalb:3
Übergabe: 4005544
Länge innerhalb:3
Nach verändern: 42926112
Länge innerhalb:10000003
Länge außerhalb:0

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:40
von ts-soft
Ich dachte der Stringmanager erfaßt die neue länge, dem ist aber anscheinend nicht so.
Also gehts nicht /:->

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:45
von STARGÅTE
eben, und man kann der Variable test welche ein String hat, nicht "einfach sagen" sei mal woanders ^^

Denn @test gibt mir ja den Pointer zum String selber, und nicht den Pointer, zur Stelle wo der Pointer zum String steht :coderselixir:

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:56
von Little John
Das letzte Mal als diese Diskussion aufkam, war meines Wissens das Ergebnis wie folgt:

Code: Alles auswählen

Procedure AendereString (*str.String)
   *str\s + " Welt 12345678901234567890"
EndProcedure

Define text.String
text\s = "Hallo"
AendereString(@text)
Debug text\s                  ; zeigt Hallo Welt 12345678901234567890
Gruß, Little John

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 18:56
von al90
Mal ne bescheidene Frage: Warum nicht einfach Global ? Oder habe ich jetzt was Falsch verstanden ?

BTW: Ich bezog mich jetzt mal auf das hier:
nalor hat geschrieben:ich möchte einfach den geänderten String dann nach der Rückkehr aus der Prozedur in der Originalen Variable haben (und eben kein ProcedureReturn dafür verwenden)

Re: String ByReference an Procedure übergeben

Verfasst: 08.04.2010 19:00
von ts-soft
Danke "kleiner Jonny", sieht gut aus:

Code: Alles auswählen

Procedure  AendereString (*str.String)
  *str\s + " Welt 12345678901234567890" + Space(1000000) + "#"
EndProcedure

Define text.String
text\s = "Hallo"
AendereString(@text)
Debug text\s                  ; zeigt Hallo Welt 12345678901234567890 
Debug Len(text\s)
Debug Right(text\s, 1)