Gültigen VariablenNamen erkennen.

Du brauchst Grafiken, gute Programme oder Leute die dir helfen? Frag hier.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Gültigen VariablenNamen erkennen.

Beitrag von cxAlex »

Servus zusammen.

Ich sucher derzeit nach einer Funktion mit der man schnell erkennen kann ob eine Variable C/PB - Konform ist. d.h. sie darf aus a-z,A-Z,0-9 und _ bestehen und nicht mit einer Zahl beginnen. Die Länge des Namens spielt keine Rolle und wir nehmen auch einmal an das sie kein Pointer ist (kein *).

Ich hab bereits eine, meiner Meinung nach, schnelle Funktion geschrieben.
Nun frage ich ich mich: Geht es noch schneller? Ich wüsste keine schnellere Methode ausser vielleicht in Assembler, aber dazu reichen meine Kentnisse nicht aus. Die Funktion ist zeitkritisch, kann sein das sie einige millionen mal aufgerufen werden muss.

Hier ist mein Code, vielleich kann ihn noch jemand optimieren:

Code: Alles auswählen

Macro isValidChar(_Char)
  ; Gültige Zeichen
  ((_Char<58) And (_Char>47)) Or ((_Char<123) And (_Char>96)) Or ((_Char<91) And (_Char>64)) Or _Char = 95
EndMacro

Procedure isValidVariableName(*VarMem.Character)
  If *VarMem\c<58 And *VarMem\c>47 ; Keine Zahlen am Anfang
    ProcedureReturn 0
  EndIf
  While *VarMem\c
    If Not isValidChar(*VarMem\c) ; Jedes Zeichen prüfen.
      ProcedureReturn 0
    EndIf
    *VarMem + 1
  Wend
  ProcedureReturn 1 ; Variable ist ok
EndProcedure


time = ElapsedMilliseconds()
For i = 1 To 100000
  isValidVariableName(@"_char1")
  isValidVariableName(@"0invlaid")
  isValidVariableName(@"sehrlangername")
Next

Debug ElapsedMilliseconds()-time
Danke schon im vorraus, cxAlex
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7035
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

ich würde das aber dann mit Regulären Ausdrücken machen:

Und auf folgenden String Prüfen:

"\w*"

\w sind genau die Zugelassenene Zeichen ...
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

Beitrag von ts-soft »

Mußte nochmal prüfen, ist aber mehr als doppelt so schnell, wenns stimmen
sollte :mrgreen:

Code: Alles auswählen

Procedure isValidVariableName(*VarMem.Character)
  If *VarMem\c < 58 And *VarMem\c > 47 ; Keine Zahlen am Anfang
    ProcedureReturn 0
  EndIf
  While *VarMem\c
      Select *VarMem\c
        Case 48 - 57, 65 - 90, 97 - 122, 95
        Default
          ProcedureReturn 1
      EndSelect
    *VarMem + 1
  Wend
  ProcedureReturn 1 ; Variable ist ok
EndProcedure
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
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

@ts-soft:

leider ergibt bei deinem Algo folgender Code 'True' :

Code: Alles auswählen

Debug isValidVariableName(@"#!°")
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7035
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

Hier ein Beispiel:

Code: Alles auswählen

CreateRegularExpression(0, "^[a-zA-Z_]\w*\w?$")

Procedure isValidVariableName(Variable$)
 ProcedureReturn MatchRegularExpression(0, Variable$)
EndProcedure

 Debug isValidVariableName("_char1") 
 Debug isValidVariableName("0invlaid") 
 Debug isValidVariableName("sehrlangername") 
 Debug isValidVariableName("BöserName") 
 Debug isValidVariableName("großerName") 
 Debug isValidVariableName("x") 
 Debug isValidVariableName("1") 
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
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

cx 3307
regex 21248
ts 483

Code: Alles auswählen

#n = 10000000

Global regex = CreateRegularExpression(#PB_Any,"^[a-z_][a-z0-9_]*$",1)

Procedure isValidVariableName2(Var.s) 
  If MatchRegularExpression(regex,Var)
    ProcedureReturn #True 
  EndIf   
EndProcedure 


Macro isValidChar(_Char) 
  ; Gültige Zeichen 
  ((_Char<58) And (_Char>47)) Or ((_Char<123) And (_Char>96)) Or ((_Char<91) And (_Char>64)) Or _Char = 95 
EndMacro 

Procedure isValidVariableName(*VarMem.Character) 
  If *VarMem\c<58 And *VarMem\c>47 ; Keine Zahlen am Anfang 
    ProcedureReturn 0 
  EndIf 
  While *VarMem\c 
    If Not isValidChar(*VarMem\c) ; Jedes Zeichen prüfen. 
      ProcedureReturn 0 
    EndIf 
    *VarMem + 1 
  Wend 
  ProcedureReturn 1 ; Variable ist ok 
EndProcedure 

Procedure isValidVariableName3(*VarMem.Character) 
  If *VarMem\c < 58 And *VarMem\c > 47 ; Keine Zahlen am Anfang 
    ProcedureReturn 0 
  EndIf 
  While *VarMem\c 
      Select *VarMem\c 
        Case 48 - 57, 65 - 90, 97 - 122, 95 
        Default 
          ProcedureReturn 1 
      EndSelect 
    *VarMem + 1 
  Wend 
  ProcedureReturn 1 ; Variable ist ok 
EndProcedure

t0 = ElapsedMilliseconds() 
For i = 1 To #n
  isValidVariableName(@"_char1") 
  isValidVariableName(@"0invlaid") 
  isValidVariableName(@"sehrlangername") 
Next 
t0 = ElapsedMilliseconds() - t0

t1 = ElapsedMilliseconds() 
For i = 1 To #n
  isValidVariableName2("_char1") 
  isValidVariableName2("0invlaid") 
  isValidVariableName2("sehrlangername") 
Next 
t1 = ElapsedMilliseconds() - t1

t2 = ElapsedMilliseconds() 
For i = 1 To #n
  isValidVariableName3(@"_char1") 
  isValidVariableName3(@"0invlaid") 
  isValidVariableName3(@"sehrlangername") 
Next 
t2 = ElapsedMilliseconds() - t2

MessageRequester("",Str(t0)+#LF$+Str(t1)+#LF$+Str(t2))  
Regex macht zwar viele Sachen viel einfacher, ist aber auch um einiges
langsamer.
Zuletzt geändert von edel am 30.09.2008 16:52, insgesamt 2-mal geändert.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7035
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

@edel

pass mal deine Abfrage an (zB wie meine), denn sonst bekommt "GroßeVar" auch ein TRUE

EDIT : und große Buchstaben werden bei dir nun auch FALSE
A-Z fehlt noch :wink:
Zuletzt geändert von STARGÅTE am 30.09.2008 16:54, insgesamt 1-mal geändert.
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
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Stimmt, hier sollte von Anfang bis Ende geprueft werden.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Ich hab jetzt mal ts´ Code angepasst das er auch funktioniert.

Code: Alles auswählen

Select *VarMem\c
  Case 48 - 57, 65 - 90, 97 - 122, 95
Default
  ProcedureReturn 1
EndSelect 
war falsch, richtig:

Code: Alles auswählen

Select *VarMem\c
  Case 48 To 57, 65 To 90, 97 To 122, 95
Default
  ProcedureReturn 0
EndSelect 
Neu ergebnisse nach edels` Code:
ts 1500
cx 1765
regex 8516
ts ist schneller, gehts noch flotter?

TestCode:

Code: Alles auswählen

#n = 10000000

Global regex = CreateRegularExpression(#PB_Any,"[a-z_][a-z0-9_]*",1)

Procedure isValidVariableName2(Var.s)
  If MatchRegularExpression(regex,Var)
    ProcedureReturn #True
  EndIf   
EndProcedure


Macro isValidChar(_Char)
  ; Gültige Zeichen
  ((_Char<58) And (_Char>47)) Or ((_Char<123) And (_Char>96)) Or ((_Char<91) And (_Char>64)) Or _Char = 95
EndMacro

Procedure isValidVariableName(*VarMem.Character)
  If *VarMem\c<58 And *VarMem\c>47 ; Keine Zahlen am Anfang
    ProcedureReturn 0
  EndIf
  While *VarMem\c
    If Not isValidChar(*VarMem\c) ; Jedes Zeichen prüfen.
      ProcedureReturn 0
    EndIf
    *VarMem + 1
  Wend
  ProcedureReturn 1 ; Variable ist ok
EndProcedure

Procedure isValidVariableName3(*VarMem.Character)
  If *VarMem\c < 58 And *VarMem\c > 47 ; Keine Zahlen am Anfang
    ProcedureReturn 0
  EndIf
  While *VarMem\c
      Select *VarMem\c
        Case 48 To 57, 65 To 90, 97 To 122, 95
        Default
          ProcedureReturn 0
      EndSelect
    *VarMem + 1
  Wend
  ProcedureReturn 1 ; Variable ist ok
EndProcedure

t0 = ElapsedMilliseconds()
For i = 1 To #n
  isValidVariableName(@"_char1")
  isValidVariableName(@"0invlaid")
  isValidVariableName(@"sehrlangername")
Next
t0 = ElapsedMilliseconds() - t0

t1 = ElapsedMilliseconds()
For i = 1 To #n
  isValidVariableName2("_char1")
  isValidVariableName2("0invlaid")
  isValidVariableName2("sehrlangername")
Next
t1 = ElapsedMilliseconds() - t1

t2 = ElapsedMilliseconds()
For i = 1 To #n
  isValidVariableName3(@"_char1")
  isValidVariableName3(@"0invlaid")
  isValidVariableName3(@"sehrlangername")
Next
t2 = ElapsedMilliseconds() - t2

MessageRequester("","cx "+Str(t0)+#LF$+"ts "+Str(t1)+#LF$+"regex "+Str(t2)) 
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
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

Beitrag von ts-soft »

cxAlex hat geschrieben:@ts-soft:

leider ergibt bei deinem Algo folgender Code 'True' :

Code: Alles auswählen

Debug isValidVariableName(@"#!°")
Sowas hab ich vermutet, hab leider keine zeit und lust zu testen, aber den
Ansatz mit Select sollteste Dir mal durch den Kopf gehen lassen, könnte
schneller sein. :wink:

// edit
zu langsam, hat sich erledigt :lol:
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