Seite 1 von 3

Programmier Tipps und Tricks

Verfasst: 17.09.2005 18:40
von PAMKKKKK
Ich mach hier mal eine Sammlung von meinen (kleinen) Programmiertricks für Anfänger mit PB.
Ich hoffe das macht ein Board Admin Sticky!

Mehrere Zeilen Kommentieren
Wer sich schon einmal darüber geärgert hat, das man in PB nicht mehrere Zeilen Kommentieren kann.
Hier ist eine einfache sehr Lösung ohne vor jede Zeile Semikolons zu setzen.
Mit CompilerIf 1=2 (ergibt False) werden die nachfolgendenZeilen nicht ausgeführt bis CompilerEndIf auftaucht.
Wenn man die Zeilen wieder braucht ändert man die Zeile in CompilerIf 1=1 (ergibt True)

Code: Alles auswählen

CompilerIf 1=2
  ; Code wird nicht ausgeführt und nicht kompiliert
  ; Code wird nicht ausgeführt und nicht kompiliert
  ; Code wird nicht ausgeführt und nicht kompiliert
  ; Code wird nicht ausgeführt und nicht kompiliert
CompilerEndIf

Code: Alles auswählen

CompilerIf 1=1 
  ; Code wird ausgeführt und kompiliert
  ; Code wird ausgeführt und kompiliert
  ; Code wird ausgeführt und kompiliert
  ; Code wird ausgeführt und kompiliert
CompilerEndIf
-------------------------------------------------------

IF NOT
PureBasic hat ja nun mal keinen NOT Operator bei IF abfragen.
Da in PureBasic auch negative Werte True sind, und nur die 0 als False gewertet wird (Das sollte mal in die PB Hilfe geschrieben werden!!), kann man bei Rückgabewerten aus Funktionen Testen ob die Funktion 0 zurückgibt.
Beispiel:

Code: Alles auswählen

If OpenWindow(2, 100, 100, 200, 100, #PB_Window_SystemMenu, "Window") = 0
  MessageRequester("Fehler", "Fenster konnte nicht geöffnet werden!", #MB_OK|#MB_ICONERROR)
  End ; oder ErrorHandler()
EndIf 
Bei dieser Schreibweise ist das IF und ENDIF nahe beisammen.

Man kann sich auch sein eigenes NOT basteln:

Code: Alles auswählen

  Procedure Not(expression) 
    if expression ; ACHTUNG auch negative Werte sind TRUE!!!!!
      ProcedureReturn 0 
    else 
      ProcedureReturn 1 ; Nur True wenn  expression = 0
    endif 
  EndProcedure 
  ; 
  a.l = 0 
  If Not(a.l) 
    PrintN("false") 
  Endif 
EndIf 
(Quelle: http://www.xs4all.nl/~bluez/datatalk/pure1.htm#top)

Die oberen Beispiele Funktionieren aber nicht, wenn man mehrere abfragen mir AND oder OR verknüpft.
Da hilft es dann nur noch den ELSE Zweig zu missbrauchen.
Das Funktioniert immer mit jeder IF variante

Code: Alles auswählen

If a=10 And b>=10 And c=20
Else
  MessageRequester("NOT !","Es ist NICHT a=10 And b>=10 And c=20")
EndIf 

test = 0
If test
Else
  MessageRequester("If test","test ist NOT TRUE")
EndIf 

-------------------------------------------------------


Debuging
Da PureBasic Variablen nicht Automatisch umwandelt (Casted), muss man beim Debuggen immer Zahlen in Strings wandeln,( mit STR(), STRF() usw….).Wen das ein bisschen nervt der kann das in zwei Zeilen Schreiben:

Code: Alles auswählen

 ; Schreibweise in einer Zeile
test = 5
Debug "Der Wert von test ist = " + Str(test)

;Schreibweise in 2 Zeilen
test = 7
Debug "Wert von test:"
Debug test 

Wenn ihr auch noch Tips habt dann schreibt sie hier. Wir sammel Sie

Verfasst: 08.10.2005 20:56
von AndyX
Die Variablen werden eigentlich schon gecastet. nur halt nicht String zu Zahl und umgekehrt.

If-ElseIf / Select-Case

Lieber

Code: Alles auswählen

If bla
  bla()
Elseif blaaaa
  Baaaa()
.....
statt

Code: Alles auswählen

Select blaaaaaa
  Case bla
  case Ballllllllaaaaa
    blaaaaaa()
.........
nutzen. Is viel schneller.

Außerdem gibts ja noch diese Lösung:

Code: Alles auswählen

Procedure MachWas()
  Print("Ich mach was")
EndProcedure
Procedure GibWasAus(bla.s)
  Print("Ich gebe aus: "+bla)
EndProcedure

Dim Table(1)
Table(0) = @MachWas()
Table(1) = @GibWasAus()

OpenConsole()
input$ = Input()
If input$ = ""
  CallFunctionFast(Table(0))
ElseIf
  CallFunctionFast(Table(1),input$)
Endif
Das hat mir ein Kumpel empfohlen, habs noch nicht genau testen können, obs schneller ist.

Verfasst: 20.04.2006 10:18
von #NULL
hab hier mal was kleines banales für alle, die von ständgigem

Code: Alles auswählen

If InitOderOpenIrgendwas()=0
  MessageRequesterUndDieZeileWillNichEnden(.....)
  End
EndIf
genervt sind:

Code: Alles auswählen

Procedure check(value.l, text.s)
	If value=0
		MessageRequester("error", text, 0)
		End
	EndIf
EndProcedure
damit kann man ein bisschen platz sparen, z.b so :

Code: Alles auswählen

check( InitSprite(), "initsprite() failed")
check( InitKeyboard(), "initkeyboard() failed")
       OR auch so
win1Nr.l=OpenWindow(#PB_Any,50,50,#Win1Width,#Win1Height,#PB_Window_SystemMenu,"window")
check( win1Nr, "openwindow() failed")
       OR auch so
shape1 = LoadSprite(#PB_Any, "shape1.bmp")
check(shape1, "'shape1.bmp' not loaded")
wenn man kein #PB_Any benutzt und den rückgabewert nicht speichern muss gehts soger in einer zeile.
[is nix dolles/ ich hoffe ich werde für mein erstes posting im forum nich gleich ausgelacht :]

man könnte die procedure ja auch den rückgabewert weiterreichen lassen

Code: Alles auswählen

sprite = check( LoadSprite(#PB_Any,"sprite.bmp"), "LADEFEHLERBLA!")
....
<edit 27.05 18:58>
momentan benutze ich die funktion so:

Code: Alles auswählen

Procedure.l check(value.l, text.s)
	If value=0 And MessageRequester("error", text + Chr(10) + "exit program?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
			End
	Else
		ProcedureReturn value
	EndIf
EndProcedure

Verfasst: 01.08.2006 07:53
von #NULL
eine erdnuß zum messen von zeitverbrauch:

Code: Alles auswählen

Procedure t(s.s)
  Static t.l
  Static switch.l
  If switch=0
    t=ElapsedMilliseconds()
  Else
    Debug s+": "+Str(ElapsedMilliseconds()-t)
  EndIf
  switch!1
EndProcedure

um z.b. den zeitverbrauch einer proc zu messen

Code: Alles auswählen

t("")
drawMap()
t("dm")
...aber schachteln geht natürlich in der form nicht.

Verfasst: 01.08.2006 10:00
von Olaf
Zeitmessen mal Prozedurabhängig:

Code: Alles auswählen

Global Dim ProcedureTime(1)
Global ID=1

Procedure TimeProcedureNeeded(ProcedureIdentifier)
  If ProcedureIdentifier>ID
    ID=ProcedureIdentifier
    ReDim ProcedureTime(ID)
  EndIf
  If ProcedureTime(ProcedureIdentifier)=0
    ProcedureTime(ProcedureIdentifier)=ElapsedMilliseconds()
  Else
    TimeNeeded=ElapsedMilliseconds()-ProcedureTime(ProcedureIdentifier)
    ProcedureTime(ProcedureIdentifier)=0
  ProcedureReturn TimeNeeded
  EndIf
EndProcedure
Aufruf:

Code: Alles auswählen

Procedure DoThis()
  For x=0 To 9
    Delay(100)
  Next x
EndProcedure

TimeProcedureNeeded(@DoThis())
DoThis()
Debug TimeProcedureNeeded(@DoThis())

Verfasst: 01.08.2006 12:08
von #NULL
versteh ich da was falsch? oder warum erstelltst du ein array mit z.b. 4 mio elementen für einen einzigen aufruf?
mit einfachen zahlen wie 1,2,3.. als parameter geht's ja auch.
ausserdem, woher willst du wissen, ob bei einem zweiten geschachtelten aufruf eine andere proc-adresse höher ist?

Verfasst: 01.08.2006 12:45
von Kiffi
Hier noch ein netter Tipp, der zeigt, wie sich verschiedenene Zugriffe auf ein
mehrdimensionales Array auf die Geschwindigkeit auswirken kann:

http://www.purebasic.fr/english/viewtopic.php?t=22909

Grüße ... Kiffi

Verfasst: 15.06.2007 19:08
von coMstructor
So, da hab ich nun auch ein Paar kleine Tipps für euch:

Link

Verfasst: 15.06.2007 19:36
von ts-soft
coMstructor hat geschrieben:So, da hab ich nun auch ein Paar kleine Tipps für euch:

Link
:allright: , aber "Länge der Variablennamen" sollte doch geändert werden.
Die Empfehlung ist von 1990 und dank Autovervollständigung usw. hat das
Wohl nicht mehr seine Berechtigung. Für lokale Variablen in Proceduren kann
man es so halten, aber bei globalen Variablen halte ich längere Namen eher
für Empfehlenswert.

PS: Aber eigentlich fällt mir Deine etwas zu grosse Signatur auf, wäre nett
wenn Du das Bild etwas verkleinern würdest, danke

Verfasst: 31.03.2008 01:42
von NicTheQuick
Wenn man ein statisches Array in einer Structure trotzdem mit "dynamischer"
Größe haben will, muss man sich mit 'AllocateMemory()' und einem
Dummy-Structure-Element behelfen, während man dem statischen Array
selbst die Größe Null gibt. Nur dann beschwert sich der Debugger nicht.
Würde man das statische Array von Anfang an z.B. auf 100000 Elemente
festlegen und irgendwann im Programmverlauf würden dynamisch doch mal
mehr als 100000 Element genutzt, würde sich der Debugger beschweren.
Mit folgender Methode passiert das nicht mehr.

Code: Alles auswählen

Structure arr
  StructureUnion
    arr.l[0] ;statisches Array auf Größe Null festlegen
    dummy.l ;Dummy-Element, damit die Struktur eine Größe hat
  EndStructureUnion
EndStructure

;dynamisch Speicher allokieren
Define *a.arr
*a = AllocateMemory(SizeOf(arr) * 10)

;Füllen
For i = 0 To 9
  *a\arr[i] = i + 1
Next

;Lesen
For i = 0 To 9
  Debug *a\arr[i]
Next