Programmier Tipps und Tricks

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
PAMKKKKK
Beiträge: 321
Registriert: 21.04.2005 22:08
Wohnort: Braunschweig
Kontaktdaten:

Programmier Tipps und Tricks

Beitrag 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
Wir Schreiben ein PureBasic Buch.
Auch du kannst mitmachen!
http://www.purearea.net/pb/english/pure ... :Main_Page
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag 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.
Benutzeravatar
#NULL
Beiträge: 2220
Registriert: 20.04.2006 09:50

Beitrag 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
Benutzeravatar
#NULL
Beiträge: 2220
Registriert: 20.04.2006 09:50

Beitrag 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.
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Olaf
Beiträge: 117
Registriert: 20.04.2006 14:51
Wohnort: 66606 St.Wendel (Niederlinxweiler, Dr.Albert-Schweitzer-Str.9)
Kontaktdaten:

Beitrag 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())
PB 4.xx (Windows & Linux & Mac OS X)
Treffen sich 2 Kurven in der Unendlichkeit. Sagt die eine zur anderen: "Hau ab aus meinem Definitionsbereich oder ich leite dich ab!"
Darauf die andere: "Mach nur! Ich bin die e-Funktion." :lol:
Benutzeravatar
#NULL
Beiträge: 2220
Registriert: 20.04.2006 09:50

Beitrag 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?
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Kiffi
Beiträge: 10443
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag 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
"tja" – a German reaction to the apocalypse, Dawn of the Gods, nuclear war, an alien attack or no bread in the house
Benutzeravatar
coMstructor
Beiträge: 130
Registriert: 04.07.2006 20:10
Kontaktdaten:

Beitrag von coMstructor »

So, da hab ich nun auch ein Paar kleine Tipps für euch:

Link
Zuletzt geändert von coMstructor am 17.06.2007 20:22, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22291
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

Beitrag 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
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
NicTheQuick
Ein Admin
Beiträge: 8394
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 20.10
NVIDIA Quadro P2200
Wohnort: Saarbrücken
Kontaktdaten:

Beitrag 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
Bild
Antworten