Υπάρχει πιο προχωρημένο θέμα εδώ (στο παράδειγμα με την Class LList) όπου χρησιμοποιούμε δείκτες σε ομάδες, και η δομή κρατιέται από τους δείκτες μόνο (ενώ στο παράδειγμα εδώ τα αντικείμενα βρίσκονται σε πίνακα, και οι δείκτες δείχνουν στοιχεία πίνακα)
Το παράδειγμα είναι αρκετά προχωρημένο και είναι στα Αγγλικά. Η κλάση Mem() που είχε δοθεί σε προηγούμενες αναρτήσεις εμπλουτίστηκε με "λογική" για υποστήριξη συνδεδεμένων λιστών τύπου LIFO και FIFO. Μπορούμε να φτιάξουμε όσες λίστες θέλουμε! Η κλάση Mem() αν χρειάζεται περισσότερα στοιχεία επεκτείνεται μόνη της! Μας παρέχει μνήμη για να βάλουμε αντικείμενα σε ένα πίνακα.
Στη Μ2000 μπορούμε σε στοιχεία πίνακα να γράφουμε αντικείμενα. Αντί να χρησιμοποιήσουμε τη συνάρτηση Malloc() που δίνει το αντικείμενο για να κάνουμε λίστες χρησιμοποιούμε τις μεθόδους PushFirst και PushLast, οι οποίες προσθέτουν μια ιδιότητα την pnext.
Η Mem() δεν ασχολείται με το τι κλάση δίνουμε! Αν χρησιμοποιούμε τις μεθόδους αυτές, για οποιοδήποτε αντικείμενο, τότε θα φτιάχνεται κανονικά η λίστα που θέλουμε! Οι δείκτες αρχής-τέλους για την FIFO και αρχής για τη LIFO είναι μεταβλητές που παρέχουμε με αναφορά.
Επιπλέον υπάρχουν και μέθοδοι και συναρτήσεις υποστηρικτικές. Δεν θα αναφέρω κάτι παραπάνω!
Μπορεί κανείς να δει το κώδικα - αλλά μπορεί και να τον τρέξει!
Η Μ2000 έχει σωρό τιμών που χειρίζεται ως στοίβα FIFO και LIFO, ότι βάλουμε, αλλά εδώ μας ενδιαφέρει η χρήση μια κλάσης. Όλο το MEM() είναι ένα αντικείμενο και μπορεί να μπει σε ένα άλλο!
Διορθώθηκε ο παλιός κώδικας (έβαζε 100 στοιχεία κάθε φορά που ζητάγαμε 1, αλλαγή συνθήκης < σε >= στο .topfree>=.Items, στην Malloc)
Προστέθηκε η PopOne για να βγάζουμε στοιχεία. Επίσης σε αυτήν την έκδοση δεν γίνεται χρήση της .Porperty$() της Mem, αλλά έχει εισαχθεί μια ιδιότητα Item() (με ένα όρισμα) η οποία γυρνάει αντίγραφο του αντικειμένου και συνδυάζεται με .name$ (αυτό γίνεται στην 9). Για το διάβασμα η Item() διαβάζει το αντικείμενο και το συνδέει. Πρέπει όμως να υπάρχει ήδη αντικείμενο εκεί που το βάζουμε!
Το παράδειγμα είναι αρκετά προχωρημένο και είναι στα Αγγλικά. Η κλάση Mem() που είχε δοθεί σε προηγούμενες αναρτήσεις εμπλουτίστηκε με "λογική" για υποστήριξη συνδεδεμένων λιστών τύπου LIFO και FIFO. Μπορούμε να φτιάξουμε όσες λίστες θέλουμε! Η κλάση Mem() αν χρειάζεται περισσότερα στοιχεία επεκτείνεται μόνη της! Μας παρέχει μνήμη για να βάλουμε αντικείμενα σε ένα πίνακα.
Στη Μ2000 μπορούμε σε στοιχεία πίνακα να γράφουμε αντικείμενα. Αντί να χρησιμοποιήσουμε τη συνάρτηση Malloc() που δίνει το αντικείμενο για να κάνουμε λίστες χρησιμοποιούμε τις μεθόδους PushFirst και PushLast, οι οποίες προσθέτουν μια ιδιότητα την pnext.
Η Mem() δεν ασχολείται με το τι κλάση δίνουμε! Αν χρησιμοποιούμε τις μεθόδους αυτές, για οποιοδήποτε αντικείμενο, τότε θα φτιάχνεται κανονικά η λίστα που θέλουμε! Οι δείκτες αρχής-τέλους για την FIFO και αρχής για τη LIFO είναι μεταβλητές που παρέχουμε με αναφορά.
Επιπλέον υπάρχουν και μέθοδοι και συναρτήσεις υποστηρικτικές. Δεν θα αναφέρω κάτι παραπάνω!
Μπορεί κανείς να δει το κώδικα - αλλά μπορεί και να τον τρέξει!
Η Μ2000 έχει σωρό τιμών που χειρίζεται ως στοίβα FIFO και LIFO, ότι βάλουμε, αλλά εδώ μας ενδιαφέρει η χρήση μια κλάσης. Όλο το MEM() είναι ένα αντικείμενο και μπορεί να μπει σε ένα άλλο!
Διορθώθηκε ο παλιός κώδικας (έβαζε 100 στοιχεία κάθε φορά που ζητάγαμε 1, αλλαγή συνθήκης < σε >= στο .topfree>=.Items, στην Malloc)
Προστέθηκε η PopOne για να βγάζουμε στοιχεία. Επίσης σε αυτήν την έκδοση δεν γίνεται χρήση της .Porperty$() της Mem, αλλά έχει εισαχθεί μια ιδιότητα Item() (με ένα όρισμα) η οποία γυρνάει αντίγραφο του αντικειμένου και συνδυάζεται με .name$ (αυτό γίνεται στην 9). Για το διάβασμα η Item() διαβάζει το αντικείμενο και το συνδέει. Πρέπει όμως να υπάρχει ήδη αντικείμενο εκεί που το βάζουμε!
\\ Example of using Mem() to build \\ Language M2000 ver 9 \\ use of public and private in class/group definitions \\ Stacks, FIFO and LIFO \\ We provide a class AnyName wihout pnext \\ and inside Mem() we add This property \\ We use PushFirst and PushLast methods Form 80,40 Gosub MyClass Class AnyName { name$ Module AnyName { Read .name$ } } A=Mem(100) Print "A FIFO, First In First Out" A1=A.Null() A2=A.Null() Stack New { Data "First","Second","Third", "Forth","Fifth" While Not Empty { A.PushFirst &A1,&A2, AnyName(letter$) } ShowList(A1) } Print "A LIFO, Last In First Out" A3=A.Null() Stack New { Data "First","Second","Third", "Forth","Fifth" While Not Empty { A.PushLast &A3, AnyName(letter$) } ShowList(A3) } Print "Change one item ********************" bb=A.CopyObj(A3) Print bb.name$ bb.name$=bb.name$+"!" A.CopyBack A3, BB \\Print A.Property$(A3,"name$") Print A.Item(A3).name$ Print "Swap 1st with 3rd using external copies***" x=A3 : For i=1 to 2 : x=A.Pnext(x) : Next i Dim aa(2) aa(0)=A.CopyObj(A3) aa(1)=A.CopyObj(x) Swap aa(0),aa(1) 'fast using pointers \\ CopyBack preserve link pointer if found A.CopyBack A3, aa(0) A.CopyBack x, aa(1) Dim aa() ' erase Print "Show List - Swap 1 with 3rd **" ShowList(A3) \\ using object method A.SwapLinked A3, x Print "Show List - Right Order ***" ShowList(A3) Print "Show List - Delete Second from Last***" A.DeleteLinked A3 '' delete second ShowList(A3) Print "Show List - Delete Last ***" For A { \\ newA3 is a temporary variable newA3=.Pnext(A3) .MFree A3 A3=newA3 } ShowList(A3) OldA3=A3 OldA1=A1 Dim bbb(1) bbb(0)=A Print bbb(0).ItemsCount For bbb(0) { Print "A1" x=A1 While x<>.Null() { Print .Item(x).name$ x=.Pnext(x) } Print "A3" x=A3 While x<>.Null() { Print .Item(x).name$ x=.Pnext(x) } Print "Pop from A3" M=.PopOne(&A3) Print M.name$ Print .itemscount M=.PopOne(&A3) Print M.name$ Print .itemscount Print "A3" x=A3 While x<>.Null() { Print .Item(x).name$ x=.Pnext(x) } Print "Pop from A1" M=.PopOne(&A1) Print M.name$ Print .itemscount M=.PopOne(&A1) Print M.name$ Print .itemscount Print "A1" x=A1 While x<>.Null() { Print .Item(x).name$ x=.Pnext(x) } } \\ bbb(0) has a copy of A, so we have in A all 8 items, as was before copy A to bbb(0) Print "Original A1" ShowList(OldA1) Print A.Item(OldA1).name$ For This { M=A.Item(OldA1) M.name$="new name" A.Item(OldA1)=M } Print A.Item(OldA1).name$ Print "Original A1 with changed name in A1" ShowList(OldA1) Print "Original A3" ShowList(OldA3) End Sub ShowList(Root) local x=Root While x<>A.Null() { Print A.Item(x).name$ x=A.Pnext(x) } Print "Press any key" a$=key$ End Sub MyClass: Class Global Mem { Private: Dim d() noUsed=-1 topfree=0 Items, Count, AddMore=100 Group Null { Null } Function IsNull { =Valid(.d(Number).Null) } Public: Group Item { value (x) { Link parent d() to d() IF valid(d(x).Null) then Error "Null at"+Str$(x) IF Type$(d(x))<>"Group" then Error "Empty at"+Str$(x) =d(x) } Set (x) { Link parent d() to d() IF valid(d(x).Null) then Error "Null at"+Str$(x) IF Type$(d(x))<>"Group" then Error "Empty at"+Str$(x) b=d(x).pnext Read a Group a { pnext=b } d(x)=a } } Group ItemsCount { Value { link parent count to count =count } } Function Pnext { Read where if .isNull(where) Then "Error pointer is Null" =.d(where).pnext } Module PushLast { If not Match("SG") Then Error "Bad Parameters" Read &First Push 1 ' For malloc Shift 2 ' so we get Group first \\ we call Malloc module using parameters in stack Call .Malloc Read Last If First=.Null() Else { .d(Last).pnext<=First } First=Last } Module PushFirst { If not Match("SSG") Then Error "Bad Parameters" Read &Root, &Last Push 1 ' For malloc Shift 2 ' so we get Group first \\ we call Malloc module using parameters in stack Call .Malloc Read First If Root=.Null() Then { Root=First Last=First } Else { .d(Last).pnext<=First Last=First } } Function Null { =-1 } Module AddMore { Read K If K<=0 Then Exit Try ok { Dim .d(K+.items) } If ok Then .Items+=K } Module Mem { Read .Items If Match("G") Then Read N N=.Null \\ This is a Union If N is a Group Dim .d(.Items)=N } Function Malloc { If Not Match("G") Then Error "No Group Found" Call .Malloc =Number } Module Malloc { If .noUsed=-1 Then { If .topfree>=.Items Then { Try { .AddMore .AddMore ok2=true } If valid(ok2) Else Error "Memory Full" } Read .d(.topfree) Gosub CheckCommand(.topfree) Push .topfree .topfree++ .count++ } Else { temp=.d(.noUsed).Null Read .d(.noUsed) Gosub CheckCommand(.noUsed) Push .noUsed .noUsed<=temp .count++ } Sub CheckCommand(X) If Match("N") Then { If Number=1 Then { \\ use Interface For .d(X) { Group kk { pNext=-1} This=kk } } } End Sub } Module Mfree { Read mf If .IsNull(mf) Then Error "Invalid Pointer" old=.noUsed .noUsed<=mf .d(mf)=.Null .d(mf).Null<=old .count-- } Function Property { Read A, A$ A$=".d(A)."+A$ ' M2000 has string pointers If .IsNull(A) Then Error "Invalid Pointer "+str$(A) =Eval(A$) If Match("N") Then A$.=Number } Function Property$ { Read A, A$ A$=".d(A)."+A$ If .IsNull(A) Then Error "Invalid Pointer" =Eval$(A$.) ' look . after A$ \\ A$. is Not A$ is a pointer To If Match("S") Then A$. = letter$ } Function CopyObj { Read A If .IsNull(A) Then Error "Invalid Pointer" =.d(A) } Module CopyBack { Read A If .IsNull(A) Then Error "Invalid Pointer" If valid(.d(A).pnext) Then { k=.d(A).pnext Read .d(A) If valid(.d(A).pnext) Else { For .d(A) { Group kk { pnext } This=kk } } .d(A).pnext<=k } Else { Read .d(A) } } Module SwapFast { Read A, B If .IsNull(A) Then Error "Invalid Pointer A" If .IsNull(B) Then Error "Invalid Pointer B" Swap .d(A), .d(B) } Module SwapLinked { Read A, B \\ no error checking if we don't have linked list If .IsNull(A) Then Error "Invalid Pointer A" If .IsNull(B) Then Error "Invalid Pointer B" ka=.d(A).pnext : kb=.d(B).pnext Swap .d(A), .d(B) .d(A).pnext<=ka : .d(B).pnext<=kb } Module DeleteLinked { Read A \\ no error checking if we don't have linked list If .IsNull(A) Then Error "Invalid Pointer" B=.d(A).pnext If .IsNull(B) Then Exit 'deleted .d(A).pnext<=.d(B).pnext .MFree B } Function PopOne { Read &A If .IsNull(A) Then Error "Invalid Pointer" =.d(A) B=.d(A).pnext .MFree A A=B } } Return
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου
You can feel free to write any suggestion, or idea on the subject.