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:

Probleme bei Konvertierung von QB4.5 zu FB
Gehe zu Seite 1, 2, 3, 4  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 20.11.2013, 01:54    Titel: Probleme bei Konvertierung von QB4.5 zu FB Antworten mit Zitat

Hallo, und erstmal ein kurzes "Vorwort":
Ich habe von Informatik wenig Ahnung, habe aber immer Spaß daran gehabt, zu irgendeinem Problem oder eine Aufgabe einfache (!) Programme zu schreiben. Die meisten davon sind über viele Jahre in QuickBasic 4.5 entstanden, da mir das immer "gereicht" hat.
Manche davon, die zum Teil noch aus Mitte der 90'er Jahre stammen (und in bescheidenem Umfang "weiterentwickelt" wurde), benutze ich noch heute.
Unter anderem ein Adressprogramm, und eine Art Kontenprogramm.
Alles Dinge, die man auch anderweitig über Exel bzw. mit zahlreichen "Fertigprogrammen" lösen könnte, aber ich würde dennoch gerne meine eigenen Tools weiter nutzen.
Spätestens mit Umstellung auf ein 64-Bit Betriebssystem sind die von QB erzeugten 16-Bit-Exe-Dateien wohl nicht mehr lauffähig.
Daher habe ich mir Freebasic angesehen, und versuche gerade das erste Programm zu konvertieren.

Noch zwei Punkte:
- Ich habe natürlich schon nach Ursachen und Lösungen gesucht, bin aber noch nicht recht schlau geworden. Wenn das Thema hier schon behandelt wurde, bitte ich um Nachsicht.
- Ebenso bitte ich um Verständnis, wenn ich nicht immer die richtigen Fachausdrücke gebrauche, ich hoffe es kommt dennoch rüber was ich meine zwinkern

Nun zu meinem aktuellen (Haupt-)Problem dabei:
Das Kontenprogramm arbeite mit Daten in Feldern, und speichert diese in eine Datei. Je Eintrag gibt es folgende Elemente:
- Datum
- Summe
- Kategorie
- Bemerkung
Die programminterne Verarbeitung dieser Daten habe ich damals so gemacht, dass jedes Element (auch die Zahlenwerte) als String fester Länge gespeichert wird. Jeder Eintrag wird dann als String der Länge 68 mit PUT und GET in die Datei geschrieben / gelesen.
Die Zahlenwerte im Fall "BETRAG" (eine Double-Zahl) habe ich mit MKD$ in einen String der Länge 8 umgewandelt. Beim Schreiben der Datei nimmt er die Bytes 5-12 in dem 68-Byte-langem Eintrag ein.

Das Problem bei Freebasic scheint mir nun zu sein, dass der Umgang mit Strings fester Länge anders ist, und insbesondere kein Wert 0 innerhalb des Strings vorkommen darf. Beim Schreiben in die Datei speichert mit FB also für die Summe keine 8 Bytes, sondern je nach Inhalt "irgendwas" kürzeres.
Damit passt natürlich gar nichts mehr...

Ich habe hier mal versucht, entscheidende Teile des Programms zusammen zu fassen:

TYPE KONTTYPE
Dat AS STRING * 4
sum AS STRING * 8
Ad AS STRING * 4
Bem AS STRING * 52
END TYPE

DIM SHARED Kont(1000) AS KONTTYPE

...

'Eingabe und Interne Speicherung als String*8
Input "Betrag:"; B#
Kont(i).sum = MKD$(B#)

...
'Speicherung der Einträge:
Dim T As String*68
OPEN "R", #1, D$, 68
...

T = Kont(i).Dat + Kont(i).sum + Kont(i).Ad + Kont(i).Bem
PUT #1, i + 1, T
...


Wenn ihr Auszüge aus dem Programmcode braucht, reiche ich diese natürlich gerne nach, ich wollte meinen Post nur nicht länger machen als er eh schon ist.

Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 20.11.2013, 12:56    Titel: Re: Probleme bei Konvertierung von QB4.5 zu FB Antworten mit Zitat

Hallo und willkommen im Forum!
TimesChange hat Folgendes geschrieben:
Spätestens mit Umstellung auf ein 64-Bit Betriebssystem sind die von QB erzeugten 16-Bit-Exe-Dateien wohl nicht mehr lauffähig.

Genau richtig. Nur mit Emulatoren wie DOSBOX kann man dort noch die alten DOS-Programme ausführen. Das ist aber deutlich weniger komfortabel.
TimesChange hat Folgendes geschrieben:
Daher habe ich mir Freebasic angesehen

Für solche "Upgrade-Projekte" von QB/DOS zu Windows/Linux ist FreeBASIC genau das Passende.

TimesChange hat Folgendes geschrieben:
Nun zu meinem aktuellen (Haupt-)Problem dabei:
Das Kontenprogramm arbeite mit Daten in Feldern, und speichert diese in eine Datei. Je Eintrag gibt es folgende Elemente:
- Datum
- Summe
- Kategorie
- Bemerkung
Die programminterne Verarbeitung dieser Daten habe ich damals so gemacht, dass jedes Element (auch die Zahlenwerte) als String fester Länge gespeichert wird. Jeder Eintrag wird dann als String der Länge 68 mit PUT und GET in die Datei geschrieben / gelesen.
Die Zahlenwerte im Fall "BETRAG" (eine Double-Zahl) habe ich mit MKD$ in einen String der Länge 8 umgewandelt. Beim Schreiben der Datei nimmt er die Bytes 5-12 in dem 68-Byte-langem Eintrag ein.

In FreeBASIC können elementare Nicht-String-Datentypen wie Integer, Double, ... sowohl im sequentiellen als auch im binären Dateimodus direkt geschrieben und gelesen werden. Ein Umweg über Strings ist komplett überflüssig. (Ich glaube mich zu erinnern, dass das aber auch in QB schon so war?)

Mit folgendem Code schreibst du die Binärdaten einer DOUBLE-Variable in eine Datei:
Code:
Dim d As Double = 42.123
Dim f As Integer = FreeFile
Open "MeineDatei.dat" For Binary As #f
Put #f, , d
Close #f

Die Datei wird, falls sie noch nicht existiert, angelegt und wird nach Ausführung des Programms genau 8 Bytes lang sein, also die Daten der Double-Variable enthalten. Also das, was du früher mit MKD herausbekommen hast.

Möchtest du den menschen-lesbaren Inhalt der Variable speichern, sähe es so aus:
Code:
Dim d As Double = 42.123
Dim f As Integer = FreeFile
Open "MeineDatei.dat" For Output As #f
Print #f, d
Close #f

Diese Datei kann man einfach direkt im Editor öffnen und den Zahlwert ablesen. Das ist für deinen Anwendungszweck jetzt nicht zu brauchen, von daher das nur so informationshalber.
Ich glaube von deinem Posting her, du kennst dich aber gar nicht mal übel aus und kennst das von daher wahrscheinlich schon. zwinkern

Ein Problem beim Übertragen der alten Dateien hin zum neuen Programm könnte sein, dass QB nicht nur mit den heute üblichen IEEE 754 Gleitkommazahlen arbeiten konnte, sondern auch ein Microsoft-eigenes Format hatte, das verwendet werden konnte (u. a. durch Angabe eines Kommandozeilenschalters). Dieses alte Format ist zum heute gebräuchlichen Format nicht kompatibel. Zum Beispiel 8 Bytes sind die Doubles in beiden Fällen lang, aber die Struktur intern unterscheidet sich.

Aber ganz unabhängig vom Lesen/Schreiben der Daten: Wenn man als Entwickler in Zusammenhang mit einer kaufmännischen Kontenanwendung von Gleitkommazahlen wie DOUBLE liest, zuckt man schon ein bisschen zusammen. lächeln
Das liegt daran, dass bei Gleitkommazahlen unvermeidlich Ungenauigkeiten auftreten, die sich bei Verrechnungen "aufschaukeln" können, bis sie tatsächlich auf der Cent-Stelle ins Gewicht fallen.

Mit Gleitkommazahlen kann man riesengroße, aber auch winzig kleine Zahlen darstellen, ohne dass mehr Platz verbraucht wird als für eine einfache Ganzzahlvariable (32/64 Bit). Das geht zulasten der Präzision und Verlässlichkeit. Problematisch ist, dass Werte wie 0.1, die uns im Dezimalsystem völlig simpel und harmlos vorkommen, im Binärsystem der Gleitkommazahlen unendlich periodisch sind. Also alles andere als glatt. Es wird bei der Verrechnung also ständig gerundet.
Von daher muss man immer, wenn es um exakte und nicht nur näherungsweise genaue Werte geht (Geldbeträge, Steuersätze, ...), auf Gleitkommazahlen verzichten. Stattdessen sollte man entweder mit Ganzzahl-Datentypen wie LONG arbeiten oder auf Festkommazahlen zurückgreifen, sofern verfügbar. Viele Sprachen und/oder Bibliotheken bieten dafür entweder spezielle Klassen an (z. B. BigDecimal in Java) oder einen Datentypen wie CURRENCY in QBX/PDS. Diese Festkommazahlen sind nicht beliebig klein oder groß, sondern sie haben genau n Nachkommastellen (teilweise kann man sich diese Anzahl n aussuchen). Nicht mehr und nicht weniger. Dadurch muss z. B. bei Additionen niemals gerundet werden.
Die andere Möglichkeit, die für FreeBASIC naheliegend wäre, ist die erste. Klingt im ersten Moment widersinnig, weil man ja nicht nur gerade Geldbeträge wie 100,- EUR hat, sondern auch mal 123,56 EUR. Der Trick ist, nicht mit Euro-Dezimalbrüchen zu arbeiten, sondern mit ganzen Centbeträgen. Das heißt, 123.56 EUR wären einfach 12345 Cents. Das ist ein simpler Short, Integer oder Long (siehe Befehlsreferenz für diese Ganzzahltypen). Keine Kommas, keine Rundung. Wenn man dann die Geldbeträge auf dem Bildschirm oder auf Papier ausgibt, teilt man nur für die Darstellung/Anzeige durch 100 und erhält einen Betrag mit Euro und Cents. Die Berechnungen und die Datenhaltung erfolgt aber un-gerundet und mit Ganzzahlpräzision in Centbeträgen. Oder man könnte auch Zehntelcents als Recheneinheit (im Beispiel 123560 statt 123,56 EUR) verwenden, wenn man z. B. präzise mit Benzinpreisen arbeiten möchte. Dann teilt man bei der Ausgabe der Infos eben durch 1000.
Eine weitere Möglichkeit wäre, sich in FreeBASIC eine eigene BigDecimal- oder Money-Klasse zu schreiben, die solche Dinge vorm Benutzer kapselt. Aber das wäre schon etwas komplexer.

TimesChange hat Folgendes geschrieben:

Code:
TYPE KONTTYPE
   Dat AS STRING * 4
   sum AS STRING * 8
   Ad AS STRING * 4
   Bem AS STRING * 52
END TYPE


Wenn du TYPE-basierte Datensätze direkt in einem Stück binär PUTtest und GETtest, gibt es ein kleines Kompatibilitätsproblem zwischen QB und FreeBASIC. FreeBASIC hängt an String-Member solcher Verbund-Datentypen ein abschließendes Nullbyte an. Das gab es in QB nicht. Das heißt, zum Beispiel dieser TYPE hier
Code:
TYPE PersonenName
  Vorname As String * 10
  Nachname As String * 10
END TYPE

wäre in der Datei nicht 20 Bytes lang, sondern 22 Bytes. Ich find das auch nicht so sinnvoll, aber das hat man wohl gemacht, damit man auch solche Strings automatisch speichern kann, die keine feste Länge wie im Beispiel 10 haben. Durch das abschließende Nullbyte weiß die Laufzeitbibliothek, wo Schluss ist mit dem einen String-Member des UDT (z. B. Ad) und wo der nächste (z. B. Bem) anfängt.

Es gibt aber eine Möglichkeit, das zu umgehen, wenngleich sie nicht ganz so komfortabel ist. Vergleich dazu mal mit einem HexEditor die beiden Dateien, die das folgende Programm erstellt:
Code:
Declare Function FuellMitNullBytes (x As String, sollLaenge As Integer) As String

TYPE tPerson
  Vorname As String * 8
  Nachname As String * 8
END TYPE

Dim test As tPerson

test.Vorname = "Sandy-Gunilla"
test.Nachname = "Quakenberg"

'Datei ueberschreiben/loeschen (falls noch uebrig vom letzten Ausfuehren):
Open "Ausgabe1.dat" For Output As #1
Close #1

'Neuen Inhalt in die jetzt leere Datei schreiben:
Open "Ausgabe1.dat" For Binary As #1
Put #1, , test
Close #1

' ------ Datei 2 -------

'Datei ueberschreiben/loeschen (falls noch uebrig vom letzten Ausfuehren):
Open "Ausgabe2.dat" For Output As #1
Close #1

Dim As String v, n
v = FuellMitNullBytes(test.Vorname, 8)
n = FuellMitNullBytes(test.Nachname, 8)
Open "Ausgabe2.dat" For Binary As #1
Put #1, , v
Put #1, , n
Close #1

Print "Fertig."
Sleep: End


Function FuellMitNullBytes (x As String, sollLaenge As Integer) As String
  Dim xLen As Integer = Len(x)
  If (xLen > sollLaenge) Then
    Return Left(x, sollLaenge)
  ElseIf (xLen = sollLaenge) Then
    Return x
  Else
    Return (x + String(sollLaenge-xLen, 0))
  End If
End Function


Die eine Datei wird statt 16 Bytes 18 lang werden und die andere hingegen genau 16. Im zweiten Fall wird nicht der komplette Verbund-Datentyp mitsamt Abschnittsmarkierungen in einem Rutsch gespeichert, sondern jedes Datum einzeln.

Viele Grüße!
Sebastian
_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 20.11.2013, 15:32    Titel: Antworten mit Zitat

Hallo Sebastian,

herzlichen Dank für deine ausführliche Antwort.
Ich muss mir das erst in Ruhe zu Gemüte führen und ausprobieren.
Vielleicht schaffe ich es noch heute Abend, ansonsten bin ich erstmal einige Tage unterwegs und melde mich danach wieder.

Mit den "Gleitkommazahlen und Buchhaltung" hast du absolut recht, ich weiß auch nicht warum ich das nicht gleich z.B. auf Cent-Basis (bzw. damals Pfennige...) mit Ganzzahlen gemacht habe...
Das wäre evtl. ein weiterer Schritt, aber zuerst mal muss ich das Programm lauffähig bekommen, und wenn's geht kompatibel mit dem bisherigen Dateiformat.
Bis dahin ist eh noch einiges zu tun zwinkern

Ich vermisse den Debug-Modus, den ich in Quickbasic hatte. Ist für die Fehlersuche schon sehr komfortabel, wenn man das Programm schrittweise ausführen, Variablenwerte anzeigen lassen kann etc.

Ich melde mich wieder
Viele Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 20.11.2013, 18:17    Titel: Antworten mit Zitat

TimesChange hat Folgendes geschrieben:
Ich vermisse den Debug-Modus, den ich in Quickbasic hatte. Ist für die Fehlersuche schon sehr komfortabel, wenn man das Programm schrittweise ausführen, Variablenwerte anzeigen lassen kann etc.

Ja, das stimmt. Das war echt praktisch. In FreeBASIC hat man die Situation, dass der Compiler ausschließlich Maschinencode bzw. mittelbar ausführbare Binaries erzeugen kann. Es gibt leider gar keinen Interpreter, dem man zur Ausführungszeit in die Karten gucken oder in die Variablen hineinreden könnte. Von daher bleibt einem nur klassisches Debugging wie z. B. in C. Es können z. B. gdb oder FBDebugger verwendet werden. Die sind aber schon viel umständlicher als früher in QB. verwundert
_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 21.11.2013, 00:00    Titel: Antworten mit Zitat

Hallo TimesChange
Hallo Sebastian

Wenn ich mal meine Senf zum Thema Debugging dazugeben dürfte:
Hier war QBasic wirklich deutlich komfortabler. Es gibt in FB mit dem Compilerparameter -g einen besonderen Debug-Modus, mit dem man z.B. mit FbEdit dem Programm beim Arbeiten zusehen und auch Haltepunkte einfügen kann, aber davon bin ich inzwischen abgekommen, weil mir das zu umständlich ist. Meistens weiß man ja so ungefähr, wo es "hakt", da ist es dann praktischer, an einer strategisch günstigen Stelle vorübergehend einen "Print"-Befehl einzubauen und das Programm anzuhalten.
Code:
...
   End Select
               
         move = GetMove(opponent) 'read the "bestmove" from the engine
         lastmove = move
         
         ? move
         Sleep
         
         'check if the response is a correct move
         Do
            For x = 1 To UBound(matesign)
...
Ich empfehle hierfür die Verwendung des Fragezeichens statt eines "Print", das erleichtert später das Wiederfinden zum Auskommentieren bzw. Löschen.

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 E-Mail senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 21.11.2013, 01:12    Titel: Antworten mit Zitat

Ja, mit Print und Sleep behelfe ich mir auch...
aber da kommt einiges an "prints" zusammen zwinkern

Guter Tipp mit dem "?", wusste ich nicht mehr, erinnert mich aber entfernt an C64 oder zumindest "Normal-Basic"-Zeiten...


Inzwischen habe ich festgestellt, dass mein Problem nicht beim PUT-Befehl,
sondern schon in der Zeile davor auftritt:

Code:
T = Kont(i).Dat + Kont(i).sum + Kont(i).Ad + Kont(i).Bem


Obwohl die Typen .Dat, .sum etc. alle als Strings fester Länge definiert sind, und mir z.B.
Code:
LEN(KOnt(i).sum)
auch 8 ausgibt, gehen beim Anhängen der einzelnen String Bytes "verloren".

Wenn ich die Strings statt in die als STRING*68 definierte Variabel "T" in einen String variabler Länge T$ kopieren, so wie hier:
Code:
T$ = Kont(i).Dat + Kont(i).sum + Kont(i).Ad + Kont(i).Bem

dann wird für T$ abhängig von den Inhalten der einzelnen Elemente z.B. nur eine Länge von 17 statt 68 (wäre Summe der "LEN"s) ausgegeben.

Sebastian hat Folgendes geschrieben:
Wenn du TYPE-basierte Datensätze direkt in einem Stück binär PUTtest und GETtest, gibt es ein kleines Kompatibilitätsproblem zwischen QB und FreeBASIC. FreeBASIC hängt an String-Member solcher Verbund-Datentypen ein abschließendes Nullbyte an.


Korrigier mich bitte, wenn ich falsch liege, aber das Problem scheint mir nicht beim PUT und GET zu liegen, sondern in der String-Operation zuvor.

Ich habe mir vorläufig so beholfen, dass ich die einzelnen Elemente nicht in T schreibe und dann als Random-Satz schreibe, sondern wie von Sebastion vorgeschlagen, die Datei als BINARY öffne, und die einzelnen Elemente nacheinander PUTte:

Code:
  Put #1,, Kont(i).Dat
  Put #1,, Kont(i).Sum
  Put #1,, Kont(i).ad
  Put #1,, Kont(i).bem


Spricht doch nichts dagegen, oder?

Jetzt kann ich halt nicht mehr gezielt einen bestimmten geänderten Datensatz an Position x schreiben, sondern muss der Reihe nach alle Datensätze neu in die Datei schreiben.
Nö, Stimmst so gar nicht: Ich muss nur die Position in Bytes umrechnen, statt in Datensatz-Nr.


Beim Einlesen als RANDOM mit GET gibt es keine Probleme.

Immerhin kann ich jetzt die mit QB4.5 erzeugten Dateien korrekt einlesen, und umgekehrt.

So, jetzt fängt die Arbeit erst richtig an... ich hoffe ich darf euch wieder fragen.

Noch eine Frage am Rande: Woran liegt es, dass die mittels FB erzeugte EXE gut doppelt so groß ist, wie die EXE von QQB4.5?
(ich compiliere in QB mit folgenden Schaltern, falls es daran liegt:
BC %1/AH/O/E/X/T;
LINK /EX /NOE %1+NOCOM.OBJ+NOEM.OBJ+SMALLERR.OBJ+QB.LIB,%1.EXE,NUL;

Viele Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 21.11.2013, 02:12    Titel: Antworten mit Zitat

TimesChange hat Folgendes geschrieben:
Obwohl die Typen .Dat, .sum etc. alle als Strings fester Länge definiert sind, und mir z.B.
Code:
LEN(KOnt(i).sum)
auch 8 ausgibt, gehen beim Anhängen der einzelnen String Bytes "verloren".

Wenn ich die Strings statt in die als STRING*68 definierte Variabel "T" in einen String variabler Länge T$ kopieren, so wie hier:
Code:
T$ = Kont(i).Dat + Kont(i).sum + Kont(i).Ad + Kont(i).Bem

dann wird für T$ abhängig von den Inhalten der einzelnen Elemente z.B. nur eine Länge von 17 statt 68 (wäre Summe der "LEN"s) ausgegeben.

Bei der Verkettung lässt er wohl die Nullbytes einfach wegfallen. Früher musste man noch mit TRIM$(...) die Whitespaces entfernen.

Hier mal ein kleines Testprogramm zum Thema:
Code:
type tPerson
    Land As String * 3
    Alter As String * 4
    Vorname As String * 8
end type

dim p as tperson
p.Land = "DE"
p.Alter = MKI(420)
p.Vorname = "Gunilla"

dim x as string

print "Len(MKI(...)) = " & len(p.Alter)

x = p.Land + p.Alter + p.Vorname

Print "Len(Komplett) = " & Len(x)

for i As Integer = 1 to len(x)
    Print asc(mid(x, i, 1)); "  ";
next i
print ""

sleep
end

Es zeigt, wie die Nullbytes am Rand der Teilstrings bei der Verkettung verlorengehen.

TimesChange hat Folgendes geschrieben:
Jetzt kann ich halt nicht mehr gezielt einen bestimmten geänderten Datensatz an Position x schreiben, sondern muss der Reihe nach alle Datensätze neu in die Datei schreiben.
Nö, Stimmst so gar nicht: Ich muss nur die Position in Bytes umrechnen, statt in Datensatz-Nr.

Wenn du weißt, dass die Bestandteile eines Satzes zusammen z. B. 68 Bytes lang sind und du 10 Sätze beim Lesen/Schreiben überspringen willst, kannst du ja einfach ausrechnen, wo die richtige Position in der Datei ist. Du kannst entweder mit SEEK dahin springen oder die Position explizit bei GET/PUT zwischen den beiden Kommas angeben.

TimesChange hat Folgendes geschrieben:
Noch eine Frage am Rande: Woran liegt es, dass die mittels FB erzeugte EXE gut doppelt so groß ist, wie die EXE von QQB4.5?
(ich compiliere in QB mit folgenden Schaltern, falls es daran liegt:
BC %1/AH/O/E/X/T;
LINK /EX /NOE %1+NOCOM.OBJ+NOEM.OBJ+SMALLERR.OBJ+QB.LIB,%1.EXE,NUL;

QB erzeugt 16-Bit-EXE-Dateien für DOS. FreeBASIC erzeugt 32-Bit-Binärprogramme, zum Beispiel für Windows. Was da erzeugt wird, hat zwar unter Windows beides die Endung EXE, aber technisch sind das wirklich 2 Paar Schuh.

Zu den technischen Details der Dateiformate siehe zum Beispiel:
http://wiki.osdev.org/MZ
http://wiki.osdev.org/PE

Viele Grüße!
Sebastian
_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4597
Wohnort: ~/

BeitragVerfasst am: 21.11.2013, 16:29    Titel: Antworten mit Zitat

Sebastian hat Folgendes geschrieben:
TimesChange hat Folgendes geschrieben:
Jetzt kann ich halt nicht mehr gezielt einen bestimmten geänderten Datensatz an Position x schreiben, sondern muss der Reihe nach alle Datensätze neu in die Datei schreiben.
Nö, Stimmst so gar nicht: Ich muss nur die Position in Bytes umrechnen, statt in Datensatz-Nr.


Wenn du weißt, dass die Bestandteile eines Satzes zusammen z. B. 68 Bytes lang sind und du 10 Sätze beim Lesen/Schreiben überspringen willst, kannst du ja einfach ausrechnen, wo die richtige Position in der Datei ist. Du kannst entweder mit SEEK dahin springen oder die Position explizit bei GET/PUT zwischen den beiden Kommas angeben.

Wenn der Datentyp nur aus Zahlen und Strings fester Länge besteht, kannst du sogar den kompletten Datensatz auf einmal abspeichern und auslesen (Achtung: geht nicht mit Strings variabler Länge oder Pointern) und die Position mithilfe von SIZEOF(datentyp) berechnen.
Code:
type tPerson
    Land As String * 3
    Alter As String * 4
    Vorname As String * 8
end type
dim as tPerson daten(1)

daten(0).Land    = "DE"
daten(0).Alter   = "55"
daten(0).Vorname = "Adam"

daten(1).Land    = "GB"
daten(1).Alter   = "44"
daten(1).Vorname = "Eva"

dim as integer f = freefile
open "daten.dat" for binary as #f
print "Schreibe an Stelle"; seek(f); ", Datenlaenge"; sizeof(tPerson)
put #f,, daten(0)
print "Schreibe an Stelle"; seek(f); ", Datenlaenge"; sizeof(tPerson)
put #f,, daten(1)
close #f
sleep

(Sieht ja fast schon ein bisschen so wie mit RANDOM aus. grinsen)
Geschrieben wird ab Position 1, d. h. deine Datensätze liegen wegen SIZEOF(tPerson) = 18 immer an den Stellen (datensatznr*18 + 1). Wenn du parallel mit FB und QB arbeitest, musst du allerdings schauen, ob die Länge des Datensatzes beide Male gleich ist.


Ach ja, noch schnell ein Einleseprogramm (die Nummerierung der Datensätze beginnt wieder bei 0)
Code:
type tPerson
    Land As String * 3
    Alter As String * 4
    Vorname As String * 8
end type
dim as tPerson daten

dim as integer f = freefile
open "daten.dat" for binary as #f
get #f, 1*sizeof(tPerson)+1, daten   ' Eva einlesen
close #f

_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 21.11.2013, 16:49    Titel: Unterschiedliche UDT-Speicherlängen in QB / FB wg. Nullbytes Antworten mit Zitat

Hallo!
nemored hat Folgendes geschrieben:
kannst du sogar den kompletten Datensatz auf einmal abspeichern und auslesen [...]
Code:
[...]
dim as tPerson daten(1)
[...]

put #f,, daten(0)

[...]

Da kommt dann leider ein Problem zum Tragen bzgl. der Kompatibilität zu alten QB-Anwendungen. Siehe letztes Code-Beispiel in diesem Posting. In QB gab es die Nullbytes nach den String-UDT-Members nicht. Beim Schreiben der UDT-Variable in einem Stück würde aus 3 String-Members zu je 8 Bytes keine Datei mit 24 Bytes, sondern 27.



In QB hingegen wären es nur 24. Zum Vergleich:



nemored hat Folgendes geschrieben:
Wenn du parallel mit FB und QB arbeitest, musst du allerdings schauen, ob die Länge des Datensatzes beide Male gleich ist.

Ja, genau das ist das Problem. Die UDT-Variablen-Binärspeicherung ist zwischen QB und FB nicht kompatibel durch diese Nullbytes.
_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4597
Wohnort: ~/

BeitragVerfasst am: 21.11.2013, 16:55    Titel: Antworten mit Zitat

Ich hätte ja gedacht, wenn FreeBASIC bei Festlängenstrings innerhalb von UDTs ein Nullbyte anhängt, würde es das bei einzelnen Festlängenstrings auch so machen - aber das ist in der Tat nicht so. Also dann doch: Strings einzeln schreiben und lesen und die Datensatzlänge "per Hand" berechnen aus der Summe der Einzellängen. lächeln
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 25.11.2013, 02:49    Titel: Antworten mit Zitat

Ich habe es nun tatsächlich geschafft, das Programm in FB zum Laufen zu bringen, ohne dass ich Fehler bemerken würde zwinkern

Vorerst habe ich mich darauf beschränkt, die Kompatibilität zur alten QB-Version herzustellen, so dass ich nun dieselben Dateien wahlweise mit der FB- oder der QB-Version lesen und schreiben kann.

Bei den nächsten Programmen, die ich auch gerne noch konvertieren würde, sollte das nun deutlich schneller gehen.

Was noch nicht passt, ist die Fehlerbehandlung, die in QB mit
Code:
Resume HAUPT
abschloss, so dass das Programm nach einem Fehler zurück ins Hauptprogramm zur Marke "Haupt" sprang.
Aber das ist erst mal nicht so tragisch.

Ein Frage (vorerst...) habe ich noch:
Es handelt sich um ein Programm in reinem "Text-Modus" (in QB mode 0 - ich denke mit 25 Zeilen und 80 Zeichen /Spalten). Jaja, nicht lachen...
Die von FB generierte Exe öffnet ein gleich großes Fenster in Windows, nur hat dieses am rechten Rand einen Scroll-Balken, mit dem ich in nie benutzte und bedruckte Bereiche meines Ausgabebildschirms scrollen könnte.
Wie bekomme ich diesen Scroll-Balken weg, oder wie kann ich angeben, dass tatsächlich nur ein 25x80-Fenster erzeugt wird?

Viele Grüße
Rainer

P.S. Tolles Forum hier mit vielen guten Infos!!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 25.11.2013, 03:27    Titel: Scroll-Leiste im Windows-Konsolenfenster abschalten Antworten mit Zitat

TimesChange hat Folgendes geschrieben:
Wie bekomme ich diesen Scroll-Balken weg, oder wie kann ich angeben, dass tatsächlich nur ein 25x80-Fenster erzeugt wird?

Das könnte mit Hilfe von WinAPI-Funktionen funktionieren, ähnlich wie hier in C/C++: How to remove scrollbars in console windows C++

Die WinAPI-Aufrufe lassen sich von C/C++ meistens relativ einfach nach FreeBASIC umschreiben.

Alternativ könntest du auch den Grafikmodus benutzen (z. B. SCREEN 12). Der hat grundsätzlich keine Scroll-Leisten, allerdings läuft der auch nicht in der Konsole. Das heißt, bspw. Auswählen und Kopieren von Texten wie in der Konsole sind dann nicht möglich.
_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 25.11.2013, 12:43    Titel: Antworten mit Zitat

TimesCchange hat Folgendes geschrieben:
Wie bekomme ich diesen Scroll-Balken weg, oder wie kann ich angeben, dass tatsächlich nur ein 25x80-Fenster erzeugt wird
Das geht ganz einfach. Geh auf Startmenü > Programme > Zubehör und mach dann einen Rechtsklick auf Eingabeaufforderung. In dem sich öffnenden Menü klicke auf Eigenschaften und gehe auf den Reiter Layout. Dort stellst du die Fensterpuffergröße auf den gleichen Wert wie die Fenstergröße und schon ist der Balken verschwunden.

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 E-Mail senden
Elor



Anmeldungsdatum: 12.07.2013
Beiträge: 205
Wohnort: Konstanz

BeitragVerfasst am: 25.11.2013, 12:59    Titel: Antworten mit Zitat

Hallo!

Vor ein paar Wochen hatte mich das gleiche problem mit dem Scoll-Balken im Konsolenfenster auch gestoehrt,
ich hab dann Width () verwendet. Ich denke mal das das fuer jede Compiler Version und jedes Betriebssystem
Funktionieren muesste.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 25.11.2013, 13:09    Titel: Antworten mit Zitat

Tatsache! Zumindest unter Windows (getestet mit Windows 7) funktioniert es bei einem Konsolenfenster in Standardgröße mit
Code:
' Credit: Elor im Posting drüber ;)
WIDTH 80, 25
PRINT "Hallo Welt"
SLEEP
END

_________________

Der Markt regelt das! | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 25.11.2013, 19:49    Titel: Antworten mit Zitat

Danke für Eure Tipps, das ging ja wieder schnell!

Die Variante mit WIDTH ist eindeutig der Gewinner, einfacher gehts ja nicht mehr lächeln

Kurze Anmerkung noch zum Vorschlag von grindstone:
Da ich nicht generell das Konsolenfenster "beschneiden" wollte, habe ich das selbe nochmal mit dem Programmfenster probiert. Dort kann ich ebenfalls über "Eigenschaften" -> "Layout" die Fenster- und Buffergöße einstellen und für dieses Programm abspeichern. Geht aber nur, wenn das Programm ausgeführt wird, nicht über "Eigenschaften" wenn ich die Datei auf der Festplatte wähle. Darum habe ich diese Möglichkeit selber nicht gefunden.

Viele Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 25.11.2013, 19:55    Titel: Antworten mit Zitat

Und noch eine Frage:

Über z.B. GETKEY kann ich auch das Anklicken des "Windows-Close-Kreuzes" mit der Maus abfragen, und das Programm beenden.
Wenn ich aber das Programm nicht sofort beenden will, sondern z.B. noch eine Benutzereingabe zur Datenspeicherung erforderlich ist, kann ich den Mausklick auf Close zwar auswerten und z.B. in eine Sub "Beenden" springen. ich bekomme dann aber nach wenigen Sekunden die Windows-Warnmeldung "Windows kann diese Programm nicht beenden...".
Kann ich verhindern, dass Windows selber versucht, das Programm zu schließen?

Viele Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 26.11.2013, 00:12    Titel: Antworten mit Zitat

TimesChange hat Folgendes geschrieben:
Geht aber nur, wenn das Programm ausgeführt wird, nicht über "Eigenschaften"
Das ist richtig. Das Verfahren, wie ich es beschrieben habe, gilt für alle Konsolenfenster, für die keine individuelle Einstellung vorgenommen wurde und für alle neu angelegten Fenster. Die individuelle Einstellung hat immer Vorrang.

TimesChange hat Folgendes geschrieben:
ich bekomme dann aber nach wenigen Sekunden die Windows-Warnmeldung "Windows kann diese Programm nicht beenden...".
Das dürfte mit hoher Wahrscheinlichkeit an deinem Programm liegen. Vermutlich versuchst du, das Programm zu beenden, während die Sicherung noch läuft. Dagegen protestiert das Betriebssystem dann. Bei einem Klick auf das Kreuz wird nur Chr(255,107) in den Tastaturpuffer geschrieben, alles andere ist Sache des Programmierers.

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 E-Mail senden
TimesChange



Anmeldungsdatum: 20.11.2013
Beiträge: 85

BeitragVerfasst am: 26.11.2013, 01:23    Titel: Antworten mit Zitat

grindstone hat Folgendes geschrieben:
... Vermutlich versuchst du, das Programm zu beenden, während die Sicherung noch läuft. Dagegen protestiert das Betriebssystem dann. Bei einem Klick auf das Kreuz wird nur Chr(255,107) in den Tastaturpuffer geschrieben, alles andere ist Sache des Programmierers.


Nein, nach meinem Verständnis hat das mit meinem Programmcode nichts zu tun.
Windows versucht immer, das (jedes) Programmfenster nach Klick auf "Close-Kreuz" zu beenden. Egal, ob ich selber den Tastaturpuffer auslese (und eine wie auch immer geartete "Beenden-Aktion starte) oder nicht.
Wenn mein gesamtes Programm aus
Code:
Print "Hallo"
Sleep
besteht, will Windows das Programm nach Klick auf Kreuz genau so beenden.

Viele Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 26.11.2013, 01:56    Titel: Antworten mit Zitat

@TimesChange: Nicht, wenn du das Fenster mit ScreenRes erzeugt hast. Dann schreibt Windows nur Chr(255,107) in den Tastaturpuffer. Ob das ein Bug oder ein Feature ist, weiss ich nicht, aber es ist so.

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 E-Mail 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 FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2, 3, 4  Weiter
Seite 1 von 4

 
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