Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Deine Meinung? |
Sehr gut |
|
100% |
[ 1 ] |
Gut |
|
0% |
[ 0 ] |
Vielleicht nützlich |
|
0% |
[ 0 ] |
Gibts schon besser |
|
0% |
[ 0 ] |
nicht nützlich |
|
0% |
[ 0 ] |
sonstiges (posten) |
|
0% |
[ 0 ] |
|
Stimmen insgesamt : 1 |
|
Autor |
Nachricht |
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 03:06 Titel: Listen in FreeBasic |
|
|
Hi FB-Community,
Mein erstes Projekt ist nicht in FB geschrieben, diesmal ist es aber anders.
Ich habe mich mit St_W über Dock-Widgets unterhalten, dann sind wir irgendwie auf Listen gekommen.
Da hab ich heute Abend mal was dazu geschrieben und zwar in FreeBASIC.
Es ist ein Type für eine doppelt verkette Liste mit vielen Funktionen.
Ich habe mir QList zum Vorbild genommen und fast alle Funktionen nachgebaut.
QList ist eine Template Klasse, das heist wenn man eine Integer Liste braucht schreibt man das so:
Jetzt gibt es ja in FB (leider) keine Templates.
Daher habe ich improvisiert.
Ich habe aber nicht den Type für jeden Datentyp neu geschrieben oder irgendwas mit Zeiger-Casting gemacht, aber ein Beispiel dürfte mehr sagen:
Code: | dim as List l
l.add("Hallo")
dim as List l2
l2.add(45) |
Das wird über einen "Template-Type" gemacht (eigene Wortschöpfung).
Ein Type der nur für jeden Datentyp einen Konstruktor, einen Casting Operator und eine Variable hat. (Bei interesse einfach listType.h öffnen)
Die Liste ist dann eine Liste dieses "Template-Types" und wenn man eine Liste eines UDTs braucht kann man die Funktionalität mit unter 10 Zeilen Code nachrüsten. (ebenfalls listType.h)
Steckbrief
Technik: doppelt verkettete Liste
Besonderheit: in ca. 20s für eigene UDTs anwendbar, gemischte Listen, z.B. [3,"Hallo",5.34,"Welt"]
Features: Schutz vor Überlauf und Schutz vor Zugriff auf einen zu großen oder zu kleinen Index
Member:
- add oder append: Hängt eine Variable an
- prepend: Fügt eine Variable an den Anfang der Liste ein
- remove: Entfernt ein Element
- removeAll: Entfernt alle Elemente die gleich sind wie der erste Parameter
- insert: Fügt an einer bestimmten Stelle eine Variable ein
- move: Verschiebt eine Variable
- get: gibt eine Variable über den Index zurück
- first und last: Geben den ersten bzw. letzten Eintrag zurück
- removeFirst und removeLast: Entfernen den ersten bzw. letzten Eintrag
- isEmpty: Gibt zurück ob die Liste leer ist
- count: kann die Länge der Liste zurückgeben oder wie oft ein bestimmter Wert in der Liste auftaucht
- indexOf: Sucht den ersten Index dessen Element gleich dem ersten Parameter ist
- lastIndexOf: Gleich wie indexOf, nur rückwärts
- startsWith und endsWith: Überprüfen ob das erste oder letzte Element gleich dem ersten Parameter sind
- replace: Ersetzen einen Eintrag mit einer anderen Variable
- swapItems: Vertauscht zwei Einträge
- ausserdem noch: 5 oder 6 andere Funktionen und der = und der += Operator sind überladen für den Type
Code: | #include "list.bi"
dim as List l
l += "Hallo"
l += "Welt"
l.add("Hallo")
l.add("Welt")
l.add("Hallo")
l.add("Welt")
print "Zahl der Elemente:"; l.count()
print
print l.get(3)
sleep
|
Download: http://users.freebasic-portal.de/stueber/Liste/Liste.zip
Wie immer würde ich mich über Rückmeldung freuen. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 13:26 Titel: |
|
|
Hab die Liste jetzt nochmal erweitert.
Jetzt hat die Liste alle Funktionen von QList aus C++ ausser den STL Funktionen.
Neu ist:
- erase: Löscht alle Elemente von s bis e
- value: Gleich wie get aber hat noch einen Parameter der zurückgegeben wird wenn der Index zu groß oder zu klein ist
- contains: überprüft ob eine Variable in der Liste vorkommt
- mid: gibt eine Teilliste von s mit der länge l zurück
- take: Gibt einen Eintrag zurück und löscht ihn danach
- removeOne: entfernt das erste auftreten eines Wertes
- operatoren: plus, minus, geteilt, ungleich, gleich und plus-gleich sind jetzt überladen um mit der Liste zu arbeiten.
Ein Beispiel zur Verwendung:
Code: | #include "list.bi"
dim l as list
l = l + "Hallo" + "Welt," + "FreeBASIC" + "Liste"
print l.count() 'Gibt 6 aus
print l.count("Welt") 'Gibt 1 aus
print l.swapItems(2,3) '["Hallo","FreeBASIC","Welt","Liste"]
print l.move(1,4) '["FreeBASIC","Welt","Liste","Hallo"]
print l.indexOf("FreeBASIC") 'Gibt 2 aus
if endsWith("Hallo") then
print get(4) 'Wird ausgegeben
end if
print l / "Welt" 'Gibt 1 aus
l = l - "Liste" '["FreeBASIC","Welt","Hallo"]
print l.count() 'Gibt 3 aus
print l.value(5,"Fehler!") 'Gibt "Fehler!" aus
'prepand("Liste") ist das gleiche wie l = "Liste" + l
l.prepend("Liste") '["Liste","FreeBASIC","Welt","Hallo"]
l.clear() 'Liste ist jetzt leer
if l.isEmpty() then
print get(-23) 'Führt zu keinem Speicherfehler sonder gibt nur 0 aus (Bei einem falschen Index wird immer 0 ausgegeben)
print.value(-23,"Standard") 'Gibt "Standard" aus, da -23 nicht existiert
end if
|
Link: http://users.freebasic-portal.de/stueber/Liste/Liste.zip
Wie oben schon gesagt: Auf Rückmeldung freu ich mich. |
|
Nach oben |
|
|
OneCypher
Anmeldungsdatum: 23.09.2007 Beiträge: 802
|
Verfasst am: 07.01.2010, 14:59 Titel: |
|
|
Das sieht schwer nach einem "objekt" aus das Microsoft "Collection" nennt und welches ich in ähnlicher weise für FB umgesetzt hatte: http://www.freebasic-portal.de/porticula/collection-bi-970.html
Es ist eine Liste mit Pointern .. die pointer können auf x-beliebige Datentypen zeigen..
Ich hatte aber auch eine ForEach( ) in( ) implementierung hinzugefügt welches den umgang mit listen vereinfachen soll...
Leider weiss ich nicht wie aktuell die oben erwähnte version meiner collection-umsetzung ist. Muss ich wahrscheinlich mal aktualisieren...
Guck dich einfach mal im quältext um, vielleicht findest du ja noch was inspirierendes ... |
|
Nach oben |
|
|
OneCypher
Anmeldungsdatum: 23.09.2007 Beiträge: 802
|
Verfasst am: 07.01.2010, 15:02 Titel: |
|
|
PS: Wie hast du denn die List.zip gehostet ? wer verbirgt sich hinter users.freebasic-portal.de ? |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 15:18 Titel: |
|
|
Hinter users.freebasic-portal.de verbirgt sich ein FTP Zugang den Sebastian mir für die IDE gegeben hat, den ich aber auch für so Kleinigkeiten nehmen kann.
Und hab in deiner Umsetzung tatsächlich was gefunden:
Die Liste hat zwar weniger Funktionen, aber dafür gibt es einen Datentyp für Listenelemente.
Ich könnte noch sowas machen:
Code: | dim las list l
l = l + "Hallo" + "Welt"
l.get(1).next()->value() 'Überladen für den Listen Element Datentyp, also das gleiche wie l.get(2)
|
So könnte man sich auch manuell an der Liste entlang hangeln, was manchmal sicher nützlich sein kann, oder aus einem Element sofort auslesen was das nächste oder vorherige Element ist bzw. was für einen Wert es hat. |
|
Nach oben |
|
|
OneCypher
Anmeldungsdatum: 23.09.2007 Beiträge: 802
|
Verfasst am: 07.01.2010, 16:46 Titel: |
|
|
Boa.. so nen FTP-Zugang möcht ich auch haben ... mein Projekt "GuiPtr" würd ich so gerne mal im freebasic-portal updaten.. aber da sind so viele dateien zu löschen und zum hochladen das es für mich einfach zu unbequem ist die übliche portal-oberfläche zu benutzen ...
Also ein "entlang hangeln" in einer liste wäre über eine scheife schon schöner..
Man kann übrigens auch For-Next für einen Datentyp überladen. "For" ist auch ein überladbarer Operator ... Vielleicht ließe sich da was machen... Muss mal schauen wo ich beispiele dazu gesehen hatte...
Mit "einen Datentyp für Listenelemente" meinst du diesen "ItemContainer" in meinem quelltext ? |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 17:03 Titel: |
|
|
Zitat: | Mit "einen Datentyp für Listenelemente" meinst du diesen "ItemContainer" in meinem quelltext ? |
Kann sein, hab das nur überflogen.
Eine Forschleife braucht man im Prinzip nicht, die Funktion value kapselt das schon.
Hat schon jemand versucht eine Liste eines eigenen Datentyps anzulegen?
Würde mich interessieren, ob es funktioniert hat wie beschrieben. |
|
Nach oben |
|
|
The_Muh aka Mark Aroni
Anmeldungsdatum: 11.09.2006 Beiträge: 718
|
Verfasst am: 07.01.2010, 17:04 Titel: |
|
|
Erinnert mich schwer an die von mir oft genutzte LinkedList.bi von TPM... auch wenn du wesentlich mehr eingebaut hast. An TPMs liste gefällt mir allerdings, das jedes element der Liste, wieder eine Liste ist, damit sind Baumstrukturen extrem einfach zu realisieren. Das dürfte zwar mit deiner Liste auch gehen, aber nur durch zusätzliche arbeit im haupt-code.
Ich werd mir die liste bei gelegenheit mal angucken, aber irgentwie vermisse ich eine einfach gehaltene liste, die verschiedene datentypen erlaubt (wie nannte sich das in python? Tuple?). Und da bräuchte ich die von dir gelisteten features eher weniger... _________________ // nicht mehr aktiv // |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 17:14 Titel: |
|
|
Code: | aber irgentwie vermisse ich eine einfach gehaltene liste, die verschiedene datentypen erlaubt |
Meinst du eine Liste die mehrere verschiedene Datentypen gleichzeitig beinhalten kann (wenn ja, das geht bei der) oder eine Liste die ohne sie neu schreiben zu müssen mit unterschiedlichen Datentypen funktioniert (sowas heist in C++ Template), wenn ja, das ist auch relativ gut gelöst. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 22:32 Titel: |
|
|
Ich hab einen zweiten Type auf Basis von List geschrieben, in dem ich die wichtigsten Funktionen von QMap nachgebaut habe.
In einer QMap kann man Werte mit anderen Werten verknüpfen.
Mit meinem Type kann man jeden beliebigen Wert bzw. jede Variable mit jedem beliebigen anderen Wert bzw. jeder Variable verknüfen.
Intern werden Key-Value Paare gespeichert. Jeder Wert hat einen Schlüssel über den man an die Value bekommt.
Beispiel:
Code: | dim m as Map
m.add(2,"Hallo")
m.add(34,"Type")
m.add(-323,"List")
m.add(0,"Map")
m.add(111,"FreeBASIC")
m.add(3943,"Welt")
print m.value(-323) 'Gibt "List" aus
print m.value(111) 'Gibt "FreeBASIC aus"
print m.value(2) 'Gibt "Hallo" aus |
Der erste Wert ist immer der Key und der zweite die Value.
Key und Value können unterschiedliche Datentypen sein und jeweils jeden beliebigen Datentyp haben.
Hier im Beispiel werden Integer mit Strings verknüpft.
Man könnte aber auch HWNDs mit UDT-Zeigern verknüpfen oder Strings mit anderen Strings.
Der Type hat nicht ganz so viele Hilfsfunktionen wie List aber trotzdem relativ viele. (16 gesammt)
Wenn interesse daran besteht, lade ich den Quelltext dafür auch noch gerne hoch. |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4597 Wohnort: ~/
|
Verfasst am: 07.01.2010, 23:28 Titel: |
|
|
So ein Mist. Jetzt muss ich mein aktuelles Programm wieder komplett umbauen. *grummel*
Hört sich hochinteressant an. Ich hoffe, dass ich bald mal dazu komme, es einzusetzen; Ideen habe ich schon zwei. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 07.01.2010, 23:53 Titel: |
|
|
Ich kann dir auch sagen, es ist komplett plattformübergreifend.
Du wirst mit Linux nicht ausgeschlossen.
Hier der Link: http://users.freebasic-portal.de/stueber/Liste/Map.zip
Quelltext und ein Beispiel liegt bei.
Da die zwei Klassen offensichtlich gut angekommen sind arbeite ich schon an den nächsten beiden. (eine ist schon fertig aber nicht so wichtig in FreeBASIC)
Rückmeldung, Fragen, Kritik, Lob einfach posten. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 08.01.2010, 17:46 Titel: For each |
|
|
OneCypher hat sich eine For-Each Schleife gewünscht.
Hier ein Beispiel Quelltext:
Code: | #include "list.bi"
#define each(a) fb_i as integer = 1 to a.count()
dim as List l
l = l + "Hallo" + "Welt" + "For" + "Liste" + "FreeBASIC"
for each(l)
print l.get(fb_i)
next
sleep |
|
|
Nach oben |
|
|
OneCypher
Anmeldungsdatum: 23.09.2007 Beiträge: 802
|
Verfasst am: 08.01.2010, 18:39 Titel: |
|
|
@Stueber: Da fehlt aber noch einiges
Denn laut syntax bezeichnest du mit Each das Element welcher als zeiger auf das aktuelle element dient und mit "in" bezeichnet man die gruppe/collection/list welche durchlaufen werden soll...
so einfach ist das nicht ..
In meiner Collection.bi sieht die ForEach( ) in( ) definition so aus:
Code: |
#define ForEach(Collection_Item) scope:dim CollectionItems123456 as item = item(Collection_Item,
#define in(ObjectCollection) ObjectCollection):Do until CollectionItems123456
#define NextOne loop: end scope
|
Ohne den rest der Collection.bi wirken diese definitionen erstmal zusammenhangslos, dennoch kann man damit z.B. sowas realisieren:
Code: |
Dim MyCollection as Collection
Dim MyInteger as integer ptr
'Erstmal füllen:
for i as integer = 1 to 100
MyCollection.Add( new integer )
next
'Und jetzt wirds lustig, denn jetzt kann man was mit der collection anfangen:
'Hier füllen wir die Werte der Integer-Elemente in MyCollection
ForEach(MyInteger) in(MyCollection)
*MyInteger = int(rnd * 1000)
NextOne
'Und nun ausgeben:
ForEach(MyInteger) in(MyCollection)
print *MyInteger
NextOne
'Alternativ geht auch:
for i as integer = 1 to MyCollection.count
MyInteger = MyCollection.item(i)
print *MyInteger
Next
|
Ob die umsetzung in meinem macro bzw define gut gelöst ist, ist ne andere sache..
Aber mit einer vollständigen For-Each( )-In( ) implementation kann man viel und schnell was anfangen.. ich finde es extrem komfortabel.. |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4597 Wohnort: ~/
|
Verfasst am: 08.01.2010, 19:25 Titel: |
|
|
Wenn ich das hier gepostete Beispiel zu den Listen (Beitrag vom 07.01.2010, 12:26) kompilieren möchte, bekomme ich ein paar Fehlermeldungen. Sind aber leicht auszumerzen.
Was ich von Ruby her erwarten würde, wäre eine Verknüpfung zweier Listen:
Code: | dim as List l, k, m
k += 1
m += 2
l = m + k |
Ich weiß nicht, ob das im Sinne des Erfinders ist; ist auch streng genommen nicht eindeutig. Aber mal so als Anregung.
Schön fände ich auch eine vordefinierte Möglichkeit, zum Debugging die gesamte Liste anzuzeigen:
_________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 08.01.2010, 19:30 Titel: |
|
|
Mach ich beides, das anhängen einer Liste wollte ich sowie so schon machen.
Das Beispiel hatte ich im Editor hier geschrieben, also nicht getestet. |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4597 Wohnort: ~/
|
Verfasst am: 08.01.2010, 19:59 Titel: |
|
|
Ich sehe gerade, dass man sehr einfach ein "double free or corruption" erzeugen kann:
Code: | dim as List l, k
k += 5
l = k
l.clear()
k.clear() |
Das zweite clear löst bei mir einen Fehler aus. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 08.01.2010, 20:02 Titel: |
|
|
Da hatte ich wohl was übersehen.
Aber die meisten Funktionen haben einen Schutz gegen Fehler.
Im Type Map der auf List basiert ist der Fehler schon behoben aber die Behebung ist nicht zu List zurück geflossen.
Edit: Fehler behoben.
Öffne einfach die Datei list.bi und ersetze die Funktion clear() durch:
Code: | sub list.clear()
if c = 0 then exit sub
do
remove(2)
loop until c = 1
end sub |
|
|
Nach oben |
|
|
Stueber
Anmeldungsdatum: 07.07.2008 Beiträge: 202
|
Verfasst am: 08.01.2010, 21:16 Titel: |
|
|
So, der Fehler ist behoben.
Zusätzlich sind neue Funtionen dazu gekommen:
- append, add, prepend und insert sind jetzt auch mit anderen Listen verwendbar.
z.B.
Code: | dim as list l1,l2
l2 = l2 + 2 + 2 + 3 + 4
l1.append(l2) |
- Die Operatoren += und + sind überladen für das hinzufügen einer Liste zu einer anderen.
- Die Operatoren >, <, >= und <= sind zum vergleich der Listenlänge überladen.
- for each() Makro zum durchlaufen der Liste. Dieses spart einem das anlegen der Zählvariable, das initialisieren und das festlegen der Anzahl der Durchläufe.
- andere Fehler wurden behoben
Download Link: http://users.freebasic-portal.de/stueber/Liste/List.zip
Ich hoffe es hilft dem ein oder anderen weiter, und das es verwendbar ist. |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4597 Wohnort: ~/
|
Verfasst am: 08.01.2010, 22:14 Titel: |
|
|
Noch eine Kleinigkeit:
Code: | #include once "listType.bi" |
Ich brauche nämlich gerade List und Map gleichzeitig, und dann würde er wegen doppelter Einbindung meckern. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
|