Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Tabellensortierung in QBasic/Parallel Array Sorting

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu QBasic.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
BDV



Anmeldungsdatum: 16.03.2020
Beiträge: 4

BeitragVerfasst am: 16.03.2020, 03:18    Titel: Tabellensortierung in QBasic/Parallel Array Sorting Antworten mit Zitat

Ich habe eine Anzahl von fertig errechneten Variablen, die zusammen mit erklärendem Text ausgegeben werden, nach dem Muster:

Code:
PRINT "Stärke von Auto beträgt:"; Staerke%;". Somit "; Prozent%; "der Gesamtgröße."


Jetzt möchte ich, daß QBasic diese PRINT-Ausgaben nach der Größe des numerischen Werts Staerke% sortiert, also quasi eine Tabellensortierung wie in Excel vornimmt, wo man die ganze Tabelle anhand einer bestimmten Spalte sortieren kann.

Ich ahne zumindest schonmal soviel, daß ich eventuell den ganzen Satz in einen String packen muß (für das obige Beispiel würde der dann z. B. Auto$ heißen), wo ich aber allein schon daran scheitere, sowohl die obigen Buchstaben, als auch die Variablen da so reinzuschreiben, daß das Programm nicht den Namen, sondern den Wert der Variable in den String schreibt. Ich vermute, daß ich irgendwas zweidimensionales anlegen muß (eine Dimension numerisch, die andere Dimension String), wo ich dann die numerische Variable und den Textstring reintun muß, um die beiden miteinander zu verknüpfen.

Erschwerend kommt hinzu: Es existieren fünf verschiedene Kategorien von Daten, die bei der Sortierung natürlich nicht vermischt werden dürfen, sondern die Kategorien sollen getrennt gelistet werden (was ich in meinem Programm bisher durch Reihenfolge der einfachen Printbefehle nach obigem Muster regele). Nennen wir die fünf Kategorien (bzw. Listen, wobei ich bislang noch nichtmal weiß, wie man in QBasic eine zusammenhängende Liste erstellt) wie folgt:

1.) Elemente

2.) Zeichen

3.) Qualität oder Modalität

4.) Häuser

5.) Quadranten

Im Web habe ich einige Anleitungen gefunden, wie man eine solche Tabellensortierung in QBasic realisiert, aber da verstehe ich bislang von vorne bis hinten nur Bahnhof:

http://www.petesqbsite.com/sections/tutorials/tuts/dandd/basic-13.html

https://www.tapatalk.com/groups/qbasic/viewtopic.php?f=182035&t=30971

Hier: http://www.antonis.de/faq/qbmonfaq-dateien/919431092.html scheint unter dem Punkt für SHELL-Sortierung auch ein Programmbeispiel für zweidimensionale Variablen/Arrays angegeben zu werden, wo der eine Teil numerisch ist und der andere ein String und das ganze dann nach dem numerischen Wert sortiert wird.

PROBLEM: Ich habe seit über 20 Jahren kein QBasic mehr gemacht, und selbst damals nur sehr einfache Grundschulrechenaufgaben damit realisiert, mit Schleifen, IF...THEN und GOTO als dem höchstem der Gefühle (Errechnen der Primzahlen von 1-100 usw.). Mein jetziges Programm, das die verschiedenen Werte errechnet, die am Ende rauskommen und jetzt sortiert werden sollen, habe ich innerhalb von zwei Tagen mit der Hilfe von fünf anderen Leuten geschrieben, die nun mit ihrem Latein am Ende sind und auch nicht wissen, wie man Listen derartig sortiert.

Bis jetzt begreife ich kaum, was Arrays sind, was ein Begriff ist, den die anderen Leute mir in den letzten zwei Tagen andauernd um die Ohren gehauen haben, und beim Durchsuchen des Forums habe ich festgestellt, daß bei ähnlichen Problemen andauernd mit dem Begriff UDT um sich geworfen wird, wo ich selbst nach der Lektüre von https://www.freebasic-portal.de/befehlsreferenz/type-udt-360.html nicht durchsteige.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
BDV



Anmeldungsdatum: 16.03.2020
Beiträge: 4

BeitragVerfasst am: 16.03.2020, 07:14    Titel: Antworten mit Zitat

Inzwischen bin ich immerhin schonmal soweit weitergekommen, daß ich jetzt weiß, wie ich Textstrings und Variablen zu neuen Strings kombinieren kann. Sprich, alles, was in meinem obigen Beispielcode gestanden hat, ist jetzt in einem festen String Auto$ abgelegt.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
BDV



Anmeldungsdatum: 16.03.2020
Beiträge: 4

BeitragVerfasst am: 16.03.2020, 10:56    Titel: Antworten mit Zitat

Ich habe durch Googeln eine Möglichkeit gefunden, wie man über DATA eine sortierbare Tabelle in QBASIC erzeugen kann. Das blöde ist, daß DATA nicht mit Variablen funktioniert, sondern nur mit direkter Zuweisung im Code nach dem Muster:

Code:
DATA "aaa",10,"bbb",5,"ccc",27...


Mit DATA weist man jedem so definierten "STRING" den nachfolgenden numerischen Wert als auslesbaren Wert zu, so daß beide so verknüpft werden, daß man die numerischen Werte so sortieren kann, daß der dazugehörige String beim Verschieben mit auf die neue Position übernommen wird. Nur eben geht das ganze nicht mit Variablen.

Indem ich dann die Lösung mit DATA in einem Chat für QB64 gepostet habe, hat mir dann einer von den Leuten, die bisher 12 Stunden geleugnet hatten, daß man in QBASIC überhaupt sortierbare Tabellen erstellen kann, oder in der ganzen Zeit nicht darauf eingegangen waren, endlich eine gangbare Lösung mit Variablen gebastelt:

Code:
DECLARE SUB quicksort (min%, max%)
DECLARE SUB display ()
DIM SHARED a$(2), b(2)

a$(0) = "aaa"
b(0) = 10
a$(1) = "bbb"
b(1) = 37
a$(2) = "ccc"
b(2) = 4

PRINT "initial array"
display
quicksort 0, 2
PRINT "sorted array"
display
END

SUB display
    FOR i% = 0 TO 2
        PRINT a$(i%), b(i%)
    NEXT
END SUB

SUB quicksort (min%, max%)
    IF min% < max% THEN
        p1% = min%
        p2% = max%
        mid = b((min% + max%) \ 2) '**
        DO UNTIL p1% > p2%
            DO WHILE b(p1%) > mid '**<<invert this unequality to sort ascending
                p1% = p1% + 1
            LOOP
            DO WHILE mid > b(p2%) '**<<this one too
                p2% = p2% - 1
            LOOP
            IF p1% <= p2% THEN
                SWAP a$(p1%), a$(p2%) '**
                SWAP b(p1%), b(p2%) '**
                p1% = p1% + 1
                p2% = p2% - 1
            END IF
        LOOP
        IF min% < p2% THEN quicksort min%, p2%
        IF p1% < max% THEN quicksort p1%, max%
    END IF
END SUB


Die Zahlen in der am Anfang stehenden Zeile DIM SHARED definieren dabei die Zeilenlänge der Tabelle. Obwohl in diesem Beispiel an der Stelle jeweils 2 steht, werden damit praktisch drei Zeilen für die drei hier benutzten String-Zahl-Verknüpfungen generiert, da 0 die erste Zeile ist. Die in Klammern stehenden Zahlen hinter dem Variablennamen bei der Zuweisung der Werte geben die Zeile der Tabelle an, in die die Information geschrieben werden soll.

Da ich in dem Programm, das ich schreibe, 5 verschiedene: "Listen" oder Datenkategorien habe, heißt das aber wohl auch, daß ich fünf verschiedene solcher Tabellen mit je eigenem Namen anlegen muß. Da jede dieser Tabellen eine unterschiedliche Länge hat (jeweils 12, 12, 4, 3 und 3 Zeilen), muß ich auch unterschiedlich benannte Subroutinen mit jeweils angepaßter Schleifenlänge basteln.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5928
Wohnort: Deutschland

BeitragVerfasst am: 16.03.2020, 13:04    Titel: UDT Type Erklärung Antworten mit Zitat

Hallo und willkommen im Forum!

Ein String wäre ja sowas: "Hurra"

Wenn du jetzt mehrere Informationen hast, könnte dein String zum Beispiel kommaseparierte Werte enthalten wie zum Beispiel: "Hurra,250,Kellergeschoss"
Das hätte verschiedene große Nachteile: So einen zusammengematschten String kann man nicht sinnvoll nach den Spalten sortieren. Außerdem bedeutet es "String-Gefrickel", wenn du jetzt z. B. die mittlere Zahl mit irgendwas verrechnen willst.
Code:
Dim Werte As String
Werte = "Hurra,250,Kellergeschoss"

Jetzt wär's doch toll, wenn du sowas im Code machen könntest:
Code:
Print Werte.DavonDieMittlereSpalte   ' soll 250 ergeben!

Oder?

Genau das geht! happy

QBasic und FreeBASIC können nicht nur mit den sog. elementaren Datentypen umgehen. Sondern du kannst auch "zusammengesetzte" Datentypen erzeugen wie Auto mit den Eigenschaften:
- Fabrikat
- Farbe
- Anzahl Sitze
- PS

Diese Eigenschaften lassen sich zu einer Variable zusammenfassen und als Gesamtpaket im Programm nutzen. Du kannst aber ganz leicht auch auf die einzelnen Bestandteile der zusammengesetzten Variablen zugreifen, indem du an die Variable einen Punkt und den Namen der Eigenschaft anhängst:

Code:
TYPE Auto
  Fabrikat As String
  Farbe As String
  AnzahlSitze As Integer
  PS As Integer
END TYPE

Dim MeinOldtimer As Auto
MeinOldtimer.Fabrikat = "Gunilla 3000"
MeinOldtimer.Farbe = "rot"
MeinOldtimer.AnzahlSitze = 2
MeinOldtimer.PS = 50

' Und jetzt wieder auf die Werte zugreifen:
Print "Mein Oldtimer ist vom Typ "; MeinOldtimer.Fabrikat; " und hat "; MeinOldtimer.PS; " Pferdestaerken!"
Print "Wenn man das mal zwei nehmen wuerde, ergaebe das "; ( MeinOldtimer.PS * 2 ); ". Interessant, oder?"

Sleep
End

Und von diesen zusammengesetzten Variablen kannst du nicht nur eine haben, sondern auch eine ganze Reihe davon, ein "Array".
Code:
TYPE ... (siehe oben)

Dim MeinFuhrpark(1 To 5) As Auto


Mit UDTs hast du die n Werte einerseits zusammen in einer Variable - so als hättest du sie nacheinander in einen String verkettet - kannst aber problemlos einzeln darauf zugreifen. Und so kann man auch leicht nach einer bestimmten Spalte oder mehreren Spalten nacheinander sortieren.

Viele Grüße!
Sebastian
_________________
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
BDV



Anmeldungsdatum: 16.03.2020
Beiträge: 4

BeitragVerfasst am: 16.03.2020, 13:18    Titel: Antworten mit Zitat

Kommando zurück! Ich brauche keine eigene Subroutine für jede einzelne Tabelle mit indivueller Länge. Mit folgendem Code brauche ich nur eine Subroutine:

Code:
DIM Tabellenstrings1$([Tabellenlänge]), Tabellenwerte1([Tabellenlänge])
DIM Tabellenstrings2$([Tabellenlänge]), Tabellenwerte2([Tabellenlänge])

Tabellenstrings1$(0) = Hugo$
Tabellenwerte1(0) = Berta%
Tabellenstrings1$(1) = Egon$
Tabellenwerte1(1) = Dietrich%
Tabellenstrings1$(2) = Henning$
Tabellenwerte1(2) = Ida%
Tabellenstrings1$(3) = Johannes$
Tabellenwerte1(3) = Kasimir%

Tabellenstrings2$(0) = Anton$
Tabellenwerte2(0) = Caesar%
Tabellenstrings2$(1) = Friedrich$
Tabellenwerte2(1) = Gustav%

quicksort Tabellenstrings1$(), Tabellenwerte1(), 0, UBOUND(Tabellenwerte1)
display Tabellenstrings1$(), Tabellenwerte1()
PRINT 'Add a blank line to the output
quicksort Tabellenstrings2$(), Tabellenwerte2(), 0, UBOUND(Tabellenwerte2)
display Tabellenstrings2$(), Tabellenwerte2()

SUB display (Tabellenstrings$(), Tabellenwerte())
    FOR i% = 0 TO UBOUND(Tabellenwerte)
        PRINT Tabellenstrings$(i%), Tabellenwerte(i%)
    NEXT
END SUB

SUB quicksort (Tabellenstrings$(), Tabellenwerte(), min%, max%)
    IF min% < max% THEN
        p1% = min%
        p2% = max%
        mid = Tabellenwerte((min% + max%) \ 2) '**
        DO UNTIL p1% > p2%
            DO WHILE Tabellenwerte(p1%) > mid '**<<invert this unequality to sort ascending
                p1% = p1% + 1
            LOOP
            DO WHILE mid > Tabellenwerte(p2%) '**<<this one too
                p2% = p2% - 1
            LOOP
            IF p1% <= p2% THEN
                SWAP Tabellenstrings$(p1%), Tabellenstrings$(p2%) '**
                SWAP Tabellenwerte(p1%), Tabellenwerte(p2%) '**
                p1% = p1% + 1
                p2% = p2% - 1
            END IF
        LOOP
        IF min% < p2% THEN quicksort Tabellenstrings$(), Tabellenwerte(), min%, p2%
        IF p1% < max% THEN quicksort Tabellenstrings$(), Tabellenwerte(), p1%, max%
    END IF
END SUB


Damit werden zwei Tabellen erzeugt, Tabelle1 mit vier Zeilen und Tabelle2 mit zwei Zeilen.

Das geniale daran, was ich zuerst überhaupt nicht kapiert habe: Man braucht Tabellenstrings$ und Tabellenwerte (ACHTUNG: ohne die Zahlen am Ende zur Ansprache von Tabelle1 und Tabelle2!) zur Festlegung der Loopanzahl nicht einzeln mit je einer Definitionsformel (wie weiter oben noch mit DECLARED SUB) zu definieren (um jeweils einmal eine zwei- und eine vierzeilige Tabelle zu sortieren), obwohl sie als Variablen erst in den Subroutinen das erstemal auftauchen! Man setzt die jeweils nötige Anzahl der Abfrageloops ganz einfach viel weiter oben mit UBOUND und im Aufruf der jeweiligen Subroutine:

Code:
quicksort Tabellenstrings1$(), Tabellenwerte1(), 0, UBOUND(Tabellenwerte1)
display Tabellenstrings1$(), Tabellenwerte1()
PRINT 'Add a blank line to the output
quicksort Tabellenstrings2$(), Tabellenwerte2(), 0, UBOUND(Tabellenwerte2)
display Tabellenstrings2$(), Tabellenwerte2()
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1000
Wohnort: Ruhrpott

BeitragVerfasst am: 16.03.2020, 19:20    Titel: Antworten mit Zitat

Hallo BDV!

Auch wenn die Verwendung von selbstdefinierten Datentypen (UDTs) für Dich Neuland und somit gewöhnungsbedürftig ist: Ich empfehle Dir dringend, Sebasitans Vorschlag zu folgen, denn die Handhabung der Datensätze wird dadurch SEHR viel einfacher.

Du kannst dir einen UDT als einen Karton vorstellen, der seinerseits mehre Kartons enthält. Du kannst -je nach Bedarf- den Karton aufmachen und dir den Inhalt ansehen, oder alles zusammen in EINEM Karton abtransportieren.

Wenn Du z.B. -um mal bei Sebastians Beispiel zu bleiben- ein Array von Oldtimern angelegt hast, kannst Du dieses ganz einfach mit dem Bubblesort - Verfahren nach Motorleistung sortieren:
Code:
Sub sortPS(MeinOldtimer())
   Do
      sortiert% = 1
      For x% = LBound(MeinOldtimer) To UBound(MeinOldtimer) - 1
         If MeinOldtimer(x%).PS > MeinOldtimer(x% + 1).PS Then
            Swap MeinOldtimer(x%), MeinOldtimer(x% + 1)
            sortiert% = 0
         EndIf
      Next
   Loop Until sortiert%
End Sub
Wie Du siehst, brauchst Du immer nur zwei Arrayelemente zu vertauschen und nicht alle enthaltenen Variablen einzeln. Das Ganze lässt sich auch sehr leicht an andere Erfordernisse anpassen, um z.B. nach Farikat zu sortieren, brauchst Du nur die entsprechende Variable zu ändern:
Code:
Sub sortPS(MeinOldtimer())
   Do
      sortiert% = 1
      For x% = LBound(MeinOldtimer) To UBound(MeinOldtimer) - 1
         If MeinOldtimer(x%).Fabrikat > MeinOldtimer(x% + 1).Fabrikat Then
            Swap MeinOldtimer(x%), MeinOldtimer(x% + 1)
            sortiert% = 0
         EndIf
      Next
   Loop Until sortiert%
End Sub


Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu QBasic. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz