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:

Keyfiles
Gehe zu Seite 1, 2  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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 23.04.2022, 20:36    Titel: Keyfiles Antworten mit Zitat

In der Applikation die wir Anfang der 80er Jahre entwickelten gab es Dateien bei denen man direkt auf einen bestimmten Datensatz zugreifen musste. Das war z.B. der Artikelstammsatzfile aus dem man mit der Artikelnummer oder auch der Kundenstammsatzfile. direkt den Stammsatzrecord eingelesen bzw, gespeichert hat.
Wir hatten damals 2 Zugriffsarten (die zugehörigen Functions haben wir damals von unserer beraterfirma erhalte, wir brauchten sie nur anwenden.).
Wir hatten damals 2 Möglichkeiten für den direkten Zugriff auf Records:
1) IAM=Index Access Method: dazu gaben wir der Funktion nur die Artikelnummer bekannt und erhielten über einen Keyfile den gesuchten Record. Mit welchem Algorithmis die Funktion arbeitete weiß ich nicht mehr.
2) ISAM=Index Sequential Access Method: ich weiß noch, dass der keyfile dafür sortiert war und zwischen Einträgen Lücken hatte indie bei Neuanlage eines Datensatzes die neuen Einträge gemacht wurde. War eine Lücke aufgebraucht wurde der Keyeintrag ans Ende des Keyfiles gestellt und mittesl Pointer zugeordnet. Daher musste man diese Keyfiles auch von Zeit zu Zeit neu erstellen.
Wir hatten damals sowohl für die Erstellung der Keyfiles als auf für die Zugriife auf die Datenfiles über einen Keyfile eigene Funktionen. Damit war der direkte Zugriff auf bestimmte Records für uns sehr einfach zu programmieren.
Gibt es derartige oder ähnliche Hilfsmittel auch für FreeBasic?
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 24.04.2022, 15:27    Titel: Antworten mit Zitat

Für konkrete Vorschläge sind deine Angaben etwas zu vage, aber sicher lässt sich das alles auch in FB programmieren.

Allerdings stammen die von dir beschriebenen Vorgehensweisen aus einer Zeit, als Arbeitsspeicher in Kilobyte, Festplattengrößen in Megabyte und Prozessortakte in Megahertz angegeben wurden, von Multicoreprozessoren ganz zu schweigen. Bei heutigen Geräten fällt das Umkopieren einer 1 oder 2 Megabyte großen Datei kaum noch ins Gewicht, und wenn es sich nicht um riesige Dateien handelt, ist es meistens sinnvoller, zum Bearbeiten die gesamte Datei in den Arbeitsspeicher zu laden und danach wieder zurückzuschreiben.

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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 24.04.2022, 15:35    Titel: Antworten mit Zitat

Ok, ist klar die Zeit und die Technologie hat sich stark verändert!
Mir ist aber jetzt ganz konkret eines nicht klar: ist es heute sinnvoller eine Datei von fast 30.000 Datensätzen sequentiell durchzulesen, um einen bestimmten Datensatz einzulesen und bearbeiten zu können?

Ich hab natürlich schon bemerkt, dass die Verarbeitung auf meinem Rechner sehr schnell ist, ich hab aber auch einen relativ schnell Desktop-PC aber wie sieht das auf einem langsamen Laptop aus?
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



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

BeitragVerfasst am: 24.04.2022, 19:54    Titel: Antworten mit Zitat

Du musst ja nicht sequenziell einlesen - du kannst auch ganze Blöcke einlesen.
Allerdings kiingt mir die Aufgabenstellung so, als ob man da einen Datenbankeinsatz geplant hat. Ein Datenbanksystem kann man mit FreeBASIC auf jeden Fall auch programmieren, aber da ist es einfacher (und sicherer), auf die bereits bestehenden zurückzugreifen.
_________________
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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 24.04.2022, 20:25    Titel: Antworten mit Zitat

Nachdem ich noch aus den Urzeiten der EDV stamme habe ich 2 Fragen:
1) wie liest man ganze Blöcke ein?
2) welche Datenbanksysteme gibt es auf die man zurückgreifen kann?

Ich denke zwar nicht, dass ich für meine Anwendung ein Datenbanksystem brauche. Nachdem die Vereine und die Mitglieder so nummeriert sind, dass die ID ident mit der Satznummer ist kann ich so ganz einfach direkt zugreifen. Ich musste mir nur eine Zwischendatei (Keyfile) schaffen und vom Verein zu seinen Mitgliedern zu kommen. So gesehen ist es doch noch relativ einfach. Mir geht es aber auch darum das Umfeld von FreeBasic etwas zu verstehn.
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



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

BeitragVerfasst am: 24.04.2022, 21:08    Titel: Antworten mit Zitat

Hier die Bibliotheken, die FreeBASIC "von Haus aus" unterstützt (also zu denen es auch bereits passende Header-Dateien gibt:
https://www.freebasic-portal.de/befehlsreferenz/externe-bibliotheken-639.html
Unter den Datenbanken ist genannt: GDBM, MySQL,PostgreSQL und SQLite.

Zum Einlesen ganzer Datenblöcke habe ich hier gerade einen Code herumliegen, der das mit einem selbstdefinierten Datentyp macht.
Code:
DIM AS INTEGER dateiNr = FREEFILE
TYPE T2DPunkt
  AS DOUBLE x, y
  AS STRING*1 bezeichner
  DECLARE CONSTRUCTOR
  DECLARE CONSTRUCTOR(x_ AS DOUBLE, y_ AS DOUBLE, bez as STRING)
END TYPE
CONSTRUCTOR T2DPunkt    ' leerer Standardkonstruktor
END CONSTRUCTOR
CONSTRUCTOR T2DPunkt(x_ AS DOUBLE, y_ AS DOUBLE, bez as STRING)
  x          = x_
  y          = y_
  bezeichner = bez
END CONSTRUCTOR

' Speicher reservieren und Daten anlegen
DIM AS T2DPunkt PTR speicherAlt = CALLOCATE(3, SIZEOF(T2DPunkt))
DIM AS T2DPunkt PTR punktA = NEW (speicherAlt)   T2DPunkt( 3,  -1.5, "A")
DIM AS T2DPunkt PTR punktB = NEW (speicherAlt+1) T2DPunkt( 5.1,   0, "B")
DIM AS T2DPunkt PTR punktC = NEW (speicherAlt+2) T2DPunkt(-2,   4.8, "C")
OPEN "temp_speicher.sav" FOR BINARY ACCESS WRITE AS #dateiNr
PUT #dateiNr, 0, *speicherAlt, 3
CLOSE #dateiNr

' weiteren Speicher reservieren und Daten laden
DIM AS T2DPunkt PTR speicherNeu = CALLOCATE(3, SIZEOF(T2DPunkt))
DIM AS T2DPunkt PTR punktX = NEW (speicherNeu)   T2DPunkt
DIM AS T2DPunkt PTR punktY = NEW (speicherNeu+1) T2DPunkt
DIM AS T2DPunkt PTR punktZ = NEW (speicherNeu+2) T2DPunkt
OPEN "temp_speicher.sav" FOR BINARY ACCESS READ AS #dateiNr
GET #dateiNr, 0, *speicherNeu, 3
CLOSE #dateiNr

' Ausgabe des dritten Punktes; aufraeumen und beenden
PRINT punktZ->bezeichner & "(" & punktZ->x & "/" & punktZ->y & ")"
DEALLOCATE speicherAlt
DEALLOCATE speicherNeu
SLEEP

Wobei es in deinem Fall vielleicht noch besser über ein Array ginge, weil du dann mit Array-Index direkt auf das passende Element zugreifen kannst.
_________________
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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 26.04.2022, 20:00    Titel: Antworten mit Zitat

danke nemored, für die ausführliche Information. Was den Code betrifft muss ich ihn erst "verdauen", da sind einige Befehle etc. enthalten mit denen ich noch nichts zu tun hatte. Dafür brauche ich noch Zeit!

Bis jetzt habe ich den Vorteil, dass mir das Vorsystem aus dem ich die Daten hole für alle Dateien IDs mit gibt die ident mit den Satznummern sind. Damit kann ich in vielen Fällen direkt auf den gewünschten Satz zugreifen.
In einem Fall ist das nicht möglich: wenn ich auf ein Mitglied in einem Verein zugreifen will geht das direkt nicht. Daher habe ich eine Keyfile erstellt der als erstes Feld die Vereinsnummer und als zweites die MitgliederID enthält. Damit kann ich direkt auf alle Mitglieder dieses Vereins (sequentiell) zugreifen. Wenn ich zusätzlich zur Vereinsnummer ein paar Anfangsbuchstaben des Namens habe bin ich mist schon beim richtigen Mitgliedersatz andernfalls muss ich zwischen 2-5 Sätzen wählen. Da gibt es absolut kein Problem mit der Geschwindigkeit.

Ich bin aber ständig auf der Suche mich zu verbessern und daher für jeden Hinweis und jede Anregung dankbar!
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 27.04.2022, 16:10    Titel: Antworten mit Zitat

Bei der heutigen Rechnergeneration brauchst du solche Klimmzüge nicht mehr.

Du kannst jeden Datensatz in einen passenden UDT packen und die ganze Datei als Array in den Arbeitsspeicher laden. Ich habe dir mal ein kleines Demoprogramm geschrieben, um zu zeigen, was heutzutage und mit FB möglich ist.

Es erstellt eine Datei mit 30000 Einträgen und schreibt sie auf die Festplatte, liest sie dann in ein Array ein, in dem du anschließend nach einem Namen suchen kannst (nur als Beispiel). Der Name lautet immer "Meier", gefolgt von dem Index, ohne Leerstelle. Das Programm durchsucht das Array von vorne, bis es den gesuchten Namen findet, der letzte Name ist "Meier30000". Das geht so schnell, daß du auf Indexdateien und ähnliches verzichten kannst.

Und keine Panik, wenn du nicht alles auf Anhieb verstehen solltest, speziell das Speichern und Lesen der Datensätze mittels eines eigenen UDTs und UNION ist ein einigermaßen tiefer Griff in die Trickkiste.
Code:
Type tDatensatz Field = 1
   As ULong mitgliedsnummer
   As String*40 Name
   As String*40 vorname
   As ULong plz
   As String*40 wohnort
   As Byte dummy
End Type

Type tZumSpeichern Field = 1
   Union
      datensatz As tDatensatz
      datensatz_ As String*SizeOf(tDatensatz)
   End Union
End Type

Dim As Integer x
Dim As String suchname
Dim As tDatensatz datensatz
Dim As tZumSpeichern speichern

'Datei mit 30000 Einträgen erstellen
Open ExePath + "\datei.dat" For Output As #1
For x = 1 To 30000
   With datensatz
      .mitgliedsnummer = x
      .name = "Meier" + Str(x)
      .dummy = 255
   End With
   speichern.datensatz = datensatz
   Print #1, speichern.datensatz_;
Next
Close 1

'datei in array einlesen
Open ExePath + "\datei.dat" For Binary As #1

ReDim As tDatensatz datenarray(0)

x = 1
Do
   speichern.datensatz_ = Input(SizeOf(tZumSpeichern) - 1, #1)
   ReDim Preserve datenarray(x)
   datenarray(x) = speichern.datensatz
   x += 1
Loop Until Eof(1)
Close 1

'name im array suchen
Do
   Input "nach Namen suchen"; suchname
   If suchname = "" Then
      Exit Do
   EndIf
   For x = 1 To UBound(datenarray)
      With datenarray(x)
         If .name = suchname Then
            Print "Name gefunden:  ";.name
            Print "Mitglidsnummer: ";.mitgliedsnummer
            Print
            Exit For
         EndIf
      End With
   Next
   If x = UBound(datenarray) + 1 Then
      Print "Name nicht gefunden"
   EndIf
   Print
Loop


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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 27.04.2022, 17:06    Titel: Antworten mit Zitat

Hallo grindstomne und nemored!
Da habt ihr euch viel Arbeit für mich gemacht! Ich bin von den Möglichkeiten beeindruckt, das wäre damals nie so möglich gewesen!
Da kann ich in meinem Konzept einiges vereinfachen!

Das führt mich gleich zu einer neuen Frage: das Problem habe ich zwar gelöst aber ich denke, dass es schneller gehen müsste.
Es handelt sich um eine Tabelle, die ca. 1500 Elemente mit einer Länge von String * 8 enthält. Der Sort dauert so ca. 5 Minuten. Wenn ich vergleiche, dass das Einlesen der Input-Datei mit ca. 440.000 Sätzen und das Erstellen der Sorttabelle keine 15 Sekunden dauert ist das eine Ewigkeit.
Ich kann mir nur vorstellen, dass mein Sort (Bubble-Sort) sehr langsam und die Daten sehr bunt gemischt sind, so dass sehr viel herumgeswapt werden muss.
Gibt es dafür schnellere Sort-Codes?
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



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

BeitragVerfasst am: 27.04.2022, 21:30    Titel: Antworten mit Zitat

Sehr effektiv ist Quicksort, der Algorithmus ist aber nicht so leicht zu durchdringen.

Code:
sub quicksort(a() as string, byval s as integer = 0, byval e as integer = -1)
  if s = 0 then s = lbound(a)
  if e = -1 then e = ubound(a)
  dim as integer i = s, j = e
  dim as string mitte = lcase(a((i+j)\2))
  do
    while lcase(a(i)) < mitte : i += 1 : wend
    while lcase(a(j)) > mitte : j -= 1 : wend
    if i <= j then
      swap a(i), a(j)
      i += 1
      j -= 1
    end if
  loop until i > j
  if j > s then quicksort(a(), s, j)
  if i < e then quicksort(a(), i, e)
end sub

Das ist jetzt rein für Strings; zum Sortieren von UDTs muss die Vergleichsoption entsprechend angepasst werden. Es gibt aber auch eine Implementierung in der C-Runtime, die wahrscheinlich theoretisch empfehlenswert ist (weil universell einsetzbar), aber für die man sich ein wenig in Callback-Funktionen einarbeiten sollte.

Noch effektiver sind gut aufgebaute Suchbäume, aber das würde ich schon als deutlich fortgeschrittene Technik bezeichnen. Da geht es dann nicht nur um das Verwalten bestehender Datensätze, sondern um den effektiven Aufbau der kompletten Datenstruktur.

@grindstone
Zu deinem Array-Beispielen: Hast du mal NEW[] mit Angabe der Startadresse versucht? Das müsste sich eigentlich sehr elegant machen lassen; mir fehlt nur gerade die Zeit zum experimentieren ...
_________________
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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 27.04.2022, 21:49    Titel: Antworten mit Zitat

Danke für den Code, ich werde ihn probieren!

In der Zwischezeit habe weiterprobiert und auch im Internet gesucht. Nach irgend einem Satz den ich gelesen habe kam mir der Verdacht, dass mein Sort deshalb so langsam sein könnte weil ich eine Stringtabelle sortiere. Ich habe dann den Sortbegriff (es sind die Mitgliedernummer und ein 2stellieger Zahlencode) so zusammengestellt, das ein Integerwert (ULONG) entstand. Damit hatte ich eine Integertabelle und nun dauerte der Sort kaum mehr als 20 Sekunden statt fast 5 Minuten und das ist akzeptabel.

Trotzdem werde ich den Quicksort auch genauer ansehen!
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 30.04.2022, 19:59    Titel: Antworten mit Zitat

Du hast an anderer Stelle erwähnt, daß deine Dateien im CSV-Format vorliegen. Die Funktionen zum Lesen und Schreiben dieses Formates lassen sich direkt in den UDT integrieren. Ich habe mein kleines Beispielprogramm von oben mal entsprechend umgeschrieben. Damit kannst du jetzt auch Strings mit variabler Länge verwenden.
Code:
Type tDatensatz
   As ULong mitgliedsnummer
   As String Name
   As String vorname
   As ULong plz
   As String wohnort
   Declare Sub speichern(dateinr As ULong)
   Declare Sub lesen(dateinr As ULong)
End Type

Sub tDatensatz.speichern(dateinr As ULong)
   With This
      Print #dateinr, mitgliedsnummer; ","; _
                      Name; ","; _
                      vorname; ","; _
                      plz; ","; _
                      wohnort
   End With
End Sub

Sub tDatensatz.lesen(dateinr As ULong)
   With This
      Input #dateinr, mitgliedsnummer
      Input #dateinr, Name
      Input #dateinr, vorname
      Input #dateinr, plz
      Input #dateinr, wohnort
   End With
End Sub

Dim As Integer x
ReDim As tDatensatz datenarray(1)

'datenarray anlegen
ReDim datenarray(30)
For x = 1 To UBound(datenarray)
   With datenarray(x)
      .mitgliedsnummer = x
      .name = "Meier" + Str(x)
      .wohnort = "Berlin"
   End With
Next

'datenarray im CSV-format in datei schreiben
Open ExePath + "\datei.dat" For Output As #1
For x = 1 To UBound(datenarray)
   datenarray(x).speichern(1)
Next
Close 1

ReDim datenarray(1) 'datenarray zurücksetzen

'CSVdatei einlesen und in array schreiben
Open ExePath + "\datei.dat" For Input As #1
x = 1
Do
   ReDim Preserve datenarray(x) 'neues arrayelement anlegen
   datenarray(x).lesen(1) 'datensatz in arrayelement schreiben
   x += 1 'nächstes element
Loop Until Eof(1)
Close 1

'ausdrucken
Print "Anzahl der Datensätze: "; UBound(datenarray)
Print
For x = 1 To UBound(datenarray)
   Print "Datensatz Nr."; x
   With datenarray(x)
      Print "Mitgliedsnummer: "; .mitgliedsnummer
      Print "           Name: "; .name
      Print
      Sleep
   End With
Next


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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 01.05.2022, 08:37    Titel: Antworten mit Zitat

Vielen Dank für diesen Code, solche Beispiele geben mir sehr viel!
Was das Auslesen von Daten aus CSV-Dateien betrifft hatte ich eine sehr gut brauchbare Version von nemored. Dann habe ich aber CSV-Dateien bei den Übernahmedateien aus dem Vorsystem gefunden die als Trenn zeichen nur ein einfaches Komma und nicht "," hatten. Jetzt nutzte mir die vorhanden Funktion nichts mehr und ich schrieb eine eigene. Dabei machte ich mir aber die Grundidee von nemored zu eigen indem ich eine Schleife über den benötigten Teil csv-Datensatzes legte und nur die Indizes verwende die ich brauche. In meiner Funktion verwende ich immer nur den linken Teil des Satzes und kürze den Satz für die weitere Verarbeitung um diesen Teil. Sobald ich das hatte erkannte ich, dass ich mit nur 2 Erweiterungen beide Arten von csd-Dateien so zerlegen konnte - ohne beim Aufruf unterscheiden zu müssen. So sieht der Code aus:
Code:

DECLARE FUNCTION csv_zerlegen (satz AS STRING) AS STRING

' csv-Datei zerlegen
'
Dim SHARED As STRING sWert
DIM SHARED AS INTEGER iKomma, iTyp
FUNCTION csv_zerlegen (sSatz AS STRING) AS STRING
   IF LEFT(sSatz,1) = CHR(34) THEN
      iTyp = 2
      sSatz = RIGHT(sSatz, LEN(sSatz)-1)  '1. Hochkomma entfernen
   ELSE
      iTyp = 1
   endif
   iKomma = INSTR(sSatz, ",")
   sWert = LEFT(sSatz, iKomma - iTyp)
   sSatz = RIGHT(sSatz, LEN(sSatz)-iKomma)
   RETURN sWert
END FUNCTION

line input #fc, sSatz
   FOR I = 1 TO 7
      sWert = csv_zerlegen(sSatz)
      IF I = 1 THEN iRey1 = VAL(sWert)   ' Vereinssnummer
      IF I = 2 THEN
         IF sWert = "FALSE" THEN
            bRey4 = 0         ' Flag: Verein=0
         ELSE
            bRey4 = 1         ' Flag: In Gründung=1
         ENDIF
      endif
      IF I = 3 THEN sRey2 = sWert      ' Vereinsname
      IF I = 5 THEN iRey3 = VAL(sWert)   ' Nummer
      IF I = 6 THEN
         IF VAL(sWert) > 0 THEN
            bRey5 = 0         ' Flag: aktive=0
         ELSE
            bRey5 = 1         ' Flag: inaktiv = 1
         ENDIF
      ENDIF
   NEXT

Im Grunde muss ich je CSV-Datei nur die FOR-Schleife anpassen, um alle erforderlichen Felder zu erhalten und dann ich Programm mit den IF-Statements die Felder selektiv einlesen.

EDIT: hab da noch einen Fehler gefunden! Die Funktion funktioniert gut wenn es in den CSV-Dateien keine Ausnahmen (z.B. Komma im Text) gibt. Bin dabei das einzubauen.
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 02.05.2022, 10:25    Titel: Antworten mit Zitat

kilix hat Folgendes geschrieben:
...als Trenn zeichen nur ein einfaches Komma und nicht "," hatten...
...wenn es in den CSV-Dateien keine Ausnahmen (z.B. Komma im Text) gibt...

Ich glaube, da machst du einen kleinen Denkfehler. Die Anführungsstriche gehören nicht zum Trennzeichen, sondern zum Text, eben damit Kommata im Text nicht als Trennzeichen interpretiert werden. Kommt im Text kein Komma vor, sind die Anführungsstriche überflüssig, sie schaden aber auch nicht.

Ersetze in meinem letzten Beispielprogramm die Zeile
Code:
.name = "Meier" + Str(x)
durch
Code:
.name = """Meier, Sepp" + Str(x) + """"
dann siehst du, was ich meine (und daß auch die INPUT - Funktion von FB korrekt damit umgehen kann, es gibt von daher also eigentlich keinen Grund, einen eigenen Stringparser zu schreiben).

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
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 02.05.2022, 12:50    Titel: Antworten mit Zitat

Ich habe deinen letzten Code eimal -nun ja- überarbeitet grinsen

So würde ich diese Aufgabe lösen:
Code:
' csv-Datei zerlegen
'
Function csv_zerlegen (sSatz As String = "") As String
   Static As String text 'sSatz merken als arbeitskopie
   Static As ULong a, e 'pointer auf text, anfang und ende
   Dim As String rueck
      
   If Len(sSatz) Then 'neuer string, alles auf anfang setzen, ansonsten alten string weiter durchsuchen
      text = sSatz 'satz merken als arbeitskopie
      a = 1
      e = 1
   EndIf
   
   If e = 0 Then 'satz ist abgearbeitet, leerstring zurückgeben
      Return ""
   EndIf
   
   e = InStr(a, text, Any """,") 'anführungsstriche oder komma suchen
   
   If Mid(text, e, 1) = """" Then 'text in anführungsstrichen
      e = InStr(e + 1, text, """") 'endpointer auf 2. anführungsstriche setzen
      e = InStr(e + 1, text, ",") 'endpointer auf nächstes komma setzen
   EndIf
      
   rueck = Trim(Mid(text, a, e - a), """") 'text zwischen den pointern zurückgeben und anführungsstriche entfernen
      
   a = e + 1 'anfangspointer hinter endpointer setzen für nächsten wert
   
   Return rueck
End Function

Dim As ULong fc, I, iRey1, iRey3
Dim As String sSatz, sRey2
Dim As boolean bRey4, bRey5

Line Input #fc, sSatz

iRey1 = Val(csv_zerlegen(sSatz))   ' Vereinssnummer
bRey4 = IIf(csv_zerlegen() = "FALSE", 0, 1) ' Flag: Verein=0 / In Gründung=1
sRey2 = csv_zerlegen()      ' Vereinsname
csv_zerlegen() 'wert überspringen
iRey3 = Val(csv_zerlegen())   ' Nummer
bRey5 = IIf(Val(csv_zerlegen()) > 0, 0, 1) ' Flag: aktive=0 / inaktiv = 1
csv_zerlegen() 'wert überspringen


Der Stringparser funktioniert folgendermaßen: Wenn du einen Text als Parameter mitgibst, wird dieser gespeichert und der erste Wert zurückgegeben. Bei jedem weiteren Aufruf mit einem Leerstring oder ohne Parameter gibt er den nächsten Wert zurück. Ist der gesamte String abgearbeitet, wird ein Leerstring zurückgegeben.

Beachte besonders die statischen Variablen innerhalb der Funktion (STATIC), daduch sparst du dir die globalen Variablen außerhalb (SHARED).

Ich habe den Parser mit allen Gemeinheiten getestet, die mir gerade eingefallen sind, er scheint zu funktionieren. Falls jemand doch noch einen Fehler entdeckt, bitte melden.

Gruß
grindstone

EDIT:
Einen Fehler habe ich noch entdeckt (und korrigiert).
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!


Zuletzt bearbeitet von grindstone am 03.05.2022, 10:20, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
nemored



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

BeitragVerfasst am: 02.05.2022, 18:43    Titel: Antworten mit Zitat

Schöner Einsatz von STATIC. Vielleicht denke ich daran, etwas in der Art ins Einsteigerhandbuch einzubauen. 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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 03.05.2022, 10:23    Titel: Antworten mit Zitat

ich danke euch wieder für die vielen Codes die ihr mir sendet! Leider brauche ich länger, um das alles zu verarbeiten aber ich gebe vorerst alles in mein Archiv in dem ich nach Bedarf stöbern kann.
Was das von mir so genannte Trennzeichen "," betrifft ist mir schon klar, dass das eigentliche Trennzeichen das Komma ist und die Hochkomma die Felder begrenzen.

Was bei mir aber zu einem Problem geführt hat hat nichts mit Programmierung zu tun. Ich habe einige CSV-Dateien zerlegt und alle hatte die Hochkomma und das Komma. Doch dann stolperte ich über eine CSV-Datei bei der die Hochkomma fehlten. Das veranlasste mich die letzte Funktion 'csv-zerlegen' zu schreiben (die inzwischen für beide Varianten funktioniert). Allerdings habe ich gestern in der Zip-Datei die die aus dem Vorsystem stammenden CSV-Dateien enthält gesehen, dass alle die Kombination "," haben auch die die bei mir nur Kommas hatte. Dazu habe ich nur eine Erklärung: wahrscheinlich (erinnern kann ich mich nicht mit dem Kopf durch die Mauer wollen) habe ich diese CSV-Datei als Tabelle eingelesen (nicht als Excel sondern im Format von OpenOffice) und dann wieder als CSV ausgegeben und OpenOffice speichert die " nicht mit. Also war meine Bemühung beide Varianten abzudecken vergebens.
Das hat mich doch viel Zeit gekostet. Das nun auf "," zu ändern ist kein Problem. Der Vorteil der neuen Funktion ist aber, dass innerhalb eines Textfeldes beliebig viele Beistriche sein können weil ich diese Prüfung in eine Schleife gelegt habe. Also werde ich jetzt alles bestehende auf diesen Standard bringen und mich erst dann Neuem zuwenden.
_________________
Grüße
kilix
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1208
Wohnort: Ruhrpott

BeitragVerfasst am: 03.05.2022, 11:31    Titel: Antworten mit Zitat

@kilix:
Natürlich ist das alles neu und braucht seine Zeit. lächeln Insbesondere der Umgang mit UDTs (TYPE) erfordert eine andere Denkweise. Ich empfehle dir aber dringend, dich damit zu befassen, denn es kann dir viel Arbeit beim Programmieren ersparen und steigert die Übersichtlichkeit von Programmen ganz enorm.

Was deine CSV - Dateien betrifft, hat das Vorhandensein der Anführungsstriche wahrscheinlich einen viel profaneren Grund: Da sie -wie ich schon geschrieben habe- auch nicht schaden, wenn kein Komma im Text vorkommt, werden sie einfach standardmäßig dazugeschrieben, damit spart man sich die Fallunterscheidung. Und wenn garantiert niemals ein Komma im Text vorkommt, kann man sie auch generell weglassen.

@nemored:
Diese Art von Parser benutze ich üblicherweise, um bestimmte Textstellen in HTML - Texten zu finden und zu isolieren.

Die Methode ist sehr flexibel, da sich die Textpointer in beide Richtungen schieben lassen, beispielsweise im gesamten Text ein bestimmtes Schlüsselwort suchen, dann von dort aus den Anfangspointer rückwärts zum Starttag und den Endpointer vorwärts zum Endtag. Und da der Text dabei nicht verändert wird, kann man das Ganze auch mehrmals durchführen.

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
nemored



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

BeitragVerfasst am: 03.05.2022, 18:09    Titel: Antworten mit Zitat

Wenn ich mich nicht sehr täusche, schreibt auch der FreeBASIC-Befehl WRITE einen String immer mit Anführungszeichen, egal ob nötig oder nicht. Eben genau aus dem Grund, dass dann nicht erst die Notwendigkeit geprüft wird. Wenn du also z. B. alle Einträge mit INPUT einliest und mit WRITE in eine neue Datei schreibst, sollten danach in der neuen Datei alle Einträge in Anführungszeichen stehen.

(PRINT schreibt dagegen immer ohne Anführungszeichen - solange man sie nicht selbst dazusetzt - und ist für Strings, die ein Komma enthalten, zu CSV-Zwecken nicht geeignet.)

((Und wenn ich jetzt so recht darüber nachdenke, beschleicht mich das Gefüh, dass das vor Kurzem schon geschrieben wurde - wenn dem so ist, tut es mir leid.))
_________________
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
kilix



Anmeldungsdatum: 05.02.2022
Beiträge: 175

BeitragVerfasst am: 06.05.2022, 20:09    Titel: Antworten mit Zitat

ich habe jetzt ein paar Tage nichts gemacht bin aber jetzt - wenn auch schaumgebremst wieder dran.
Die CSV-Dateien sind geklärt, es gibt in den Dateien die ich aus dem Vorsystem übernehme nur solche die " als Textbegrenzer und Komma als Feldbegrenzer haben. Damit ist alles einheitlich und kein Problem mehr in der Bearbeitung. Das funktioniert jetzt gut und problemlos.
Jetzt habe ich meinen Bubble-Sort auf den Quicksort von nemored umgestellt. Das schien ganz einfach aber ich mache da was falsch denn nach dem Sort ist der sortierte Array leer.
Ich habe hier symbolisch im Code dargestellt wie ich es codiert habe
Code:

DECLARE sub quicksort(a() as string, byval s as integer = 0, byval e as integer = -1)
'
REDIM A(1 TO 1000) AS string
'
' Aufbau Sorttabelle
'
While Not Eof(fc)
   IF iSatznr > 1000 THEN REDIM preserve A(1 TO iSatznr) ENDIF
   A(iSatznr) = RIGHT("00000" & STR(iWer1),5) & RIGHT("00" & STR(iWer2b),2)
WEND
'
quicksort(A(), 0, -1)
'
FOR I = 1 TO UBOUND(A)
PRINT A(I): getkey         '<=== A(I) ist leer
   sWer1 = left(A(I),5)
   usw
'
'   Quicksort
'
sub quicksort(a() as string, byval s as integer = 0, byval e as integer = -1)
  if s = 0 then s = lbound(a)
  if e = -1 then e = ubound(a)
  usw

Alles was ich sonst codiert habe und das mit dem Problem garantiert nichts zu tun hat habe ich weggelassen. Ich nehme an, dass der Fehler im Aufruf des Quicksort liegt denn bis dahin ist alles in Ordnung. Erst nach dem Quicksort ist die Tabelle leer.

EDIT 8.5.22:
Problem gelöst! offen gesagt weiß nicht exakt wodurch, habe zurück geändert auf den Bubble-Sort, drei sachliche Verarbeitungsfehler korrigiert und nachdem das funktioniert hat wieder zum Quicksort gewechselt.
_________________
Grüße
kilix


Zuletzt bearbeitet von kilix am 08.05.2022, 08:30, insgesamt einmal bearbeitet
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 FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
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