Lesen sequentieller Files

Es gibt 61 Antworten in diesem Thema, welches 8.048 mal aufgerufen wurde. Der letzte Beitrag (13. Mai 2023 um 08:22) ist von BIF.

  • Also oft auch nicht, ich krieg manchnmal ?illegal quantity error in 50

    +

    Das liegt gewissermassen an der Zeile 20, zum einen koennte die unvollstaendig sein, zum andern betrifft es den Wert von "H$", eventuell auch L$.

    Ist H$, oder L$ ="", also nichts, dann steigt das Program in Zeile 50 eben mit dem besagten Fehler aus.

    Eine Abhilfe schafft hier, wenn man das Program folgendermassen abaendert:

    Hatten wir schon mit Korrektur in Bitte melde dich an, um diesen Link zu sehen..

    Ehrlich gesagt sind mir diese IF-THEN für den ASCI-Sonderfall zu hässlich, zu lang und zu langsam.

    Die

    Code
    1 Z$=CHR$(0)
    ...
    1234 GET#1,A$
    1235 A=ASC(A$+Z$)

    Wegen dem String-Müll, der dabei entsteht und der Garbage-Collection braucht man sich da keine Sorgen machen (solange weniger als 100 aktive Strings im Programm auftreten). Falls man wirklich mit vielen Strings hantiert, sollte man sowieso auf einen flotten Bitte melde dich an, um diesen Link zu sehen. einsetzen.

  • 1234 GETBitte melde dich an, um diesen Link zu sehen.,A$
    1235 A=ASC(A$+Z$)

    Oder den BIF-Trick verwenden: get#1,a$:a=peek(512). Funktioniert bestens und ohne viel String-Müll zu erzeugen!

    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Hab ja das @ weggelassen... :whistling:

    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Hatten wir schon mit Korrektur in Bitte melde dich an, um diesen Link zu sehen..

    Ehrlich gesagt sind mir diese IF-THEN für den ASCI-Sonderfall zu hässlich, zu lang und zu langsam.

    Die

    Code
    1 Z$=CHR$(0)
    ...
    1234 GET#1,A$
    1235 A=ASC(A$+Z$)

    ...

    Hatte ich, wie schon so oft, dezent ueberlesen.;)

    MfG

    Claus

    "Wer einen Fehler begangen hat und ihn nicht korrigiert, begeht einen weiteren Fehler."

    (aus den Lehren des Konfuzius)

    Mein GitHub: Bitte melde dich an, um diesen Link zu sehen.

  • Oder den BIF-Trick verwenden: get#1,a$:a=peek(512). Funktioniert bestens und ohne viel String-Müll zu erzeugen!

    Arndt

    Das gefälllt mir prinzipiell.

    Leider ist es dann nicht mehr portabel - oder ist Speicherstelle 512 bei allen CBM-Achtbittern gleich verwerndet?

  • Leider ist es dann nicht mehr portabel - oder ist Speicherstelle 512 bei allen CBM-Achtbittern gleich verwerndet?

    Bin mir auch nicht 100%ig sicher, aber das ist der Eingabepuffer bei $0200 und der ist durch alle System ziemlich fix. Also bei C128 BASIC 7, Plus4 BASIC 3.5, PET, VC20 hab ich's getestet. CBM-II-Linie (noch) nicht.

  • Oder den BIF-Trick verwenden: getBitte melde dich an, um diesen Link zu sehen.,a$:a=peek(512). Funktioniert bestens und ohne viel String-Müll zu erzeugen!

    Das ist übrigens ein Fehlschluss, denn damit wird der Stringmüll trotzdem erzeugt. Der String wird ja durch GET immer angelegt (also wenn ein Zeichen gedrückt ist).

    Das ASC(A$+Z$) produziert allerdings nicht mehr Müll, da zu der zusammengehängte String temporär erzeugt wird (2 Zeichen) und auch gleich wieder vom String-Heap "entfernt" wird (im Zuge des Aufräumens am String-Stack für die Ausdrucksauswertung für das Argument von ASC().

    Anders allerdings bei ASC(A$+CHR$(0)) - da werden immer 2 Bytes pro Aufruf am String-Heap gelegt. ;)

    D.h. die an sich system-abhängige peek()-Variante ist (wenn man von einem Geschwindigkeitsaspekt absieht) um nichts besser als die ASC(A$+Z$)-Variante und würde ich eher vermeiden, wenn nicht wirklich einen zwingender Grund gibt.

  • Das ist übrigens ein Fehlschluss, denn damit wird der Stringmüll trotzdem erzeugt.

    Mein Einwurf lautete: "und ohne viel Stringmüll". Für mich zählt außerdem, dass der Test auf CHR$(0) entfällt.

    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Mein Einwurf lautete: "und ohne viel Stringmüll". Für mich zählt außerdem, dass der Test auf CHR$(0) entfällt.

    Vielleicht hab ich mich missverständiglich ausgedrückt:

    1. Beide Varianten liefern erzeugen gleich viel String-Müll - damit ist "ohne viel String-Müll" aus dem Speil.

    2. Beide Varianten brauchen keinen expliziten Test auf CHR$(0)

    Was bleibt: die Maschinenabhängigkeit mit PEEK(512) - auf einem CBM-II (mit BASIC 4+) geht es dann z.B. nämlich nicht, denn da liegt der Input-Puffer woanders. ;) Ich persönlich bevorzuge immer die portablere Variante.

  • Das verstehe ich jetzt nicht. get#1,a$:a=asc(a$+z$) verbraucht in meinen Augen drei Bytes: eins bei GET und zwei weitere bei Plus. Bei PEEK wird nur eins benötigt, das bei GET. Liege ich da denn falsch?


    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Das verstehe ich jetzt nicht. getBitte melde dich an, um diesen Link zu sehen.,a$:a=asc(a$+z$) verbraucht in meinen Augen drei Bytes: eins bei GET und zwei weitere bei Plus. Bei PEEK wird nur eins benötigt, das bei GET. Liege ich da denn falsch?

    Sind meine Erklärung wirklich so schwer zu verstehen oder werden die einfach nur immer überlesen ... ?

    Ich schrieb:

    Das ASC(A$+Z$) produziert allerdings nicht mehr Müll, da zu der zusammengehängte String temporär erzeugt wird (2 Zeichen) und auch gleich wieder vom String-Heap "entfernt" wird (im Zuge des Aufräumens am String-Stack für die Ausdrucksauswertung für das Argument von ASC().

    Anders allerdings bei ASC(A$+CHR$(0)) - da werden immer 2 Bytes pro Aufruf am String-Heap gelegt. ;)

    Da z$ fix am Heap ist, wird durch GET immer nur der Inhalt von A$ neu angelegt und das Ergebnis der String-Concatenation als temporärer String sofort (nicht erst bei der GC) wieder verworfen (die String-Verwaltung ist nicht so verschwenderisch wie manche glauben). Deswegen kommt hier immer nur ein Byte am Heap dazu - wegen dem GET, und das in beiden Fällen.

  • Etwas ist schräg in VICE.

    Wir haben also folgendes Programm:

    Nun hänge ich eine .d64 Disk Image ein mit, Inhalt ein Prog mit 17 Blocks, damit 647 Blocks free.

    True Drive Emulation ON

    Virtual Device Traps OFF

    - Starte obiges Progrämmchen --->> BLOCKS FREE: 647

    - load"*",8

    - new

    - Starte obiges Progrämmchen nochmals --->> BLOCKS FREE: 647

    Alles gut also. Dann ändere ich mal:

    True Drive Emulation OFF

    Virtual Device Traps ON

    - Starte obiges Progrämmchen --->> BLOCKS FREE: 647

    - load"*",8

    - new

    - Starte obiges Progrämmchen nochmals --->> BLOCKS FREE: 17

    WTF?

  • Da z$ fix am Heap ist, wird durch GET immer nur der Inhalt von A$ neu angelegt und das Ergebnis der String-Concatenation als temporärer String sofort (nicht erst bei der GC) wieder verworfen

    Ah, die Info hat mir gefehlt (und nie ausprobiert)! Danke!

    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Warum "WTF"? Das eine ist halt eine komplette 1541-Emulation, die wie gewünscht auf die Directory-Pattern-Trickserei manipuliert und das andere ist das VDrive, das ähnlich wie sd2iec ein virtuelles Laufwerk mit komplett neu implementiertem DOS ist und daher nicht auf alle Frickeltricks genauso reagiert wie eine 1541.

    10 x=rnd(-1963):fori=1to81:y=rnd(1):next
    20 forj=1to5:printchr$(rnd(1)*16+70);:next
    30 printint(rnd(1)*328)-217

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Ich finds einfach interessant, dass die Anzahl ja stimmt beim 1. Aufruf.

    Nachdem Laden einer Datei wird immer die Anzahl Blöcke ebendieser Datei ausgegeben.

    Selbst wenn ich das Image auswerfe, Hard Reset mache und Image wieder einhänge.

    Es bleibt sogar so, wenn ich das Image wechsle und danach erneut lade.

  • Wenn man ganz auf Strings bei GET verzichten will kann man die GET-Routine auch mit SYS aufrufen und dann mit peek(780) den ASCII-Code auslesen.
    Noch raffinierter ist es natürlich, wenn man zusätzlich den Stringpointer z.B. von A$ auf 780 zeigen läßt.
    Damit kann man dann Speicherstelle 780 als String lesen, ohne Stringanlegen.

    Für die Wandlung von von String nach Num ist peek(512) wohl die kürzeste Lösung, da man natürlich auch n$=chr$(0): berücksichtigen muß.

    Ein weiterer Trick ist es sich den StringgrenzenZeiger zu merken und nach dem GET wieder zurückzusetzen.
    Damit hat man dann die völlige Kontrolle über den String-Bereich und kann temporäre Strings löschen.

    Schönen Gruß.

  • Die Stringverkettung kann übrigens bei knappen Speicher auch eine Garbage-Collection auslösen, da natürlich auch temporäre Strings einen Überlauf auslösen können.
    Das hat man natürlich bei peek(512) nicht.
    Schönen Gruß.

  • Die Stringverkettung kann übrigens bei knappen Speicher auch eine Garbage-Collection auslösen, da natürlich auch temporäre Strings einen Überlauf auslösen können.
    Das hat man natürlich bei peek(512) nicht.
    Schönen Gruß.

    Die PEEK()-Variante hilft ja nichts, weil GETA$ immer einen temporären String anlegt. Die String-Verkettung in dieser Form (CHR$(0) in einer Variable) räumt den temporären String immer vom String-Heap und kann nur dann eine GC auslösen (was nicht schlimm sein muss, siehe unten), wenn der freie Speicher nahezu aufgebraucht ist. Es ist aber dann auch schon egal, ob es das GETA$ oder die Stringverkettung ist. Aber dafür ist die GC ja da und stört auch nicht. Das PEEK() ändert jedoch nichts daran, dass prinzipbedingt das GETA$ laufend (sofern ein Zeichen eingegeben wird) den String-Heap füllt.


    Aber die GC ist nicht (immer) das Horrorgespenst als das es von manchen immer dargestellt wird. In diesem Fall ist es völlig harmlos und kostet keine nennenswerte Zeit. Wir haben hier konkret nur einen String. Da muss es schon eine signifikant höhere Anzahl von belegten Strings geben, um überhaupt über das nachdenken zu müssen.

  • Wie oft die GBC ausgelöst wird kommt wohl auf die Programmlänge und die Anzahl der Strings an.
    Peek(512) dient hauptsächlich zur Umwandlung des Eingabe-Strings nach Numerisch.
    Man kann damit mit einem Befehl den String in eine Zahl wandeln, wobei auch das Nullbyte richtig gewandelt wird. ASC() ergibt übrigens bei einem Nullbyte=Leerstring eine Fehlermeldung.
    Z.B. um die Return-Taste abzufragen.
    geta$:c=peek(512):if c=13 goto ...
    :if peek(512)=13 goto ...
    :if peek(512)=0 goto ...


    Schönen Gruß.