[gelöst] dringende Hilfe bei einem Programm!

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
hilfelazarus
Beiträge: 5
Registriert: Sa 16. Aug 2014, 16:56

[gelöst] dringende Hilfe bei einem Programm!

Beitrag von hilfelazarus »

:shock: Liebe Community,

ich bin relativ neu in Lazarus, Pascal und insgesamt der Programmierung und arbeite zur Zeit an einer Art "Lernprogramm" mit Quiz für Englisch. Dabei treten einige Fehler auf:

Zunächst erst einmal das gesamte Projekt im Ordner, falls jemand so nett ist und das mal ausprobiert ;)
[Link entfernt]

Update: gelöst
(1. Problem:
- beim Lesen der Fragen und Antworten aus einer, von mir bereits erstellten fragen.db Datei liest das Programm an einer bestimmten Stelle die Frage nicht, die Antworten schon.)

Update: gelöst
2. Problem:
- ich möchte die Ergebnisse mit Namen des Spielers und erreichter Punktzahl in eine Textdatei schreiben (ergebnisse.txt).



Vielleicht könnt ihr mir weiterhelfen, ich würde mich sehr sehr freuen! Bei weiteren Infos einfach fragen...

Liebe Grüße
der Hilfesuchende
Zuletzt geändert von hilfelazarus am So 17. Aug 2014, 18:42, insgesamt 6-mal geändert.

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Hilfe bei einem Programm

Beitrag von Heinrich Wolf »

Hallo.

Du hast ja schon ganz schön viel Arbeit in Dein Programm gesteckt.

Dein Programm wirft bei mir nach "Test starten" eine SIGSEGV. D.h. es überschreibt Speicher, der ihm nicht gehört. Danach kann man für nichts mehr garantieren. Der Assembler, der aufgeblendet wird, hilft Dir nicht weiter.

Du deklarierst in Unit3.pas

Code: Alles auswählen

var datei:file of fragen;             //Variablendeklaration
    afragen:array[1..4] of fragen;
    datensatz:fragen;
    fnr:integer;punkte:integer;       
Aber Deine Laderoutine B_starttestClick(Sender: TObject); liest einfach alles, was in der Datei ist und kümmert sich nicht um den Wertebereich des Index von afragen.

Vielleicht wäre es besser gewesen, afragen als dynamisches array zu deklarieren.

Code: Alles auswählen

afragen = array of fragen;
SetLength(afragen, i);
Heiner

Soner
Beiträge: 726
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: dringende Hilfe bei einem Programm!

Beitrag von Soner »

Der Fehler steckt wie Heinrich Wolf schreibt bei:
afragen:array[1..4] of fragen;

Du kümmerst in Leseroutine (procedure TForm3.B_starttestClick(Sender: TObject); ) nicht um korrekte Größe und definierst afragen-Array ab 1 an aber belegst es schon mit afragen[0]
Definiere das mal so:
afragen:array[0..400] of fragen;
Dann läuft es. Natürlich ist es nur zum Testen, du musst für richtige Größe sorgen, bei 401 fragen würde es wieder Fehler verursachen.

hilfelazarus
Beiträge: 5
Registriert: Sa 16. Aug 2014, 16:56

Re: Hilfe bei einem Programm

Beitrag von hilfelazarus »

Erst einmal einen herzlichen Dank für eure schnelle Hilfe! Echt nett!

An Heinrich Wolf habe ich eine Frage:

Wie definiere ich dann "i" ? Ist es durch die Fragenanzahl zu ersetzen?
Heinrich Wolf hat geschrieben:

Code: Alles auswählen

afragen = array of fragen;
SetLength(afragen, i);
Heiner
Ansonsten würde ich einfach

Code: Alles auswählen

afragen = array [1..15] of fragen;

schreiben, da ich das Programm erst einmal so lassen möchte...

Wenn es euch möglich wäre, würde ich gern noch mal über das 2te Problem eure Hilfe einholen.
Ich möchte in eine/mehrere Textdatei/en (am besten wäre es, wenn das Programm für jeden Spieler eine neue "vnamenname.txt" Datei erstellen könnte [ich weiß nicht, wie ich den ausgelesenen Namen aus den Editfeldern in den Variablen "vname" und "nname" dann als automatische Dateibezeichner funktionalisieren kann], wo die erreichte Punktzahl sowie die jeweiligen Antworten zu jeder Frage gespeichert werden) die Informationen reinschreiben.
Mein erster Ansatz war ja der:

Code: Alles auswählen

 procedure TForm3.B_auswertungClick(Sender: TObject);
begin
  Showmessage('Congratulations! You reached '+inttostr(punkte)+' points.');
  assignfile(datei_antworten,'ergebnisse.txt');
  rewrite (datei_antworten);
  closefile(datei_antworten);
  assignfile(datei_antworten,'ergebnisse.txt');
  rewrite(datei_antworten);
  vorname:='Vorname:' + vname;
  nachname:='Nachname:' + nname;
  punkte_erreicht:='Punkte:' + IntToStr(punkte);
  spielerdatensatz:=vorname+','+nachname+','+punkte_erreicht;
  writeln(datei_antworten,spielerdatensatz);
  closefile(datei_antworten);
end;
Aber da speichert er ja nur in einer Datei :( und überschreibt diese beim nächsten mal einfach, wegen fehlender Neubezeichnung der .txt Datei. Vielleicht kann mir jemand von euch sagen, wie ich dann noch die Antworten des Spielers auslesen und mit in diese Datei schreiben kann. Ich wollte das auch über einen record machen

Code: Alles auswählen

 type antworten = record
            vname:string[30];
            nname:string[40];
            ant_geg:string[30];
            punkte_err:integer; 

Nochmals vielen Dank! Ich freue mich sehr!

wp_xyz
Beiträge: 5135
Registriert: Fr 8. Apr 2011, 09:01

Re: dringende Hilfe bei einem Programm!

Beitrag von wp_xyz »

Wie definiere ich dann "i" ? Ist es durch die Fragenanzahl zu ersetzen?
Ja, aber du weißt im Allgemeinen doch nicht, wieviele Fragen in der Datei stehen. Am besten arbeitest du mit einem dynamischen Array (aFragen: array of fragen), startest mit Array-Länge 0 und erhöhst die Array-Lange vor jedem Datensatz um 1 (es geht auch besser, aber das würde dich hier nur verwirren). Und beachte, dass die Indizierung eines dynamischen Arrays bei 0 beginnt. So sollte die Leseroutine in unit3 funktionieren (nicht getestet):

Code: Alles auswählen

 
var
  afrage: array of fragen
 
procedure TForm3.B_starttestClick(Sender: TObject);
var i:integer;
 begin
   SetLength(afragen, 0);  // wp
   RG_frage.visible:=true;
   RB_1.Visible:=true;
   RB_2.Visible:=true;
   RB_3.Visible:=true;
   B_starttest.visible:=false;
   punkte:=0;                         //Punkte-Startwert festlegen
   fnr:=1;                            //FragenNummer auf 1 setzen
   assignfile(datei,'fragen.db');     //die .db-Datei wird der Variable "datei" zugewiesen
   reset(datei);                      //Öffnen der Datei zum Lesen
   i:=0;
   seek(datei,0);
   while not eof(datei) do begin     //Auslesen der "fragen.db"-Datei mit Schleife
         seek(datei,i);              //Datensatzzeiger setzen
         read(datei,datensatz);      //Lesen eines Datensatzes
         SetLength(afragen, i+1);    // wp: Platz im Array für neue Frage schaffen
         afragen[i].frtext:=datensatz.frtext; //Belegung des zuvor definierten Records mit den Daten aus der "fragen.db"-Datei
         afragen[i].a1:=datensatz.a1;
         afragen[i].a2:=datensatz.a2;
         afragen[i].a3:=datensatz.a3;
         afragen[i].richtig:=datensatz.richtig;
         fnr:=1;
         punkte:=0;
         i:=i+1;            // wp: Zähler hochzählen. Steht jetzt am Ende, weil die Indizierung des Arrays bei 0 beginnt.
   end;
   closefile(datei);                    //Datei schließen
 
   // wp: Im folgenden wird Index 1 durch 0 ersetzt
   RG_frage.Caption:=afragen[0].frtext; //Füllen der Überschrift der RadioGroup mit der Frage Nr. 1 aus der Datei
   RB_1.Caption:=afragen[0].a1;         //Füllen des 1. Radiobuttons mit der Antwort Nr. 1 zur Frage 1 aus der Datei
   RB_2.Caption:=afragen[0].a2;         //Füllen des 2. Radiobuttons mit der Antwort Nr. 2 zur Frage 1 aus der Datei
   RB_3.Caption:=afragen[0].a3;         //Füllen des 3. Radiobuttons mit der Antwort Nr. 3 zur Frage 1 aus der Datei
   B_pruefen.Visible:=true;
 end;
 


Zur 2. Frage: Ich würde alles in eine Datei schreiben, ein Record pro Teilnehmer. Wenn du die Ergebnisse eines Teilnehmers abspeichern willst, musst du zuerst suchen ob dieser schon eingetragen ist und den Datensatz überschreiben. Es gibt bessere Methoden, aber du hast mit klassischen Dateien angefangen, dann könntest du so vorgehen:

Code: Alles auswählen

 
procedure TForm3.B_auswertungClick(Sender: TObject);
const
  DATEINAME = 'ergebnisse.txt';  // wird öfter verwendet!
 
type 
  // Das ist der Record, der in die Datei geschrieben wird. Wichtig ist, dass die Größe konstant ist
  TAntworten = record  
    vname:string[30];
    nname:string[40];
    ant_geg:string[30];
    punkte_err:integer;
  end;
 
var
  p: Integer; 
  antworten: TAntworten;
 
begin
  Showmessage('Congratulations! You reached '+inttostr(punkte)+' points.');
 
  assignfile(datei_antworten,DATEINAME);
 
  // Wenn's die Antwortendatei bereits gibt, zuerst zum Lesen öffnen und die Position des Datensatzes suchen
  if FileExists(DATEINAME) then begin
    resetfile(datei_antworten, SizeOf(TAnworten));
    while not EoF(datei_antworten)  do begin
      p := FilePos(datei_antworten);
      Read(datei_antworten, antworten);
      if (antworten.vname = vname) and (antworten.nname=nname) then  
      // Hier ist der Datensatz gefunden. "p" hat sich die Position in der Datei gemerkt.
        break;
    end;
    closeFile(datei_antworten);
  end else
    p := 0;
 
  // Nun die Datei ein 2. Mal zum schreiben öffnen und an Position "p" den neuen Datensatz schreiben
  rewriteFile(datei_antworten, Sizeof(TAntworten));
  Seek(datei_antworten, p);
  antworten.vname := vname;
  antworten.nname := nname;
  // usw - die Felder des Record füllen...
  Write(datei_antworten, antworten);  // Hier wird der bisherige Record in der Datei überschreiben. Weil alle Records gleich groß sind, wird nichts zerstört!
  closeFile(datei_antworten);
 
[EDIT] Ich habe schon seit Urzeiten nichts mehr mit klassischen Dateien gemacht... Bin nicht mehr sicher, ob nicht die Datei bei "rewrite" gelöscht wird. --> ausprobieren. Und es fehlt oben noch die Deklaration der Dateivariablen:

Code: Alles auswählen

 
var
  datei_antworten: file of TAntworten;
 
Generell würde ich das Programm nicht mit klassischen Dateien angehen. Schon eine einfache INI-Datei für Fragen und Ergebnisse würde manches einfacher und klarer machen:

Code: Alles auswählen

 
uses
  IniFiles;
 
type
  TFrage = record
    Frage: String;
    Antwort1: String;
    Antwort2: String;
    Antwort3: String;
    Richtig: Integer;
  end;
 
var
  FragenArray: Array of TFrage;
 
procedure TForm3.B_starttestClick(Sender: TObject);
var
  ini: TIniFile;
  L: TStringList;
  key: String;
begin
  ini := TIniFile.Create('fragen.txt');   // Die Endung ".db" klingt zu sehr nach Datenbank
  L := TStringList.Create;
  try
    ini.ReadSection('Fragen', L);
    SetLength(FragenArray, L.Count);
    for i:=0 to L.Count-1 do begin
      key := 'Frage' + IntToStr(i+1);
      Fragen[i].Frage := ini.ReadString(key, 'Frage', '');
      Fragen[i].Antwort1 := ini.ReadString(key, 'Antwort1', '');
      Fragen[i].Antwort2 := ini.ReadString(key, 'Antwort2', '');
      Fragen[i].Antwort3 := ini.ReadString(key, 'Antwort3', '');
      Fragen[i].Richtig := ini.ReadInteger(key, 'Richtig', -1);
    end;
  finally
    L.Free;
    ini.Free;
  end;
 
  RG_frage.Caption:=Fragen[0].Frage; //Füllen der Überschrift der RadioGroup mit der Frage Nr. 1 aus der Datei
  RB_1.Caption:=Fragen[0].Antwort1;   //Füllen des 1. Radiobuttons mit der Antwort Nr. 1 zur Frage 1 aus der Datei
  RB_2.Caption:=Fragen[0].Antwort2;   //Füllen des 2. Radiobuttons mit der Antwort Nr. 2 zur Frage 1 aus der Datei
  RB_3.Caption:=Fragen[0].Antwort3;   //Füllen des 3. Radiobuttons mit der Antwort Nr. 3 zur Frage 1 aus der Datei
  B_pruefen.Visible:=true;
end;
 
Diese Ini-Datei ist eine Text-Datei, die du mit jedem Editor erstellen und ändern kannst - bei deinen eigenen Dateien geht das nicht. Hier wäre eine Beispiel:

Code: Alles auswählen

 
[Frage1]
Frage=How do you do?
Antwort1=Wie geht es Ihnen?
Antwort2=Wie alt sind Sie?
Antwort3=Was tun Sie da?
Richtig=1
 
[Frage2]
.... usw
 

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: dringende Hilfe bei einem Programm!

Beitrag von Heinrich Wolf »

Danke an wp_xyz für die Beantwortung an meiner Stelle!

hilfelazarus
Beiträge: 5
Registriert: Sa 16. Aug 2014, 16:56

Re: dringende Hilfe bei einem Programm!

Beitrag von hilfelazarus »

Sehr schön, ich habe das jetzt mit dem Array dynamisch gemacht, so wie du (wp_xyz) mir das sehr gut geschrieben hast. Bloß bei dem Schreiben in die Textdatei gibt es noch Probleme:

Ich habe beispielsweise mal den Namen "Testkanditat Name" eingegeben (zuvor auch schon andere...) und den Test gemacht. Merkwürdigerweise kommt dann in der .txt datei ein komischer Eintrag:

Code: Alles auswählen

Testkandidató$03u©Y§Ùô$‘m,NamezrƒÛ½  •´.tÔW $              p   ÿÿÿÿÿÿÿÿél,u‘m,u:(              
.

Wie kann das denn sein? Es scheint so, als würde er die alten Einträge überschreiben? Was machen diese Sonderzeichen da? Wäre es möglich, vname; nname; punkte... mit Komma zu trennen?

Viele Fragen, aber ich hoffe es gibt eine simple Antwort ;)


Hier noch mal der geupdatete Code:

Code: Alles auswählen

 
implementation
uses unit2, unit1;        //Zurückverweis auf das 2. Formular
 
{$R *.lfm}
 
{ TForm3 }
 
type fragen = record            //Definieren des Records, auf den zugegriffen werden soll
            frtext:string[255];
            a1:string[200];
            a2:string[200];
            a3:string[200];
            richtig:integer;
     end;
 
var datei:file of fragen;
    afragen:array of fragen;
    datensatz:fragen;
    fnr:integer;punkte:integer;
 
type TAntworten = record         // Das ist der Record, der in die Datei geschrieben wird. Wichtig ist, dass die Größe konstant ist
                vname:string[30];
                nname:string[40];
                punkte_err:integer;
     end;
 
var p: Integer;
    antworten: TAntworten;
    datei_antworten:file of TAntworten;
 
 
 
procedure TForm3.B_zurueckClick(Sender: TObject);
 begin
  form3.hide;                        //Formular 2 wird wieder eingeblendet, Formular 3 ausgeblendet
  form2.show;
 end;
 
procedure TForm3.B_starttestClick(Sender: TObject);
 var i:integer;
     begin
           SetLength(afragen, 0);
           RG_frage.visible:=true;
           RB_1.Visible:=true;
           RB_2.Visible:=true;
           RB_3.Visible:=true;
           B_starttest.visible:=false;
           punkte:=0;                         //Punkte-Startwert festlegen
           fnr:=1;                            //FragenNummer auf 1 setzen
           assignfile(datei,'fragen.db');     //die .db-Datei wird der Variable "datei" zugewiesen
           reset(datei);                      //Öffnen der Datei zum Lesen
           i:=0;
           seek(datei,0);
        while not eof(datei) do
              begin     //Auslesen der "fragen.db"-Datei mit Schleife
                 seek(datei,i);              //Datensatzzeiger setzen
                 read(datei,datensatz);      //Lesen eines Datensatzes
                 SetLength(afragen, i+1);    //Platz im Array für neue Frage schaffen
                 afragen[i].frtext:=datensatz.frtext; //Belegung des zuvor definierten Records mit den Daten aus der "fragen.db"-Datei
                 afragen[i].a1:=datensatz.a1;
                 afragen[i].a2:=datensatz.a2;
                 afragen[i].a3:=datensatz.a3;
                 afragen[i].richtig:=datensatz.richtig;
                 fnr:=1;
                 punkte:=0;
                 i:=i+1;            //Zähler hochzählen. Steht jetzt am Ende, weil die Indizierung des Arrays bei 0 beginnt.
              end;
        closefile(datei);                    //Datei schließen
 
   //Im folgenden wird Index 1 durch 0 ersetzt
        RG_frage.Caption:=afragen[0].frtext; //Füllen der Überschrift der RadioGroup mit der Frage Nr. 1 aus der Datei
        RB_1.Caption:=afragen[0].a1;         //Füllen des 1. Radiobuttons mit der Antwort Nr. 1 zur Frage 1 aus der Datei
        RB_2.Caption:=afragen[0].a2;         //Füllen des 2. Radiobuttons mit der Antwort Nr. 2 zur Frage 1 aus der Datei
        RB_3.Caption:=afragen[0].a3;         //Füllen des 3. Radiobuttons mit der Antwort Nr. 3 zur Frage 1 aus der Datei
        B_pruefen.Visible:=true;
   end;
 
procedure TForm3.B_pruefenClick(Sender: TObject);
 
    procedure antwort_pruefen(var fnr:integer);
     var korrekt:boolean;
            begin
              korrekt:=false;
              case afragen[fnr].richtig of
                   1: if RB_1.checked=true then korrekt:=true;
                   2: if RB_2.checked=true then korrekt:=true;
                   3: if RB_3.checked=true then korrekt:=true;
              end;
              if korrekt then
                 begin
                   L_richtig.caption:='That is absolutely correct!';
                   punkte:=punkte+1;
                 end
              else L_richtig.caption:='Sorry, this answer is wrong!';
              fnr:=fnr+1;
            end;
begin
  antwort_pruefen(fnr);
  L_richtig.Visible:=true;
  B_pruefen.Visible:=false;
  If fnr<15 Then B_naechste.Visible:=true
  Else
    begin
       RG_frage.Visible:=false;
       RB_1.Visible:=false;
       RB_2.Visible:=false;
       RB_3.Visible:=false;
       B_pruefen.Visible:=false;
       B_auswertung.Visible:=true;
       B_close.Visible:=true;
    end;
end;
 procedure TForm3.B_closeClick(Sender: TObject);
 begin
   close();
 end;
 
 
procedure TForm3.B_auswertungClick(Sender: TObject);
 const DATEINAME = 'ergebnisse.txt';  // wird öfter verwendet!
  begin
       Showmessage('Congratulations! You reached '+inttostr(punkte)+' points.');
       assignfile(datei_antworten,DATEINAME);
       if FileExists(DATEINAME) then
          begin
            reset(datei_antworten, SizeOf(TAntworten));
            while not EoF(datei_antworten) do
              begin
                   p:=FilePos(datei_antworten);
                   Read(datei_antworten, antworten);
                   if (antworten.vname=vname)and (antworten.nname=nname)then
                   break;
              end;
            closefile(datei_antworten);
            end else
            p:=0;
  // Nun die Datei ein 2. Mal zum schreiben öffnen und an Position "p" den neuen Datensatz schreiben
       rewrite(datei_antworten, Sizeof(TAntworten));
       Seek(datei_antworten, p);
       antworten.vname := vname;
       antworten.nname := nname;
       antworten.punkte_err:=punkte;
  // usw - die Felder des Record füllen...
       Write(datei_antworten, antworten);  // Hier wird der bisherige Record in der Datei überschreiben. Weil alle Records gleich groß sind, wird nichts zerstört!
       closeFile(datei_antworten);
  end;
procedure TForm3.B_naechsteClick(Sender: TObject);
 begin
       RB_1.Checked:=false;
       RB_2.Checked:=false;
       RB_3.Checked:=false;
       RG_frage.Caption:=afragen[fnr].frtext;
       RB_1.Caption:=afragen[fnr].a1;
       RB_2.Caption:=afragen[fnr].a2;
       RB_3.Caption:=afragen[fnr].a3;
       B_pruefen.Visible:=true;
       B_naechste.Visible:=false;
       L_richtig.Visible:=false;
 end;
end.
 
Liebe Grüße und nochmals recht herzlichen Dank^^
Zuletzt geändert von hilfelazarus am So 17. Aug 2014, 17:43, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: dringende Hilfe bei einem Programm!

Beitrag von mse »

hilfelazarus hat geschrieben: Was machen diese Sonderzeichen da?
Die Datei ist definiert als

Code: Alles auswählen

 
type fragen = record            //Definieren des Records, auf den zugegriffen werden soll
            frtext:string[255];
            a1:string[200];
            a2:string[200];
            a3:string[200];
            richtig:integer;
     end;
 
var datei:file of fragen;
 
Die Datei ist also keine Textdatei sondern eine Aneinanderreihung von "fragen" records. Das Format der string[nnn] Daten ist hier definiert:
http://www.freepascal.org/docs-html/ref ... 370003.2.5
Wenn in a1 z.B. 'abc' steht, sind die Daten: 3 (die Anzahl gültige Zeichen),'a','b','c' und 197 mal irgend ein zufälliger Wert.

hilfelazarus
Beiträge: 5
Registriert: Sa 16. Aug 2014, 16:56

Re: dringende Hilfe bei einem Programm!

Beitrag von hilfelazarus »

Hmm, aber die Fragen werden doch gar nicht gespeichert? Es geht doch um den Namen und die Punkte?

wp_xyz
Beiträge: 5135
Registriert: Fr 8. Apr 2011, 09:01

Re: dringende Hilfe bei einem Programm!

Beitrag von wp_xyz »

Wäre es möglich, vname; nname; punkte... mit Komma zu trennen?
Da du offenbar an einer "lesbaren" Text-Datei interessiert bist, würde ich die Datei nicht als "File of TAnworten" deklarieren, sondern einfach als "TextFile". Und das mittelalterliche Konstrukt mit den Strings vordefinierter Länge würde ich auch fallenlassen, und die Namen etc. einfach als "String" deklarieren, sie können dann beliebig lang werden und belegen nur soviel Speicher wie nötig. Allerdings sind dann die Records nicht mehr gleich lang, und du kannst beim Abspeichern eines Ergebnisses nicht mehr garantieren, nur die Daten eines Teilnehmers zu überschreiben. Daher würde ich zu Beginn die ganze Datei in eine TStringList einlesen, wobei jeder String für den komma-getrennten Eintrag eines Teilnehmers steht. Den String des betreffenden Teilnehmers änderst du dann entsprechend seiner Ergebnisse und schreibst die StringListe wieder in die Datei zurück. Interessanterweise brauchst du dazu gar keine Datei zu deklarieren, denn die Klasse TStringListe kann das schon alles. Wird super einfach, allerdings der Lerneffekt für den Umgang mit Dateien bleibt auf der Strecke. Deine Wahl...

Hier - nicht getestet - die Version mit der Stringliste:

Code: Alles auswählen

 
procedure TForm3.B_auswertungClick(Sender: TObject);
const ERGEBNIS_DATEINAME = 'ergebnisse.txt'; 
var
  ErgebnisList: TStringList;
  SuchText: String;
  ErgebnisZeile: String;
  i: Integer;
  IndexGefunden: Integer;
begin
  Showmessage('Congratulations! You reached '+inttostr(punkte)+' points.');
  ErgebnisList := TStringList.Create;
  try
    if FileExists(ERGEBNIS_DATEINAME) then
    begin
      ErgebnisList.LoadFromFile(ERGEBNIS_DATEINAME);  // Bisherige Ergebnisse aus Datei einlesen
      // Die Zeilen der Datei, d.h. Bestandteile der StringListe, sollen folgendermaßen aufgebaut sein:
      // vorname;nachname;ant_geg;punkte_err
      // Aus dem zu suchenden Teilnehmer den Anfang einer Zeile "vorname;nachname" zusammenbauen ...
      SuchText := vname + ';' + nname;
      // ... und suchen, in welchem Element der Liste der Teilnehmer enthalten ist:
      IndexGefunden := -1;
      for i:=0 to ErgebnisList.Count-1 do   // Die Indizierung beginnt bei 0. Bei "Count" Einträgen, ist der Index des letzten Eintrag "Count-1".
        if pos(SuchText, ErgebnisList[i]) = 1 then begin
          IndexGefunden := i;
          Break;
        end;
 
      // jetzt den neuen Ergebnis-String zusammenbauen
      ErgebnisZeile := vname + ';' + nname + ';' + ant_geg + ';' + IntToStr(punkte_err);
 
      if IndexGefunden <> -1 then
        // Wenn es für den Teilnehmer schon ein Ergebnis in der Datei gibt (IndexGefunden <> -1), diese Zeile ersetzen
        ErgbnisList[IndexGefunden] := ErgebnisZeile
      else
        // wenn nicht, die Ergebniszeile hinten an die ErgebnisList anhängen
        ErgebnisList.Add(ErgebnisZeile);
 
      // Geänderte ErgebnisListe speichern
      ErgebnisList.SaveToFile(ERGEBNIS_DATEINAME);
  finally
    ErgebnisList.Free;   // Immer darauf achten, dass alles, was man erzeugt, auch wieder freigegeben wird.
  end;
end;
 

wp_xyz
Beiträge: 5135
Registriert: Fr 8. Apr 2011, 09:01

Re: dringende Hilfe bei einem Programm!

Beitrag von wp_xyz »

hilfelazarus hat geschrieben:Hmm, aber die Fragen werden doch gar nicht gespeichert? Es geht doch um den Namen und die Punkte?
Ist egal - bei den Ergebnissen hast du dieselbe Situation: Wenn du einen String mit fester Länge deklarierst, steht an den nicht benötigten Stellen Müll.

hilfelazarus
Beiträge: 5
Registriert: Sa 16. Aug 2014, 16:56

Re: dringende Hilfe bei einem Programm!

Beitrag von hilfelazarus »

Vielen Dank! Es funktioniert alles ;) Ich bin echt erleichtert! Ich danke euch allen und vorallem wp_xyz für seine große Unterstützung!

Antworten