String ByReference an Procedure übergeben

Anfängerfragen zum Programmieren mit PureBasic.
nalor
Beiträge: 10
Registriert: 29.06.2009 15:48

String ByReference an Procedure übergeben

Beitrag 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!
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String ByReference an Procedure übergeben

Beitrag 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
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: String ByReference an Procedure übergeben

Beitrag 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.
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
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String ByReference an Procedure übergeben

Beitrag 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.
Zuletzt geändert von ts-soft am 08.04.2010 18:32, insgesamt 1-mal geändert.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: String ByReference an Procedure übergeben

Beitrag 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
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
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String ByReference an Procedure übergeben

Beitrag von ts-soft »

Ich dachte der Stringmanager erfaßt die neue länge, dem ist aber anscheinend nicht so.
Also gehts nicht /:->
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: String ByReference an Procedure übergeben

Beitrag 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:
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
Little John

Re: String ByReference an Procedure übergeben

Beitrag 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
Benutzeravatar
al90
Beiträge: 1101
Registriert: 06.01.2005 23:15
Kontaktdaten:

Re: String ByReference an Procedure übergeben

Beitrag 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)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: String ByReference an Procedure übergeben

Beitrag 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)
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten