Τετάρτη 20 Μαΐου 2026

Revision 34 Version 14

 Now M2000 can use object arrays (4 byte per item, pointer to object - any object) to hold at the end a buffer object which is an array of memory items (in a flat manner). Although if we use string as item we get 4 bytes for a pointer to a BSTR string. So when we use these strings we don't serialize the structure easy (as flat memory) (if we get the string representation of a buffer we get zero for BSTR pointers, unless we do some actions on data, like to write to StrPtr, M2000 keep truck of actuall strings, so the pointer on the buffer for bstr is just a copy, but if the we change the copy M2000 return dummy string "crash" without crashing)


Easy Example:

structure simple {
x as double
y as double
{ StrPtr as long} ' we make a union
name1 as string
}
simple one[5], zero
zero|name1="This is a BSTR string"
Print len(Simple)=20 ' 20 bytes, 2x8 bytes double, 4 bytes pointer to string
one[3]=zero ' copy to one at index 3 (4th item)
Print len(zero)=20, len(one)=20*5 ' 20 bytes and 100bytes
print Len(one[3]|name1)=21 ' characters = 21 words = 21*2 bytes
print one[3]|StrPtr ' this is the address of the string
print one[0]|StrPtr=0 ' this is null string
print Len(one[0]|name1)=0
' now start the real example
Object alfa[3], beta[3][2]
alfa[1]=one
print alfa[1][3]|name1="This is a BSTR string"
print alfa[1] is one, " : True"  ' we have the same object
alfa[2]=buffer(one) ' we get a copy of all items
alfa[3]=one[3] ' using one[3] we get a copy of item 3
print alfa[2] is one, " : False"  ' we have different objects
print alfa[2][3]|name1
print alfa[1][3]|StrPtr=one[3]|StrPtr, " : True"
print alfa[2][3]|StrPtr=one[3]|StrPtr, " : False"
print len(alfa[3])=20 ' one only item
print alfa[3]|name1="This is a BSTR string"
print alfa[3]|StrPtr=one[3]|StrPtr, " : False"
beta[3][0]=one
print beta[3][0] is alfa[1], " : True"
beta[3][0][3]|name1="New string"
print alfa[1][3]|name1="New string", " : True"
print one[3]|name1="New string", " : True"
' we can put an object in an array of objects too
beta[3][2]=alfa
print beta[3][2][1][3]|name1="New string", " : True"
zero=beta[3][2][1][3] 'we get the index 3 of object at beta[3][2][1]
' zero is a copy
print zero|name1="New string", " : True"
print zero|StrPtr<>beta[3][2][1][3]|StrPtr, " : True"
zero=beta[3][2][1]
zero[3]|name1="last string"
' zero now point to beta[3][2][1]
print zero is one, " : True"
print zero is alfa[1], " : True"
print zero is beta[3][2][1], " : True"
print zero is beta[3][0], " : True"
print beta[3][0][3]|name1="last string", " : True"


Haed Example:

structure simple {
x as double
y as double
{StrPtr as long} ' we make a union
name1 as string
}
structure bigone {
{simple}; ' import simple (using ; we bypass the uninon mechanism)
z as double * 100
}
structure bigtwo {
s as simple * 4
z as double * 10
}
bigtwo two[10]
bigone one[5]
simple zero
zero|name1="This is a BSTR string"
print len(Simple)=20 ' 20 bytes, 2x8 bytes double, 4 bytes pointer to string
one[3]=zero
print len(zero)=20, len(one)=(20+100*8)*5 ' 20 bytes and 100bytes
print one[3]|name1=zero|name1, one[3]|StrPtr<>zero|StrPtr
print Len(two)=(4*20+10*8)*10
two[2]|s[1]=zero
print two[2]|s[1]|name1=zero|name1, two[2]|s[1]|StrPtr<>zero|StrPtr
two[2]|s[1]|name1="new string"
print two[2]|s[1]|name1=zero|name1, " : False"
zero=two[2]|s[1] ' get a copy
print two[2]|s[1]|name1=zero|name1, two[2]|s[1]|StrPtr<>zero|StrPtr
' now the real example
Object alfa[4], beta[3][2]
alfa[2]=two
print alfa[2][2]|s[1]|name1=zero|name1
beta[3][1]=one
print beta[3][1][3]|name1="This is a BSTR string"
beta[3][1][3]=zero ' copy because ...[3] is index to buffer at beta[3][1]
print type$(beta[3][1])="Buffer"
print beta[3][1][3]|name1=zero|name1
print_name1(beta[3][1][3])
print_name2(zero) ' zero is object pass pointer
print zero|name1, zero|StrPtr ' we get new values.
print alfa[2][2]|s[1]|name1, alfa[2][2]|s[1]|StrPtr, " values before call"
print_name2(alfa[2][2]|s[1]) ' pass copy
print alfa[2][2]|s[1]|name1, alfa[2][2]|s[1]|StrPtr, " same values as before call"
print_name3(alfa[2],2,1) ' alfa[2] is object - pass pointer
print alfa[2][2]|s[1]|name1, "change name"
sub print_name1(a as bigone)
print a|name1, a|StrPtr, a|z[30], " inside print_name1()"
end sub
sub print_name2(a as simple)
print a|name1, a|StrPtr, " inside print_name2()"
a|name1=a|name1+"...ok...."
end sub
sub print_name3(a as bigtwo, index, n)
print a[index]|s[n]|name1, a[index]|s[n]|StrPtr, " inside print_name3()"
a[index]|s[n]|name1=a[index]|s[n]|name1+"...ok"
end sub




Τρίτη 19 Μαΐου 2026

Test Enumeration - Δοκιμές Απαρίθμησης

 English Version:



locale 1033  ' we get True and False - using 1032 we get the Greek words
Module TestEnumNumericValue {
print "Test Enumeration Type of Numeric Value"
enum alfa {
kappa
delta
}
var m as alfa
print m=1, eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
m++
print m=2, eval$(m)="delta", m=delta, type$(m)="alfa", m^=1
m=1
print m=1, eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
try ok {
m=100
}
if error or not ok then print error$ 'we get error message Expected Enumaration Type
print m=1, eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0

clear
' clear all local variables
' make alfa start from 0 (by default is 1), also make the error value active
enum alfa {
kappa=0 ' we can use 0& for long type or 0&& for long long etc..
delta
error:
novalue=-1
}
var m as alfa
print m=0, eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
m++
print m=1, eval$(m)="delta", m=delta, type$(m)="alfa", m^=1
m=0
print m=0, eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
' this is bad value (not exist in values list of enumaration)
m=100
' then m turn to error vaue
print m=-1, eval$(m)="novalue", m=novalue, type$(m)="alfa", m^=2
m=kappa
do
print m^, type$(m^)="Long", eval$(m)
if m^=alfa^ then exit
m++
always
' we may have members of an enumaration with same value
clear
enum alfa {
kappa=0 ' we can use 0& for long type or 0&& for long long etc..
delta
epsilon=0
omega
error:
novalue=-1
}
var m as alfa
zeta=each(alfa)
oldtab=tab
// $(6,6) means center propotional print at 6 character's place column
print $(6, 6),"value", "name", "type","index", "same"
while zeta
m=eval(zeta) '  an object at index zeta^
? m, eval$(m), type$(m), m^, m^=zeta^
end while
print $(0, oldtab)
// we don't get the error value. Error value has index 4 now, but is out of the normal range.

}
module TestEnumStringValue {
print "Test Enumeration Type of String Value"
enum alfa {
kappa="North"
delta="East"
}
var m as alfa
print m="North", eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
m++
print m="East", eval$(m)="delta", m=delta, type$(m)="alfa", m^=1
m="North"
print m="North", eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
try ok {
m="Beep"
}
if error or not ok then print error$ 'we get error message Expected Enumaration Type
print m="North", eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
clear
' clear all local variables
' make the error value active
enum alfa {
kappa="True"
delta="False"
error:
novalue="?"
}
var m as alfa
print m="True", eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
m++
print m="False", eval$(m)="delta", m=delta, type$(m)="alfa", m^=1
m="True"
print m="True", eval$(m)="kappa", m=kappa, type$(m)="alfa", m^=0
' this is bad value (not exist in values list of enumaration)
m="Beep"
' then m turn to error vaue
print m="?", eval$(m)="novalue", m=novalue, type$(m)="alfa", m^=2
m=kappa
do
print m^, type$(m^)="Long", eval$(m)
if m^=alfa^ then exit
m++
always
' we may have members of an enumaration with same value
clear
enum alfa {
kappa="True"
delta="False"
epsilon="True"
omega="False"
error:
novalue="?"
}
var m as alfa
zeta=each(alfa)
oldtab=tab
// $(6,6) means center propotional print at 6 character's place column
print $(6, 6),"value", "name", "type","index", "same"
while zeta ' this is a variation of while using an iterator object
m=eval(zeta) '  an object at index zeta^
print m, eval$(m), type$(m), m^, m^=zeta^
end while
print $(0, oldtab)
// we don't get the error value. Error value has index 4 now, but is out of the normal range.
}
TestEnumNumericValue
TestEnumStringValue


Greek Version:



Τοπικό 1032 'θα έχουμε στα ελληνικά το Αληθές Ψευδές
Τμήμα ΔοκιμήΑπαρίθμησηςΑριθμητικήςΤιμής {
τύπωσε "Δοκιμή Απαρίθμησης με Αριθμητική Τιμή"
απαρ άλφα {
κάππα
δέλτα
}
μεταβλητή μ ως άλφα
τύπωσε μ=1, εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
μ++
τύπωσε μ=2, εκφρ$(μ)="δέλτα", μ=δέλτα, τύπος$(μ)="άλφα", μ^=1
μ=1
τύπωσε μ=1, εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
δες οκ {
μ=100
}
αν λάθος ή όχι οκ τότε τύπωσε λάθος$ 'θα πάρουμε το μήνυμα Λάθους Περίμενα τύπο απαρίθμησης
τύπωσε μ=1, εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0

καθαρό
' καθαρίζουμε όλες τις τοπικές του τμήματος
' κάνουμε το άλφα να ξεκινάει από το 0 (εξ ορισμού είναι το 1), επίσης ενεργοποιούμε τη λάθος τιμή.
απαρ άλφα {
κάππα=0 ' με 0& για Μακρύς ή 0&& για Μακρύς Μακρύς κ.ο.κ.
δέλτα
λάθος:
μη_τιμή=-1
}
μεταβλητή μ ως άλφα
τύπωσε μ=0, εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
μ++
τύπωσε μ=1, εκφρ$(μ)="δέλτα", μ=δέλτα, τύπος$(μ)="άλφα", μ^=1
μ=0
τύπωσε μ=0, εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
' δίνουμε μια τιμή που δεν υπάρχει στη λίστα τιμών της απαρίθμησης
μ=100
' το μ θα πάρει την τιμή λάθους
τύπωσε μ=-1, εκφρ$(μ)="μη_τιμή", μ=μη_τιμή, τύπος$(μ)="άλφα", μ^=2
μ=κάππα
επανέλαβε
τύπωσε μ^, τύπος$(μ^)="Long", εκφρ$(μ)
αν μ^=άλφα^ τότε έξοδος
μ++
πάντα
' μπορούμε να έχουμε μέλη απαρίθμησης με ίδια τιμή
καθαρό
απαρ άλφα {
κάππα=0 ' με 0& για Μακρύς ή 0&& για Μακρύς Μακρύς κ.ο.κ.
δέλτα
έψιλον=0
ωμέγα
λάθος:
μη_τιμή=-1
}
μεταβλητή μ ως άλφα
ζήτα=κάθε(άλφα) ' το ζήτα είναι ένα αντικείμενο επαναλήπτης με το άλφα εντός
παλιά_στήλη=στήλη
// $(6,6) σημαίνει αναλογική γραφή με κεντράρισμα στη στήλη και στήλη 6 χαρακτήρων (μη αναλογικών)
τύπωσε $(6, 6),"τιμή", "όνομα", "τύπος","δείκτης", "όμοιος"
ενώ ζήτα ' η ενώ εδώ είναι παραλλαγή της ενώ και δουλεύει με επαναλήπτη
μ=εκφρ(ζήτα) '  μας δίνει ένα αντικειμενο του άλφα με δείκτη ζήτα^
τύπωσε μ, εκφρ$(μ), τύπος$(μ), μ^, μ^=ζήτα^
τέλος ενώ
τύπωσε $(0, παλιά_στήλη)
// δεν θα δούμε την τιμή του λάθους εδώ γιατί είναι εκτός λίστας (πάντα είναι στο δείκτη άλφα^+1, ακριβώς μετά το τελευταίο)
}
Τμήμα ΔοκιμηΑπαρίθμησηςΑλφαριθμητικήςΤιμής {
τύπωσε "Δοκιμή Απαρίθμησης με Αλφαριθμητική Τιμή"
απαρ άλφα {
κάππα="North"
δέλτα="East"
}
μεταβλητή μ ως άλφα
τύπωσε μ="North", εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
μ++
τύπωσε μ="East", εκφρ$(μ)="δέλτα", μ=δέλτα, τύπος$(μ)="άλφα", μ^=1
μ="North"
τύπωσε μ="North", εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
δες οκ {
μ="Beep"
}
αν λάθος ή όχι οκ τότε τύπωσε λάθος$ 'θα πάρουμε το μήνυμα Λάθους Περίμενα τύπο απαρίθμησης
τύπωσε μ="North", εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
καθαρό
' καθαρίζουμε όλες τις τοπικές του τμήματος
' ενεργοποιούμε τη λάθος τιμή.
απαρ άλφα {
κάππα="Αληθές"
δέλτα="Ψευδές"
λάθος:
μη_τιμή="?"
}
μεταβλητή μ ως άλφα
τύπωσε μ="Αληθές", εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
μ++
τύπωσε μ="Ψευδές", εκφρ$(μ)="δέλτα", μ=δέλτα, τύπος$(μ)="άλφα", μ^=1
μ="Αληθές"
τύπωσε μ="Αληθές", εκφρ$(μ)="κάππα", μ=κάππα, τύπος$(μ)="άλφα", μ^=0
' δίνουμε μια τιμή που δεν υπάρχει στη λίστα τιμών της απαρίθμησης
μ="Beep"
' το μ θα πάρει την τιμή λάθους
τύπωσε μ="?", εκφρ$(μ)="μη_τιμή", μ=μη_τιμή, τύπος$(μ)="άλφα", μ^=2
μ=κάππα
' το άλφα εξ ορισμού έχει δείκτη στο τελευταίο κανονικό στοιχείο (όχι στο λάθος)
επανέλαβε
τύπωσε μ^, τύπος$(μ^)="Long", εκφρ$(μ)
αν μ^=άλφα^ τότε έξοδος
μ++ ' αλλάζουμε τιμή με αλλαγή του δείκτη αλλά δεν αλλάζει στο τέρμα.
πάντα
' μπορούμε να έχουμε μέλη απαρίθμησης με ίδια τιμή
καθαρό
απαρ άλφα {
κάππα="Αληθές"
δέλτα="Ψευδές"
έψιλον="Αληθές"
ωμέγα="Ψευδές"
λάθος:
μη_τιμή="?"
}
μεταβλητή μ ως άλφα
ζήτα=κάθε(άλφα) ' το ζήτα είναι ένα αντικείμενο επαναλήπτης με το άλφα εντός
παλιά_στήλη=στήλη
// $(6,6) σημαίνει αναλογική γραφή με κεντράρισμα στη στήλη και στήλη 6 χαρακτήρων (μη αναλογικών)
τύπωσε $(6, 6),"τιμή", "όνομα", "τύπος","δείκτης", "όμοιος"
ενώ ζήτα ' η ενώ εδώ είναι παραλλαγή της ενώ και δουλεύει με επαναλήπτη
μ=εκφρ(ζήτα) '  μας δίνει ένα αντικειμενο του άλφα με δείκτη ζήτα^
τύπωσε μ, εκφρ$(μ), τύπος$(μ), μ^, μ^=ζήτα^
τέλος ενώ
τύπωσε $(0, παλιά_στήλη)
// δεν θα δούμε την τιμή του λάθους εδώ γιατί είναι εκτός λίστας (πάντα είναι στο δείκτη άλφα^+1, ακριβώς μετά το τελευταίο)
}
ΔοκιμήΑπαρίθμησηςΑριθμητικήςΤιμής
ΔοκιμηΑπαρίθμησηςΑλφαριθμητικήςΤιμής



Δευτέρα 18 Μαΐου 2026

Ταξινόμηση τύπου Κύκλου

 Η τακινόμηση τύπου κύκλου είναι ένας αλγόριθμος ταξινόμησης με τα παρακάτω χαρακτηριστικά:

- In Place  (Στο τόπο) : Η ταξινόμηση γίνεται στον ίδιο πίνακα όχι σε βοηθητικό ή πρόχειρο.

- Unstable (Ασταθής): Μια ασταθή ταξινόμηση είναι αυτή που τα όμοια "κλειδιά" χάνουν την σειρά τους. Αν είχαμε για κάθε κλειδί μια τιμή δεδομένων τότε θα βλέπαμε τα δεδομένα να χάνουν την σειρά τους από αυτήν που είχαν στην αρχική τοποθέτηση στο πίνακα. Εδώ δεν έχουμε τιμές και κλειδιά, αλλά θα μπορούσαμε να είχαμε και έναν  δεύτερο πίνακα με τιμές και να κάναμε τις αλλαγές όπως στα κλειδιά.

- Comparison Sort (Ταξινόμηση βάσει Σύγκρισης). Στη ταξινόμηση βάσει σύγκρισης γίνονται μεταφορές στοιχείων όταν υπολογιστεί η θέση του στοιχείου.

Tο πρόγραμμα που ακολουθεί είναι η ελληνική εκδοχή του προγράμματος σε Μ2000 με αγγλικές εντολές

Ο πίνακας π() είναι τύπου Άτυπος (εξ ορισμού αν δεν δηλωθεί αλλιώς). Ο Άτυπος ή Variant είναι ο τύπος που αλλάζει ανά στοιχείο. Στη Συνάρτηση ΤαξινόμησηΚύκλου() έχουμε μια τοπική το Στοιχείο που είναι Άτυπος, γιατί θέλουμε να παίρνει τιμή είτε αριθμητική είτε αλφαριθμητική.

Η συνάρτηση ΤαξινόμησηΚύκλου() είναι απλή συνάρτηση της Μ2000. Οι απλές συνάρτησης είναι μέρος του τμήματος που της καλεί. Παλαιότερα για να καλέσουμε μια απλή συνάρτηση βάζαμε το @ μπροστά από το όνομα (ισχύει ακόμα) αλλά μπορούμε να μην το βάλουμε και βρίσκει ο διερμηνευτής τη πρώτη φορά ότι εννοούμε την απλή συνάρτηση και το απομνημονεύει για μελλοντική κλήση. Η χρήση του @ κάνει ελαφρά πιο γρήγορη τη κλήση.

Ο πίνακας π() παιρνάει με αναφορά στην ΤαξινόμησηΚύκλου. Για αυτό το πρόγραμμα το πέρασμα με αναφορά είναι πλεοονασμός, αφού η απλή συνάρτηση βλέπει τον π() και την χρησιμοποιούμε μόνο για τον π(). Εδώ είναι  μια άσκηση να αλλάξει κάποιος το πρόγραμμα και να δουλεύει χωρίς να περάσουμε με αναφορά τον π(). Δείτε ότι όταν περνάμε με αναφορά έναν πίνακα το & πρέπει να το έχουμε και στις δυο πλευρές, στην πλευρά του καλούντα και  στη πλευτά του καλούμενου. Δείτε επίσης ότι παρενθέσεις έχουν και οι πίνακας και οι συναρτήσεις στη Μ2000. Αν έχουμε πίνακα με ίδιο όνομα με συνάρτηση τότε η Μ2000 διαλέγει τον πίνακα εκτός αν βάλουμε το * αμέσως μετά το όνομα και την ανοικτή παρένθεση στη κλήση για να του πούμε ότι θέλουμε τη συνάρτηση ΤαξινόμησηΚύκλου(*&π())  (αυτό αν έχουμε ήδη ένα πίνακα ΤαξινόμησηΚύκλου() (που δεν υπάρχει περίπτωση να έχουμε...αλλά λέμε τώρα σε περίπτωση που θα υπήρχε τι θα έκανε ο διερμηνευτής).

Ένα άλλο θέμα συζήτησης είναι το Για Επόμενο. Εδώ στην δήλωση Επόμενο έχουμε βάλει την μεταβλητή ελέγχου, ενώ είναι προαιρετικό (δηλαδή μπορούμε να το αφαιρέσουμε). Αν υπάρχει όπως τώρα απλά ελέγχει ο διερμηνευτής ότι είναι αυτό το όνομα που πρέπει, και αν δεν είναι βγαίνει λαθος. Δεν υπάρχει πρακτικός άλλος λόγος, γιατί ξέρει ακριβώς σε ποια μεταβλητή σχετίζεται το Επόμενο. Αν βάλουμε ένα παραπανίσιο Επόμενο θα βγει λάθος γιατί θα καταλάβει ο διερμηνευτής ότι δεν υπάρχει Για αντίστοιχη της Επόμενο. Η Για Επόμενο μπαίνει σε ένα σωρό επιστροφής ειδικό για το τρέχον νήμα εκτέλεσης, και σε αυτό μπαίνουν και τα Αν Τέλος Αν καθώς και το Επίλεξε Με (δεν μπαίνουν τα Για με μπλοκ και τα Ενώ και τα Επανέλαβε γιατί υλοποιούνται με μπλοκ πάντα ακόμα και αν στα Ενώ βάλουμς  Τέλος Ενώ και στην Επανέλαβε δεν βάλουμε μπλοκ μεταξύ Επανέλαβε και Μέχρι ή Πάντα ή Όσο).

Επίσης η Για όπως υλοποιείται στην Μ2000 πάντα εκτελεί μια φορά τουλάχιστον το σώμα της. Εκτός αν δώσουμε στην αρχή του τμήματος το BASIC οπότε μόνο για το τμήμα η Για δουλεύει όπως η Basic (αλλά και η ΠΙΝΑΚΑΣ φτιάχνει ν+1 στοιχεία από ν, πχ Πίνακας Α(10) φτιάχνει από 0 έως και 10, συνολικά 11 στοιχεία, και επίσης η εντολή Διάβασε δουλεύει όπως το read της Basic, με τα Data (Σειρά) και Restore (Επαναφορά) όπως της Basic (BBC BASIC)).

Μας ενδιαφέρει λοιπόν να δούμε τι γίνεται στην Για ι = Αρχή_Κύκλου+1 Έως Άνω_Όριο, αν υπάρχει περίπτωση να έχουμε Αρχή_Κύκλου+1>Άνω_Όριο γιατί σε αυτήν την περίπτωση θα πρέπει να βάλουμε μια Αν  Αρχή_Κύκλου+1<=Άνω_Όριο Τότε / Βάζουμε τη Για ανάμεσα/ Τέλος Αν, αν δεν έχουμε το τρόπο της BASIC όπου το βήμα είναι θετικό και αν ΑρχικήΤιμή>ΤελικήΤιμή τότε παρακάμπτει το Για. Στην Μ2000 το βήμα δεν έχει πρόσημο, και η κατεύθυνση ορίζεται από τις τιμές Αρχική και Τελική. Με μηδενικό βήμα εκτελείται μια φορά το Για.

Το παρακάτω πρόγραμμα θα εκτελεστεί μια φορά και θα δώσει 1 (αυτό ισχύει και σε επιλογή BASIC)

για ι=1 εως 10 ανά 0
? ι
επόμενο ι

Ενώ αυτό χωρίς τη BASIC εντολή θα δώσει τα 10 έως 0, ενώ με την εντολή BASIC δεν θα δώσει τίποτα γιατί το βήμα είναι μη μηδενικό και αφού δεν το δώσαμε είναι το 1:

//	BASIC
για ι=10 εως 0
? ι
επόμενο ι

Τα παραπάνω παραδείγματα τα γράφουμε σε ένα τμήμα. Δείτε τις οδηγίες για το τμήμα Α παρακάτω (αντί να βάλουμε με επικόλληση το πρόγραμμα Ταξινόμηση τύπου Κύκλου, γράφουμε το πρόγραμμά μας).

Σώνουμε όλα τα  φορτωμένα/διορθωμένα τμήματα με το Σώσε Όνομα123 και με το Νεο τα καθαρίζουμε. Καμιά φορά μπορεί να χρειαστεί και το Καθαρό που σβήνει τυχόν μεταβλητές γενικές που φτιάξαμε στην κονσόλα - όχι σε τμήμα, και το Άδειασε που αδειάζει το σωρό τιμών.  Μπορούμε να δούμε αν έχουμε μεταβλητές με την εντολή Λίστα (και μέσα σε τμήμα) και να δούμε τις τιμές στο σωρό τιμών με την Σωρός (και μέσα σε τμήματα). Επίσης μπορούμε να δούμε τα τμήματα με την Τμήματα και Τμήματα ? (με το ερωτηματικό μόνο τα φορτωμένα, ενώ χωρίς τα δείχνει όλα, και τα φορτωμένα και τα προγράμματα που μπορούν να έχουν πολλά τμήματα). Σημειώστε ότι ένα τμήμα μπορεί να έχει πολλά τμήματα αλλά με την Τμήματα βλέπουμε όσα τμήματα είναι ενεργά δηλαδή έχουν δηλωθεί. Τα τμήματα μέσα σε τμήμα δεν θα δηλωθούν όσο το τμήμα δεν εκτελείται

Η απλή συνάρτηση ΤαξινόμησηΚύκλου() λέγεται απλή γιατί δεν είναι όπως το τμήμα, με δήλωση στην αρχή, αλλά στατική συνάρτηση του τμήματος. Στατική σημαίνει ότι δεν είναι δυναμική, δεν μπορεί να αλλάξει κώδικα. Μια κανονική συνάρτηση δηλώνεται με το Συνάρτηση Όνομα { } ή Συνάρτηση Όνομα(χ, ψ) { } και κάθε φορά που δηλώνεται στο ίδιο τμήμα, αλλάζει κώδικα! Επίσης μια κανονική συνάρτηση έχει δικά της τμήματα και συναρτήσεις και απλές συναρτήσεις καθώς και ρουτίνες επειδή έχει Όνομα Χώρου (δίνει το πρόθεμα που δεν βλέπουμε στα νέα αναγνωριστκά). Ετσι μια απλή συνάρτηση: Δεν έχει δικό της όνομα χώρου, δεν έχει δικά της τμήματα/συναρτήσεις, και πρέπει να χρησιμοποιεί την Τοπικό/Τοπική/Τοπικές για να δημιουργεί τοπικές μεταβλητές (που σκιάζουν τυχόν μεταβλητές με το ίδιο όνομα) γιατί εντός της απλής συνάρτησης είναι θεατό οτιδήποτε έχει φτιαχτεί στο τμήμα. Επίσης μια απλή συνάρτηση έχει πρόσβαση στον σωρό τιμών του τμήματος/συνάρτησης από όπου τη καλούμε ενώ μια κανονική συνάρτηση όταν καλείται σε έκφραση έχω πάντα δικό της σωρό τιμών. Μια απλή συνάρτηση μπορεί να κληθεί μόνο σε έκφραση, ενώ μια κανονική συνάρτηση μπορεί να κληθεί με τη Κάλεσε σαν τμήμα (με σωρό τον σωρό του καλούντα). Μια κανονική συνάρτηση μπορεί να περαστεί με αναφορά ενώ μια απλή όχι.

Σε άλλες γλώσσες υπάρχει μια και μόνο συνάρτηση. Συνήθως όμως σε αυτές τις γλώσσες δεν υπάρχει συνάρτηση στη συνάρτηση. Μια βασική διαφορά στη Μ2000 είναι η θέαση άλλων αναγνωριστικών σε σχέση με τους δυο τύπους συναρτήσεων. Στην κανονική συνάρτηση είναι θεατά μόνο τα τοπικά που  δεν δηλώνονται τοπικά γιατί εξ ορισμού ότι φτιάχνουμε είναι τοπικά, και τα γενικά. Στην απλή συνάρτηση είναι θεατό οτιδήποτε είναι θεατό σε αυτό που τη κάλεσε. Αυτή είναι μια ουσιαστική διαφορά. Στη C σε μια συνάρτηση είναι θεατό οτιδήποτε έχει δηλωθεί στο αρχείο που είναι γραμμένη, η δε συνάρτηση αν δηλωθεί static δεν θα είναι θεατή έξω από το αρχείο (εξ ορισμού οι συναρτήσεις είναι extern δηλαδή αν το αρχείο γίνει import σε άλλο αρχείο τότε όλες οι extern συναρτήσεις θα είναι θεατές σε αυτό). Η C επεξεργάζεται το πρόγραμμα πριν το εκτελέσει (compiler). Η Μ2000 εκτελεί άμεσα το πρόγραμμα και βασίζεται στο τρόπο που ορίζουμε κάτι για να γγνωρίζει τι να κάνει με αυτό. Η Συνάρτηση ΤαξινόμησηΚύκλος δεν δηλώνεται σαν κανονική συνάρτηση (θα μπορούσε να δηλωθεί), οπότε όταν ζητηθεί με @ΤαξινόμνησηΚύκλου() θα αναζητηθεί στη λίστα στατικών και αν δεν βρεθεί θα αναζητηθεί στο κώδικα, και αν βρεθεί θα γραφτεί στη λίστα στατικών και θα εκτελεστεί. Στην επόμενη κλήση ήδη θα υπάρχει στη λίστα και έτσι δεν θα γίνει αναζήτηση. Αν δεν χρησιμοποιήσουμε το @ και δώσουμε τη πρώτη φορά το ΤαξινόμησηΚύκλου() πρώτα θα αναζητηθεί αν είναι πίνακας, αν δεν βρεθεί θα αναζητηθεί στη λίστα κανονικών συναρτήσεων, αν δεν βρεθεί θα υποθέσει ο διερμηνευτής ότι ζηταμε στατική και θα βάλει έναν μεσολαβητή. Ο μεσολαβητής λέει ότι το όνομα ΤαξινόμησηΚύκλου() είναι στατική. Αν δεν βρεθεί η στατική τότε βγαίνει λάθος και πετάει τον μεσολαβητή το σύστημα. Αν βρεθεί γίνεται κανονικά η εγγραφή στη λίστα στατικών και εκτελείται. Τη δευτερη φορά αν χρησιμοποιήσουμε το @ θα βρεί αμέσως ο διερμηνευτής τη συνάρτηση στη λιστα στατικών ενώ αν δεν το χρησιμοποιήσουμε τότε εκεί που ψάχνουμε για κανονική συνάρτηση θα βγει ο μεσολαβητής και θα δηλώσει ότι είναι στατική και έτσι θα εκτρέψει τη ροή στην εκτέλεση της στατικής (εύρεση από τη λίστα στατικών και εκτέλεση). Η "πατέντα" με τον μεσολαβητή έκανε τον διερμηνευτή να εκτελεί τις απλές συναρτήσεις χωρίς τη χρήση του @ (όπως είδατε το ζήτημα δεν ήταν απλά να δούμε πως θα εκτελεστεί η απλή συνάρτηση αλλά τι θα γίνει αν δώσουμε όνομα που δεν υπάρχει). Γενικά στο προγραμματισμό πρέπει να σκεφτόμαστε για κάτι διπλά, μια φορά αν αυτό που έχουμε είναι πραγματικό και μια αν δεν είναι, και αυτό ισχύει και με τα νούμερα, μια φορά αν τα νούμερα είναι αποδεκτά και μια φορά αν δεν είναι. Και αυτό το σκεφτόμαστε και στις επαναλήψεις, πότε μια επανάληωη θα γίνει και πότε όχι.  Επίσης πρέπει να σκεφτόμαστε και πώς θα τερματίσει μια επανάληψη και πώς δεν θα τερματίσει σε εύλογο διάστημα (άρα να έχουμε υπολογίσει πόσο χρόνο χρειάζεται περίπου για το σκοπό της χρήσης).

Στην ταξινόμηση κύκλου  ο χρόνος έχει σχέση με το πόσα στοιχεία έχουμε. Δείτε ότι η Αρχή_κύκλου ξεκινάει από το κάτω όριο του πίνακα (εδώ είναι το 0) και πάει στο πάνω όριο μειον ένα. Αν ο πίνακας έχει λιγότερα από 2 στοιχεία δεν έχουμε ταξινόμηση. Αν έχουμε 2 τότε το πάνω όριο είναι το 1 άρα η Αρχή_κύκλου θα πάει από το 0 μέχρι το 1-1 = 0, άρα θα έχουμε μια μόνο επανάληψη (δεν θα έχουμε πρακτικά καμία επανάληψη, απλά θα εκτελεστεί ο κώδικας της επανάληψης μια φορά). Μετά κοιτάμε από την Αρχή_κύκλου+1 μέχρι το Άνω όριο, δηλαδή από το 0+1=1 μέχρι το 1 (τόσο είναι το άνω όριο) οπότε θα έχουμε εδώ μια φορά την επανάληψη (από 1 μέχρι 1) και σε αυτήν θα κάνουμε έλεγχο α(ι)<Στοιχείο και αν ναι τότε προσθέτουμε ένα στη Θέση_στοιχείου. Αφού τελειώσει η επανάληψη κοιτάμε αν η Θέση_στοιχείου μεγάλωσε από την αρχική. Αν δεν μεγάλωσε τότε πάμε στην επομενη Αρχή_κύκλου (σημαίνει ότι το στοιχείο είναι στη θέση του). Ας υποθέσουμε εδώ ότι πράγματι μεγάλωσε η Θέση_στοιχείου. Κοιτάμε αν στο στοιχείο που θελουμε να βάλουμε στοιχείο είναι ήδη κάποιο στοιχείο με ίδια τιμή και αν είναι αυξάνουμε τη Θέση_στοιχείου. Τώρα αν προσέξουμε θα δούμε ότι αυξάνουμε τη Θέση_στοιχείου χωρίς να κοιτάμε αν φτάσαμε στο τέλος! Πράγματι δεν μας νοιάζει εδώ γιατί ξέρουμε κάτι σίγουρο, ότι υπάρχει ένα α(ι) που είναι μικρότερο από το Στοιχείο, άρα ξέρουμε ότι το Θέση_στοιχείου δεν θα περάσει το ι. Όταν τελειώσει και αυτή η επανάληψη θα κάνουμε την αλλαγή με την Άλλαξε α(Θέση_στοιχείου), Στοιχείο. Τώρα το Στοιχείο θα πρέπει να μπεί κάπου μεταξύ της αρχή_κύκλου έως Θέση_στοιχείου-1. Επίσης επειδή μας ενδιαφέρει να γράφουμε τον αριθμό μεταφορών αυξάνουμε τη μεταβλητή Μεταφορές κατά ένα. Ξεκινάμε για τη τελική επανάληψη που γίνεται όσο η Θέση_Στοιχείου δεν συμπίμπτει με την Αρχή_Κύκλου. Πράγματι στην αρχή δεν συμπίπτει γιατί είναι η Θέση_Στοιχείου που βρέθηκε το α(ι)<Στοιχείο και ξεκίνησε από το Αρχή_Κύκλου+1. Το πρώτο πράγμα που κάνουμε εντός της επανάληψης είναι να πάμε τη Θέση_Στοιχείου στην Αρχή_Κύκλου, φτιάχνοντας δηλαδή τη τιμή που η συνθηκη της επανάληψης ΔΕΝ ικανοποιείται, δηλαδή που τερματίζει την επανάληψη. Μετά πάμε σε μια Για ι = Αρχή_Κύκλου + 1 Έως Άνω_Όριο. Σκεφτήτε εδώ ότι από τηνΑρχή_Κύκλου πήραμε το στοιχείο στο 0 και βρήκαμε ότι στο 1 το α(1)<Στοιχείο, και μετά αλλάξαμε το Στοιχείο με το α(1), και τώρα έχουμε στο α(0) το προηγούμενο στοιχείο που είναι και στο α(1), και το Στοιχείο που είναι το παλιό α(1) και δεν είναι αυτή τη στιγμή στο πίνακα!  Όταν πάμε λοιπόν στο Για θα πάμε στο α(1) που είναι το αντίγραφο του α(0), κα θα το συγκρίνουμε με το Στοιχείο, το παλιό α(1), όμως το Στοιχείο είναι μικρότερο από το α(1) (που είναι το α(0) αντίγραφο) άρα το α(ι)<Στοιχείο δεν ισχύει. Τερματίζει η Για και πάμε στην Ενώ για τα όμοια. Δεν υπάρχει όμοιο στη πρώτη θέση, στη θέση_στοιχείου, δεν ικανοποιείται η συνθήκη Στοιχείο=α(Θέση_στοιχείου), φεύγουμε από το Ενώ και πάμε στην αλλαγή, με την Άλλαξε α(Θέση_στοιχείου), Στοιχείο και έτσι το Στοιχείο που είναι το παλιό α(1) γίνεται α(0). Τώρα όλα τα στοιχεία είναι στον πίνακα. Και αυξάνουμε τον αριθμό μεταφορών κατά ένα. Επειδή δεν άλλαξε τιμή η Θέση_στοιχείου και δείχνει στη τιμή του Αρχή_κύκλου τερματίζει η Ενώ. Τερματίζει και η Για με επόμενο το Αρχή_κύκλου. Επιστρέφουμε τη τιμή μεταφορές και τερματίζει η συνάρτηση.


Ο χρόνος που θα χρειστεί η συνάρτηση εξατιέται από τα στοιχεία που έχει ο πίνακας και αν είναι n θα έχουμε n*n ή n^2 συνολικές ενέργειες  ή διακριτές επαναλήψεις. 

Η εντολή Τύπωσε π()#ταξινόμηση()#γραφή$(", ")  κάνει άμεσα ταξινόμηση με QuickSort (Γρήγορη Ταξινόμηση) σε γλώσσα μηχανής (όχι σε Μ2000) και για το λόγο αυτό το παράδειγμα με τη Ταξινόμηση τύπου κύκλου δεν έχει πρακτική αξία, πέρα από την εκπαιδευτική σκοπιά. Βέβαια η ταξινόμηση κύκλου κάνει τις λιγότερες εγγραφές, και πρακτικά κάνει τόσες εγγραφές όσα και τα στοιχεία του πίνακα. Όταν η εγγραφή είναι κοστοβόρα τότε η Ταξινόμηση τύπου  κύκλου έχει πρακτική αξία! Στα αλφαριθμητικά στους πίνακες η Μ2000 κάνει αλλαγή στους δείκτες στα αλφαριθμητικά και όχι στα ίδια τα αλφαριθμητικά! Έτσι η αλλαγή δεν έχει να κάνει με το πόσα γράμματα έχει το αλφαριθμητικό αλλά μόνο με ένα δείκτη που έχει μέγεθος 32bit, ή 4bytes, όσο δηλαδή ένας Μακρύς (long) αριθμός. Αν αντί για το Αλλαξε α(ι), Στοιχείο χρησιμοποιούσαμε μια τρίτη μεταβλητή τότε θα δουλεύαμε με αντίγραφα, άρα θα μέτραγε το μήκος του αλφαριθμητικού. Αυτό συμβαίνει με οποιαδήποτε γλώσσα. Εξ ορισμού τα αλφαριθμητικά είναι "απρόσβλητα" από αλλαγές, και όταν προσθέτουμε ένα χαρακτήρα γίνεται το τελικό αποτέλεσμα σε νέο αλφαριθμητικό. Η Άλλαξε μας βοηθάει με το να μην δουλεύουμε με τα αλφαριθμητικά ως έχουν αλλά με τους δείκτες σε αυτά. Στην πράξη ένα αλφαριθμητικό είναι ένας δείκτης που αν εχει το 0 σημαίνει κενός αλφαριθμητικό ενώ αν έχει οτιδήποτε άλλο σημαίνει ότι εκεί που δείχνει θα έχει το πρώτο χαρακτήρα (μας λέει πόσους χαρακτήρες έχει ακριβώς 4 θέσεις πιο πίσω που γράφεται το μήκος του αλφαριθμητικού σε bytes, και ένα Unicode Utf16Le γράφεται σε μοναδες Word, δυο bytes, άρα το μήκος θα βγαίνει ζυγό). Για λόγους συμβατότητας, η VB6, με την οποία είναι γραμμένος ο διερμηνευτής της Μ2000, για  ένα κενό αλφαριθμητικό μπορεί να έχει δείκτη και στο πρώτο χαρακτήρα να έχει το μηδέν (δηλώνει και τέρμα σε ορισμένες γλώσσες), ενώ το μήκος δηλώνεται 0. Έτσι 'ενα κενό αλφαριθμητικό μπορεί να έχει δείκτη ή όχι! Στη VB6 το "" είναι κενό αλφαριθμητικό με δείκτη, ενώ το vbnullstring είναι μηδενικός δείκτης.




Πρόγραμμα Ταξινόμηση τύπου Κύκλου.

  • Ξεκινάμε το m2000.exe
  • Γράφουμε Σ Α πατάμε enter
  • Κάνουμε επικόλληση και πατάμε esc
  • Γράφουμε Α και πατάμε enter και έχουμε την εκτέλεση.
  • Αν θέλουμε να καθαρίσουμε την οθόνη (και να φύγουν και οι γραμμές πάνω που λέει στοιχεία για τον διερμηνευτή και το σύστημα) τότε γράφουμε Οθόνη , 0 και πατάμε enter. Η πρώτη παράμετρος της Οθόνη είναι το χρώμα φόντου και εδώ δεν το δίνουμε, το αφήνουμε ως έχει.
  • Με το Βοήθεια Οθόνη βλέπουμε πληροφορίες για την εντολή. Με το Βοήθεια όλα μας δίνει μια λίστα ονομάτων για επιλογή (κάνουμε κλικ σε όποιο όνομα θέλουμε).


Πίνακας π()
π()=(0, 1, 2, 2, 2, 2, 1, 9, 3.5, 5, 8, 4, 7, 0, 6)
Τύπωσε π()#γραφή$(", ")
ποσό=ΤαξινόμησηΚύκλου(&π())
Τύπωσε "Μετεγγραφές:";ποσό ' 10
Τύπωσε π()#γραφή$(", ")
π()=(38, 119, 38, 33, 33, 28, 24, 101, 108, 120, 99, 59, 69, 24, 117, 22, 90, 94, 78, 75)
Τύπωσε π()#γραφή$(", ")
ποσό=ΤαξινόμησηΚύκλου(&π())
Τύπωσε "Μετεγγραφές:";ποσό '  19
Τύπωσε π()#γραφή$(", ")
π()=("Greygill Hole", "Ogof Draenen", "Ogof Ffynnon Ddu", "Malham Tarn Pot")
Τύπωσε π()#γραφή$(", ")
ποσό=ΤαξινόμησηΚύκλου(&π())
Τύπωσε "Μετεγγραφές:";ποσό '  3
Τύπωσε π()#γραφή$(", ")


Συνάρτηση ΤαξινόμησηΚύκλου(&α())
Αν Διάσταση(α())<>1 Τότε Λάθος "Ταξινόμηση μόνο για μιας διάστασης πίνακα"
Αν Μήκος(α())<2 Τότε =0:Έξοδος Συνάρτησης
Τοπική Μακρύς Θέση_Στοιχείου, Μεταφορές, Αρχή_Κύκλου, ι
Τοπική Μακρύς Άνω_Όριο=Διάσταση(α(), 1, 1)
Τοπική Άτυπος Στοιχείο
Για Αρχή_Κύκλου=Διάσταση(α(), 1, 0) Έως Άνω_Όριο-1
Στοιχείο = α(Αρχή_Κύκλου)
Θέση_Στοιχείου = Αρχή_Κύκλου
Για ι = Αρχή_Κύκλου+1 Έως Άνω_Όριο
Αν α(ι)<Στοιχείο Τότε Θέση_Στοιχείου++
Επόμενο
Αν Θέση_Στοιχείου = Αρχή_Κύκλου Τότε Συνέχισε Για
Ενώ Στοιχείο = α(Θέση_Στοιχείου)
Θέση_Στοιχείου++
Τέλος Ενώ
Άλλαξε α(Θέση_Στοιχείου), Στοιχείο
Μεταφορές++
Ενώ Θέση_Στοιχείου <> Αρχή_Κύκλου
Θέση_Στοιχείου = Αρχή_Κύκλου
Για ι = Αρχή_Κύκλου + 1 Έως Άνω_Όριο
Αν α(ι) < Στοιχείο Τότε Θέση_Στοιχείου++
Επόμενο ι
Ενώ Στοιχείο = α(Θέση_Στοιχείου)
Θέση_Στοιχείου++
Τέλος Ενώ
Άλλαξε α(Θέση_Στοιχείου), Στοιχείο
Μεταφορές++
Τέλος Ενώ
Επόμενο Αρχή_Κύκλου
=Μεταφορές
Τέλος Συνάρτησης