NextDatabaseRow() --> Stack Overflow

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
zigapeda
Beiträge: 1753
Registriert: 06.03.2005 17:22
Wohnort: Kaufbeuren
Kontaktdaten:

NextDatabaseRow() --> Stack Overflow

Beitrag von zigapeda »

Moin

Ich bekomm hier bei dem Befehl NextDatabaseRow() einen stack overflow.
Der Fehler ist reproduzierbar und zwar nur wenn der Befehl hinter einem If oder einer Variable steht

Code: Alles auswählen

If NextDatabaseRow(#db)
oder

Code: Alles auswählen

temp = NextDatabaseRow(#db)
und ich versuche aus einer leeren Tabelle daten abzufragen

Code: Alles auswählen

select * from table limit 30 offset 0
Wenn ich den Befehl nicht überprüfe, sprich einfach aufrufe funktioniert alles

Code: Alles auswählen

NextDatabaseRow(#db)
Repeat 
  string = ""
  For i = 0 To DatabaseColumns(#db) - 1
    string + Chr(10) + GetDatabaseString(#db,i)
  Next
  AddGadgetItem(fenster(winname)\datahandler,-1,string)
Until NextDatabaseRow(#db) = 0
Mach ich irgendwas falsch oder sollte man den Thread lieber in Bugs verschieben?

MfG Daniel
kluger Mann + kluge Frau = Romanze | dummer Mann + dumme Frau = Schwangerschaft
kluger Mann + dumme Frau = Affäre | dummer Mann + kluge Frau = Shopping <)
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von Kiffi »

ich würde hier generell eine kopfgesteuerte Schleife verwenden:

Code: Alles auswählen

While NextDatabaseRow(...
...
Wend
Ansonsten kann ich ohne lauffähigen Code wenig dazu sagen.

Bau doch mal ein kleines Beispiel zusammen. Du kannst ja eine ":memory:" - Datenbank verwenden.

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
zigapeda
Beiträge: 1753
Registriert: 06.03.2005 17:22
Wohnort: Kaufbeuren
Kontaktdaten:

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von zigapeda »

Ich hab mal meine Procedure exportiert...

Code: Alles auswählen

#db = 0

UseSQLiteDatabase()

Procedure gettabledata(winname.s)
  Protected tablename.s = winname ; Mid(winname,14)
  Protected string.s = ""
  ;ClearGadgetItems(fenster(winname)\datahandler)
  ;SetGadgetText(fenster(winname)\datacontenthandler,Str(fenster(winname)\datacontent))
  If DatabaseQuery(#db,"select * from " + tablename + " limit 30 offset 0");" + Str(fenster(winname)\datacontent))
    If NextDatabaseRow(#db)
      Repeat 
        string = ""
        For i = 0 To DatabaseColumns(#db) - 1
          string + Chr(10) + GetDatabaseString(#db,i)
        Next
        Debug string ;AddGadgetItem(fenster(winname)\datahandler,-1,string)
      Until NextDatabaseRow(#db) = 0
    Else 
      Debug "kein inhalt"
      ;fenster(winname)\datacontent - 30
      ;gettabledata(winname)
    EndIf
  Else
    MessageRequester("Database Error",DatabaseError())
  EndIf
EndProcedure

If OpenDatabase(#db,"C:\test.db","","")
  gettabledata("columntypetest")
EndIf

End
das funktioniert aber super...

Wenn du vor meinem Bösen Sourcecode From Hell nicht zurückschreckst kannst du dir den auch gerne mal den ganzen anguggen...
Also wie gesagt, eine Datenbank mit Tabellen, aber die Tabellen sind Leer...
wenn ich ein SQL Fenster öffne und selber "select * from table limit 30 offset 0" eingebe läuft es, die vordefinierte version
um die tabelleninhalte abzufragen geht nicht

[Edit]Wer keine datenbank zur hand hat, meinen code (unten) ausführen, neue datenbank erstellen, sql fenster öffnen und foldendes eintippen:

Code: Alles auswählen

create table testtable (a, b, c)
Dann datenbank schließen, wieder öffnen und es sollte eine tabelle drin sein[/Edit]

Code: Alles auswählen

EnableExplicit

Enumeration
  #db
  #win_main
  #men_main
  #men_file_newdb
  #men_file_opendb
  #men_file_closedb
  #men_file_newsql
  #men_file_opensql
  #men_file_savesql
  #men_file_savesqlas
  #men_file_quit
  #men_window_vertical
  #mdi_main
  #tree
  
EndEnumeration

Structure fenster
  id.i
  type.i
  panelhandler.i
  StructureUnion
    structurehandler.i
    editorhandler.i
  EndStructureUnion
  datahandler.i
  datacolumns.b
  datacontent.i
  datacontenthandler.i
  datanext.i
  dataprevious.i
  startbuttonhandler.i
EndStructure

Global NewMap fenster.fenster()
Global sqlwindowcounter.l

Define event.i
Define temp.s
Define quit.b
Define i.l
Define string.s
Define winname.s

UseSQLiteDatabase()

;OpenDatabase(#db,"c:\artikel.sqlite","","")

OpenWindow(#win_main,0,0,600,400,"PB SQLite Viewer",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
TreeGadget(#tree,0,0,200,400,#PB_Tree_AlwaysShowSelection)
CreateMenu(#men_main,WindowID(#win_main))
MenuTitle("File")
MenuItem(#men_file_newdb,"New Database")
MenuItem(#men_file_opendb,"Open Database")
MenuItem(#men_file_closedb,"Close Database")
MenuBar()
MenuItem(#men_file_newsql,"New SQL")
MenuItem(#men_file_opensql,"Open SQL")
MenuItem(#men_file_savesql,"Save SQL")
MenuItem(#men_file_savesqlas,"Save SQL as...")
MenuBar()
MenuItem(#men_file_quit,"Quit")
MenuTitle("Window")
MenuItem(#men_window_vertical,"Tile vertical")
MDIGadget(#mdi_main,200,0,450,400,1,2)
; AddGadgetItem(#mdi_main,#win_child,"Tableviewer")
; ListIconGadget(#structure,0,0,210,200,"Columnname",150)
; AddGadgetColumn(#structure,1,"Columntype",50)

Procedure getdatabasestructure()
  ClearGadgetItems(#tree)
  Define counter.l = 0
  AddGadgetItem(#tree,counter,"Indexes",0,0)
  counter + 1
  DatabaseQuery(#db,"select name from sqlite_master where type = 'index' order by name")
  While NextDatabaseRow(#db)
    AddGadgetItem(#tree,counter,GetDatabaseString(#db,0),0,1)
    SetGadgetItemData(#tree,counter,1)
    counter + 1
  Wend
  
  AddGadgetItem(#tree,counter,"Tables",0,0)
  counter + 1
  DatabaseQuery(#db,"select name from sqlite_master where type = 'table' order by name")
  While NextDatabaseRow(#db)
    AddGadgetItem(#tree,counter,GetDatabaseString(#db,0),0,1)
    SetGadgetItemData(#tree,counter,2)
    counter + 1
  Wend
  
  AddGadgetItem(#tree,counter,"Triggers",0,0)
  counter + 1
  DatabaseQuery(#db,"select name from sqlite_master where type = 'trigger' order by name")
  While NextDatabaseRow(#db)
    AddGadgetItem(#tree,counter,GetDatabaseString(#db,0),0,1)
    SetGadgetItemData(#tree,counter,3)
    counter + 1
  Wend
  
  AddGadgetItem(#tree,counter,"Views",0,0)
  counter + 1
  DatabaseQuery(#db,"select name from sqlite_master where type = 'view' order by name")
  While NextDatabaseRow(#db)
    AddGadgetItem(#tree,counter,GetDatabaseString(#db,0),0,1)
    SetGadgetItemData(#tree,counter,4)
   counter + 1
  Wend
  
;   AddGadgetItem(#tree,counter,"Virtual Tables",0,0)
;   counter + 1
;   DatabaseQuery(#db,"select name from sqlite_master where type = 'virtual table' order by name")
;   While NextDatabaseRow(#db)
;     AddGadgetItem(#tree,counter,GetDatabaseString(#db,0),0,1)
;     SetGadgetItemData(#tree,counter,5)
;     counter + 1
;   Wend
  
EndProcedure

Procedure getindexstructure(indexname.s)
  Protected winname.s = "Indexviewer: " + indexname
  If fenster(winname)\id
  
  Else
    fenster(winname)\id = AddGadgetItem(#mdi_main,#PB_Any,winname)
    fenster(winname)\type = 3 ;    ----Indexstructurewindow
  EndIf
  DatabaseQuery(#db,"select sql from sqlite_master where name = '" + indexname + "'")
  If NextDatabaseRow(#db)
    ;Debug GetDatabaseString(#db,0)
    
  EndIf
EndProcedure

Procedure gettabledata(winname.s)
  Protected tablename.s = Mid(winname,14)
  Protected string.s = ""
  Protected i.l
  ClearGadgetItems(fenster(winname)\datahandler)
  SetGadgetText(fenster(winname)\datacontenthandler,Str(fenster(winname)\datacontent))
  If DatabaseQuery(#db,"select * from " + tablename + " limit 30 offset " + Str(fenster(winname)\datacontent))
    If NextDatabaseRow(#db)
      Repeat 
        string = ""
        For i = 0 To DatabaseColumns(#db) - 1
          string + Chr(10) + GetDatabaseString(#db,i)
        Next
        AddGadgetItem(fenster(winname)\datahandler,-1,string)
      Until NextDatabaseRow(#db) = 0
    Else 
      fenster(winname)\datacontent - 30
      gettabledata(winname)
    EndIf
  Else
    MessageRequester("Database Error",DatabaseError())
  EndIf
EndProcedure

Procedure gettablestructure(tablename.s)
  Protected winname.s = "Tableviewer: " + tablename
  Protected string.s = ""
  Protected i.l
  If fenster(winname)\id
    ClearGadgetItems(fenster(winname)\structurehandler)
    SetGadgetState(#mdi_main,fenster(winname)\id)
  Else
    fenster(winname)\id = AddGadgetItem(#mdi_main,#PB_Any,winname)
    fenster(winname)\type = 1 ;   ----Tablestructurewindow
    fenster(winname)\panelhandler = PanelGadget(#PB_Any,0,0,WindowWidth(fenster(winname)\id),WindowHeight(fenster(winname)\id))
    AddGadgetItem(fenster(winname)\panelhandler,-1,"Structure")
      fenster(winname)\structurehandler = ListIconGadget(#PB_Any,0,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight),"Columnname",150)
    AddGadgetItem(fenster(winname)\panelhandler,-1,"Data")
      fenster(winname)\datahandler = ListIconGadget(#PB_Any,0,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20,"",20)
      fenster(winname)\dataprevious = ButtonGadget(#PB_Any,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20,50,20,"<")
      fenster(winname)\datacontenthandler = TextGadget(#PB_Any,50,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20,100,20,Str(fenster(winname)\datacontent),#PB_Text_Center)
      fenster(winname)\datanext = ButtonGadget(#PB_Any,150,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20,50,20,">")
    AddGadgetColumn(fenster(winname)\structurehandler,1,"Columntype",80)
  EndIf
  DatabaseQuery(#db,"select * from " + tablename + " limit 1")
  For i = 0 To DatabaseColumns(#db) - 1
    string = DatabaseColumnName(#db,i)
    AddGadgetColumn(fenster(winname)\datahandler,i+1,string,150)
    Select DatabaseColumnType(#db,i)
      Case #PB_Database_String
        string + Chr(10) + "STRING"
      Case #PB_Database_Double
        string + Chr(10) + "DOUBLE"
      Case #PB_Database_Quad
        string + Chr(10) + "QUAD"
      Case #PB_Database_Blob
        string + Chr(10) + "BLOB"
      Case 0
        string + Chr(10) + "NONE"
    EndSelect
    AddGadgetItem(fenster(winname)\structurehandler,-1,string)
  Next
  gettabledata(winname)
EndProcedure

Procedure newsqlwindow()
  sqlwindowcounter + 1
  Protected winname.s = "SQL " + Str(sqlwindowcounter)
  fenster(winname)\id = AddGadgetItem(#mdi_main,#PB_Any,winname)
  fenster(winname)\type = 2 ;   -----SQL Window
  fenster(winname)\panelhandler = PanelGadget(#PB_Any,0,0,WindowWidth(fenster(winname)\id),WindowHeight(fenster(winname)\id))
  AddGadgetItem(fenster(winname)\panelhandler,1,"Editor")
    fenster(winname)\editorhandler = EditorGadget(#PB_Any,0,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20)
    fenster(winname)\startbuttonhandler = ButtonGadget(#PB_Any,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight)-20,50,20,"Start")
  AddGadgetItem(fenster(winname)\panelhandler,2,"Data")
    fenster(winname)\datahandler = ListIconGadget(#PB_Any,0,0,GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(winname)\panelhandler,#PB_Panel_ItemHeight),"",20)
EndProcedure

Procedure closedatabasecomplete()
  If IsDatabase(#db)
    CloseDatabase(#db)
  EndIf
  ForEach fenster()
    If fenster()\type = 1
      CloseWindow(fenster()\id)
      DeleteMapElement(fenster())
    EndIf
  Next
EndProcedure

Repeat
  temp = ""
  event = 0
  Select WaitWindowEvent()
    Case #PB_Event_Menu
      Select EventMenu()
        Case #men_file_newdb
          temp = SaveFileRequester("Create Database","","All Files (*.*)|*.*|Database Files (*.db)|*.db|SQLite Files (*.sqlite)|*.sqlite",1)
          If temp
            closedatabasecomplete()
            CreateFile(#db,temp)
            CloseFile(#db)
            OpenDatabase(#db,temp,"","")
            getdatabasestructure()
          EndIf
        Case #men_file_opendb
          temp = OpenFileRequester("Open Database","","All Files (*.*)|*.*|Database Files (*.db)|*.db|SQLite Files (*.sqlite)|*.sqlite",1)
          If temp
            closedatabasecomplete()
            OpenDatabase(#db,temp,"","")
            getdatabasestructure()
          EndIf
        Case #men_file_closedb
          closedatabasecomplete()
          ClearGadgetItems(#tree)
        Case #men_file_newsql
          newsqlwindow()
        Case #men_file_quit
          quit = 1
        Case #men_window_vertical
      EndSelect
    Case #PB_Event_Gadget
      event = EventWindow()
      If event = #win_main
        If EventGadget() = #tree And EventType() = #PB_EventType_LeftDoubleClick
          Select GetGadgetItemData(#tree,GetGadgetState(#tree))
            Case 1
              ;Debug "index"
              getindexstructure(GetGadgetText(#tree))
            Case 2
              ;Debug "table"
              gettablestructure(GetGadgetText(#tree))
            Case 3
              ;Debug "trigger"
            Case 4
              ;Debug "view"
              
          EndSelect
        EndIf 
      Else
        Select EventGadget()
          Case fenster(GetWindowTitle(event))\datanext
            fenster(GetWindowTitle(event))\datacontent + 30
            gettabledata(GetWindowTitle(event))
          Case fenster(GetWindowTitle(event))\dataprevious
            If fenster(GetWindowTitle(event))\datacontent > 30
              fenster(GetWindowTitle(event))\datacontent - 30
            Else 
              fenster(GetWindowTitle(event))\datacontent = 0
            EndIf
            gettabledata(GetWindowTitle(event))
          Case fenster(GetWindowTitle(event))\startbuttonhandler
            If DatabaseQuery(#db,GetGadgetText(fenster(GetWindowTitle(event))\editorhandler)) = 0
              MessageRequester("Database Error",DatabaseError())
            Else
              ClearGadgetItems(fenster(GetWindowTitle(event))\datahandler)
              If fenster(GetWindowTitle(event))\datacolumns
                For i = fenster(GetWindowTitle(event))\datacolumns To 1 Step -1
                  RemoveGadgetColumn(fenster(GetWindowTitle(event))\datahandler,i)
                Next
              EndIf
              NextDatabaseRow(#db)
              string = ""
              fenster(GetWindowTitle(event))\datacolumns = DatabaseColumns(#db)
              For i = 0 To DatabaseColumns(#db) - 1
                string + Chr(10) + GetDatabaseString(#db,i)
                AddGadgetColumn(fenster(GetWindowTitle(event))\datahandler,i+1,DatabaseColumnName(#db,i),150)
              Next
              AddGadgetItem(fenster(GetWindowTitle(event))\datahandler,-1,string)
              While NextDatabaseRow(#db)
                string = ""
                For i = 0 To DatabaseColumns(#db) - 1
                  string + Chr(10) + GetDatabaseString(#db,i)
                Next
                AddGadgetItem(fenster(GetWindowTitle(event))\datahandler,-1,string)
              Wend
            EndIf
        EndSelect
      EndIf
    Case #PB_Event_SizeWindow
      event = EventWindow()
      If event = #win_main
        ResizeGadget(#tree,0,0,150,WindowHeight(#win_main)-20)
        ResizeGadget(#mdi_main,150,0,WindowWidth(#win_main)-150,WindowHeight(#win_main)-20)
      Else
        Select fenster(GetWindowTitle(event))\type
          Case 1
            ResizeGadget(fenster(GetWindowTitle(event))\panelhandler,0,0,WindowWidth(event),WindowHeight(event))
            ResizeGadget(fenster(GetWindowTitle(event))\structurehandler,0,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight))
            ResizeGadget(fenster(GetWindowTitle(event))\datahandler,0,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20)
            ResizeGadget(fenster(GetWindowTitle(event))\dataprevious,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20,50,20)
            ResizeGadget(fenster(GetWindowTitle(event))\datacontenthandler,50,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20,100,20)
            ResizeGadget(fenster(GetWindowTitle(event))\datanext,150,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20,50,20)
          Case 2
            ResizeGadget(fenster(GetWindowTitle(event))\panelhandler,0,0,WindowWidth(event),WindowHeight(event))
            ResizeGadget(fenster(GetWindowTitle(event))\editorhandler,0,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20)
            ResizeGadget(fenster(GetWindowTitle(event))\startbuttonhandler,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight)-20,50,20)
            ResizeGadget(fenster(GetWindowTitle(event))\datahandler,0,0,GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemWidth),GetGadgetAttribute(fenster(GetWindowTitle(event))\panelhandler,#PB_Panel_ItemHeight))
        EndSelect
      EndIf
    Case #PB_Event_CloseWindow
      event = EventWindow()
      If event = #win_main
        quit = 1
      Else
        winname = GetWindowTitle(event)
        CloseWindow(fenster(winname)\id)
        DeleteMapElement(fenster(),winname)
      EndIf
  EndSelect
Until quit
kluger Mann + kluge Frau = Romanze | dummer Mann + dumme Frau = Schwangerschaft
kluger Mann + dumme Frau = Affäre | dummer Mann + kluge Frau = Shopping <)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von Kaeru Gaman »

"Procedure" dachte ich mir schon fast, wenn der Stack betroffen ist...

so und deine Proc alleine funzt super...?

dann musst du wo ganz ganz anders den Stack ruinieren, es kommt nur hier zum tragen.
ähnlich wie das bei einem IMA passieren kann, würde ich mal schätzen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
zigapeda
Beiträge: 1753
Registriert: 06.03.2005 17:22
Wohnort: Kaufbeuren
Kontaktdaten:

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von zigapeda »

Hmm, danke @ Kaeru, weiß nicht warum aber du hast mich auf den Fehler gebracht...

Ich weiß zwar eigentlich was ein Stack Overflow ist und auch wie man ihn Produziert aber ich hab keine ahnung wie ich das übersehen / nicht von selber drauf kommen konnte :freak:

[Edit]Wenn es jemanden interessiert, ich hab einen counter (fenster(winname)\datacontent) in dem ich den aktuellen datensatz speicher, wenn der query keinen datensatz zurück gibt (sprich einmal zuviel auf "nächsten 30 datensätze anzeigen" geklickt wurde) zieht er 30 ab und ruft die prozedur erneut auf. Das hat er 36914 mal gemacht und dann hat er sich gekillt.
@Kiffi Deswegen auch erst das NextDatabaseRow() mit einem If um eben erklärtes zu überprüfen und dann eine schleife mit abbruchbedingung damit der erste Record nicht verloren geht[/Edit]
Zuletzt geändert von zigapeda am 11.12.2009 14:43, insgesamt 1-mal geändert.
kluger Mann + kluge Frau = Romanze | dummer Mann + dumme Frau = Schwangerschaft
kluger Mann + dumme Frau = Affäre | dummer Mann + kluge Frau = Shopping <)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von Kaeru Gaman »

und was wars? hast du in nem Select/Case Mist gebaut?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: NextDatabaseRow() --> Stack Overflow

Beitrag von Kiffi »

zigapeda hat geschrieben:Ich weiß zwar eigentlich was ein Stack Overflow ist und auch wie man ihn Produziert
geht ganz easy:
Procedure Test1()
Test1()
EndProcedure

Test1()
Auf dem Stack wird die Adresse der Procedure abgelegt, aus der in eine andere Procedure gesprungen wird, um beim
ProcedureReturn bzw. beim EndProcedure zum Aufrufer zurückzukehren. Dieser Stack hat nur ein gewisse Größe.

Da Du zu oft gesprungen bist, ist der Stack dann irgendwann übergelaufen.

Grüße ... Kiffi
a²+b²=mc²
Antworten