Variablen-Übergabe an Prozedur

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ChristianK
Beiträge: 77
Registriert: 13.12.2004 14:55

Beitrag von ChristianK »

sehr gut!
ChristianK for President
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Dann erklärt mir das mal ???

Code: Alles auswählen

;-- PB 4.02 
EnableExplicit 

Procedure Aendere_String (*str.s) 
   ; mit *str.s wird die Adresse des String-Deskriptors an die Prozedur übergeben 

   *str + " Welt12" 
EndProcedure 

Define text.s 

text = "Hallo" 
Aendere_String(@text) 
Debug text

Code: Alles auswählen

Procedure Aendere_String1 (*str.s) 
   ; mit *str.s wird die Adresse des String-Deskriptors an die Prozedur übergeben 

   *str + " Welt1" 
EndProcedure 

Define text.s 

text = "Hallo" 
Aendere_String1(@text) 
Debug text
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

PureBasic versucht, den String an den Speicher @text anzuhängen. Da der Speicher @text den Pointer zu einem String und nicht den String enthält, klappt das nicht.

Schau hier:

Code: Alles auswählen

Procedure Aendere_String1 (*str.s)
   ; mit *str.s wird die Adresse des String-Deskriptors an die Prozedur übergeben

   *str + " Welt1"
EndProcedure

Define text.s{100}

text = "Hallo"
Aendere_String1(@text)
Debug text 
Little John

Beitrag von Little John »

Leonhard hat geschrieben:

Code: Alles auswählen

Define text.s{100}
Das ist ein anderer Variablentyp. Es ging mir nicht um Strings mit fester Länge. Es ging mir gerade um Strings mit variabler Länge und darum, dass PB sich automatisch um die Speicherverwaltung kümmert.

Ich habe jetzt noch einen anderen Thread im engl. Forum gefunden, wo aktuell das gleiche diskutiert wird. :D Dort ist man auch zu dem Schluss gekommen, dass die hier bisher verfolgten Ansätze für Strings mit variabler Länge nicht funktionieren. iNX meint dort, dass folgendes funktioniere:

Code: Alles auswählen

;-- PB 4.02
EnableExplicit

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

Define text.String

text\s = "Hallo"
Aendere_String(@text)
Debug text\s
Gruß, Little John
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Hallo Leonhard

Du hast in deinem Code auch genügend Platz reserviert
und dann klappt es natürlich !

ich wollte mit meinem Beispiel vor allem zeigen das der letzte Code den Little John gepostet hat nur dann funktioniert, wenn der String, der addiert wird nicht zu groß ist.
PureBasic reserviert für Strings einen Speicherbereich der meistens etwas größer als die Zeichenkette ist und füllt den Rest mit Char-Null auf.
Erst wenn die Addition der beiden Zeichenketten größer als der reservierte Bereich wird, dann erst wird der neu gebildete String verschoben im Speicher.

Beweis:

Code: Alles auswählen

a$="Hallo"
b$="Hallo"
c$="Hallo"

Debug @a$
Debug @b$
Debug @c$

a$="Hallo1"
b$="Hallo2222222222"
c$="Hallo12"

Debug @a$
Debug @b$
Debug @c$
man vergleiche die Adressen ! Beim zweitem Mal zuweisen ändert sich nur die Adresse von b$
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Little John

Beitrag von Little John »

2hjbremer:
Meinst Du, der von mir zuletzt gepostete Code ist OK?

Gruß, Little John
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Little John: ja und eher nein
das hängt eben davon ab wie lang die zu verkettenden Zeichen sind. Wenn Sie zusammen größer als 11 Bytes sind funktioniert es nicht mehr.

ich nehme mal an du willst eine Stringvariable übergeben, diese in der Prozedur ändern und im Hauptprogramm diese Änderung benutzen. Wie in den guten alten Zeiten z.B. unter QuickBasic. Das geht so einfach in PB aber nicht.

Hier ein Beispiel wie es geht:

Code: Alles auswählen

;-- PB 4.02 

Procedure Aendere_String (*str) 
   
   ;weise der lokalen Variablen den übergebenen Text zu
   ;diese Zeile muß sein
   txt$=PeekS(*str)
      
   ;verändere die lokale Variable   
   txt$="HJ sagt " + txt$ + " und muß jetzt ins Bett"
   
   ;übergebe lokale Variable an Variable im Hauptprogramm
   ;und PB erledigt den Rest, soll heißen verschieben des Strings im Speicher
   PokeS(*str, txt$) 
   
EndProcedure 

Define text.s 

text = "Hallo" 
Aendere_String(@text) 
Debug text
Das funktioniert natürlich auch mit 3 oder 4 oder 5 Variablen, egal welchen Typ. Hauptsache der Typ von Peek und Poke stimmt.

Und die Experten würden nun wieder sagen uuuuhhh, das geht auch anders und schneller. Recht haben Sie !!!
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Little John

Beitrag von Little John »

hjbremer hat geschrieben:Little John: ja und eher nein
das hängt eben davon ab wie lang die zu verkettenden Zeichen sind. Wenn Sie zusammen größer als 11 Bytes sind funktioniert es nicht mehr.
Das heißt bei Dir funktioniert der Code nicht? Das überrascht mich jetzt. Bei mir funktioniert er einwandfrei, und die verketteten Strings sind ja zusammen 31 Zeichen lang. Auch mit noch längeren Strings geht es bei mir.
hjbremer hat geschrieben:ich nehme mal an du willst eine Stringvariable übergeben, diese in der Prozedur ändern und im Hauptprogramm diese Änderung benutzen. Wie in den guten alten Zeiten z.B. unter QuickBasic.
Genau.
hjbremer hat geschrieben:Das geht so einfach in PB aber nicht.
Das finde ich sehr irritierend, zumal ich in der Hilfe kein Wort dazu gefunden habe.
hjbremer hat geschrieben:Hier ein Beispiel wie es geht:

Code: Alles auswählen

;-- PB 4.02 

Procedure Aendere_String (*str) 
   
   ;weise der lokalen Variablen den übergebenen Text zu
   ;diese Zeile muß sein
   txt$=PeekS(*str)
      
   ;verändere die lokale Variable   
   txt$="HJ sagt " + txt$ + " und muß jetzt ins Bett"
   
   ;übergebe lokale Variable an Variable im Hauptprogramm
   ;und PB erledigt den Rest, soll heißen verschieben des Strings im Speicher
   PokeS(*str, txt$) 
   
EndProcedure 

Define text.s 

text = "Hallo" 
Aendere_String(@text) 
Debug text
Das funktioniert natürlich auch mit 3 oder 4 oder 5 Variablen, egal welchen Typ. Hauptsache der Typ von Peek und Poke stimmt.
Ich staune dass das geht. Denn das Programm POKEt ja an die Adresse von 'text' im Hauptprogramm. Dort waren aber nur 5 Byte Speicherplatz reserviert.
hjbremer hat geschrieben: Und die Experten würden nun wieder sagen uuuuhhh, das geht auch anders und schneller. Recht haben Sie !!!
Und wie geht es anders und schneller?

Gruß, Little John
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Beitrag von hjbremer »

Hallo Little John:

anders geht es so

Code: Alles auswählen

;-- PB 4.02 

Procedure Aendere_String (*str.s) 
      
   txt$= *str 
   
   x$="HJ sagt " + txt$ + " und muß jetzt ins Bett"   
      
   PokeS(@*str,x$)
   
EndProcedure 

Define text.s 

text = "Hallo" 
Aendere_String(@text) 

MessageRequester("Test", text)
macht im Grunde dasselbe, gefällt mir aber nicht, wegen dem *str.s bei der Übergabe und beim Poke ist der Klammeraffe. Ist mir persönlich irgendwie nicht so einfach und klar genug.

PS: es muß x$="HJ"+... heißen wie im obigen Beispiel und nicht txt$="HJ"+... wie im gestrigen Beispiel. Gibt sonst irgendwann einen Memory-Fehler. Warum ? keine Ahnung !

schneller geht es so:

Code: Alles auswählen

;-- PB 4.02 

Structure Programmvariablen
  name1.s
  name2.s
  usw.l
EndStructure

prgv.Programmvariablen


Procedure Aendere_String (*prgv.Programmvariablen) 
         
   *prgv\name1="HJ sagt " + *prgv\name1 + " und muß jetzt ins Bett"
   *prgv\name2="HJ sagt " + *prgv\name2 + " und muß jetzt ins Bett"
         
EndProcedure 

prgv\name1="Blubb" 
prgv\name2="Hello" 

Aendere_String(prgv) 

MessageRequester("Test", prgv\name1+#CR$+prgv\name2)
aber wenn so, dann finde ich, kann man die Variable prgv gleich als global definieren und braucht den ganzen Zeigerkram nicht.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Little John

Beitrag von Little John »

2hjbremer:

Das gleiche wie Dein letztes Beispiel -- aber in einer "schlankeren" Variante -- hatte ich ja auch schon gepostet:
http://www.purebasic.fr/german/viewtopic.php?p=153521#153521

Du meintest dazu:
wie lang die zu verkettenden Zeichen sind. Wenn Sie zusammen größer als 11 Bytes sind funktioniert es nicht mehr.
... was ich nach wie vor bezweifle.

Gruß, Little John
Antworten