Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Selbstprogrammierung eines Vokabeltrainers (https://www.delphipraxis.net/180545-selbstprogrammierung-eines-vokabeltrainers.html)

Soph6297 27. Mai 2014 20:22

Selbstprogrammierung eines Vokabeltrainers
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guten Abend! :hi:

Schlussendlich habe ich jetzt doch meinen Weg hierher gefunden, da ich mit meinen bisherigen Kenntnissen leider nicht weiterkomme.
Wir haben in der Schule die Aufgabe bekommen ein Programm mit Delphi 6 selbst zu schreiben, uns blieb dabei überlassen, welche Art von Programm wir erstellen.
Ich habe mich für eine Art Vokabeltrainer entschieden, allerdings mit Geschichtsjahreszahlen/-ereignissen.

Ich habe bereits mit dem Schreiben des Quelltextes begonnen und möchte einmal kurz umreißen, wie ich mir das Programm vorgestellt habe (Formular s. Anhang);
Ich habe eine separate Textdatei (war Pflicht bzw. eine typisierte Datei), deren Inhalt ich in die ListBox hochlade. Der Inhalt besteht aus geschichtlichen Ereignissen, wie z.B. die Kaiserkrönung Napoleons. Die ListBox ist beim Ausführen des Programms nicht sichtbar. Eine Zeile der Textdatei wird zufällig in das Panel geladen und zu diesem Ereignis muss dann später die passende Jahreszahl eingegeben werden (Edit-Feld).
Anleitung- und Abbruch-Button sind an der Stelle nicht weiter relevant.
Durch Klick auf den "Neues Ereignis" Button soll zufällig ein neues Ereignis aus der Textdatei in das Panel geladen werden (funktioniert soweit!).
Durch Klick auf den "Ok"-Button soll geprüft werden, ob die eingegebene Jahreszahl mit dem Ereignis übereinstimmt.
Und da komme ich nicht weiter...
Mein bisheriger Quelltext lautet:

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    AbbruchButton: TBitBtn;
    JahreszahlEdit: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    BitBtn1: TBitBtn;
    EreignisButton: TBitBtn;
    AnleitungButton: TBitBtn;
    ListBox1: TListBox;
    EreignisPanel: TPanel;
    procedure AbbruchButtonClick(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure AnleitungButtonClick(Sender: TObject);
    procedure EreignisButtonClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var Jahreszahl:Integer;
procedure TForm1.AbbruchButtonClick(Sender: TObject);
begin
close
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Jahreszahl:=StrToInt(JahreszahlEdit.Text);


end;

procedure TForm1.AnleitungButtonClick(Sender: TObject);
begin
ShowMessage('Wie funktioniert dieser Trainer?'+#13+'Durch das Klicken auf den Button "Neues Ereignis" wird zufällig ein geschichtliches Ereignis ausgewählt'+#13+ 'und unter dem Wort "Ereignis" angezeigt. Ihre Aufgabe ist es nun die richtige Jahreszahl des angezeigten Ereignisses anzugeben,indem sie die Jahreszahl in das Feld unterhalb der Wörter "Gesuchte Jahreszahl" eingeben.'+#13+'Mit Klick auf den "Ok"-Button bestätigen Sie Ihre Eingabe und Sie werden darüber informiert, ob Ihre Eingabe richtig war.'+#13+'Mit einem erneuten Klick auf den "Neues Ereignis"-Button wird das nächste Ereignis angezeigt.');
end;

procedure TForm1.EreignisButtonClick(Sender: TObject);
var zufall:Integer;



begin

ListBox1.Items.LoadFromFile('TextEreignis.txt');

randomize;
zufall:=random(ListBox1.Items.Count);
EreignisPanel.Caption:=ListBox1.Items.Strings[Zufall];




end;

end.
Wie ist es mir möglich (wenn überhaupt?), dass das Programm feststellt, ob die eingegebene Jahreszahl mit dem zufällig gewählten Ereignis aus der Textdatei übereinstimmt?
Wäre dankbar für eure Denkanstöße! :)

MfG
Soph6297

Perlsau 27. Mai 2014 21:19

AW: Selbstprogrammierung eines Vokabeltrainers
 
Würdest du mal kurz erläutern, was du unter "typisierte Datei" vor dem Lesen der verlinkten Anleitung und dann nochmal kurz, was du nach dem Lesen des Tutorials darunter verstehst? Denn mit einer Listbox eine typisierte Datei laden zu wollen erscheint mir doch etwas arg naiv. Wenn du dem Link folgst, erhältst du eine umfassende Einführung in typisierte Dateien. Dein gezeigter Code ist auf keinen Fall bereit, eine typisierte Datei entgegenzunehmen, denn es fehlt – genau, du hast's erfaßt! – der Record.

Da fällt mir noch ein: Wieso schreibst du nicht ein Programm auf der Basis dessen, was ihr in der Schule gelernt habt? Man erwartet doch sicher nicht von dir, Programmiertechniken einzusetzen, die man dir nicht zuvor beigebracht hat, oder?

Dejan Vu 28. Mai 2014 07:17

AW: Selbstprogrammierung eines Vokabeltrainers
 
Er liest eine Textdatei in eine Listbox ein. Wo ist da das Problem? Die Vorgabe war 'Textdatei oder typisierte Datei'.

Textdateien sind bei einfachen Sachen vorzuziehen, das man sie mit jedem Notepad-Derivat bearbeiten kann.

In deiner Textdatei muss neben dem Text, der das geschichtliche Ereignis beschreibt, auch die Jahreszahl stehen.
Damit das Programm die beiden Werte voneinander unterscheiden kann, sollte man sie markieren, z.B. mit einem Trennzeichen: "1939;Beginn des 2.Weltkrieges"

Damit kannst Du die Daten aber nicht einfach so ins Ereignispanel schreiben, sondern musst vorher Jahr von Ereignis trennen,

Delphi-Quellcode:
// Statt
// EreignisPanel.Caption:=ListBox1.Items.Strings[Zufall];
  TrenneJahrUndEreignis (ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
  EreignisPanel.Caption := Ereignis;
...
'Ereignis' ist eine lokale String-Variable (die musst Du deklarieren, weißt Du, wo?)
'FJahr' ist ein privates Feld. Weißt Du auch, wo du das deklarieren musst?

Im OnClick des OK-Buttons vergleichst Du nun die Jahreszahleinfabe mit dem Feld 'FJahr' und gibst eine entsprechende Meldung aus.

Ach, trennen musst Du ja noch:
Delphi-Quellcode:
Procedure TForm1,TrenneJahrUndEreignis (text : String; Var jahr, ereignis : string);
Begin
  ...
  jahr := ...
  ereignis := ...
End;
Hier wird dir 'Pos' und 'Copy' weiterhelfen, und die Tatsache, das z.B. das Semikolon Jahr und Ereignis trennt.

Mehr Hilfe gibt es aber nicht :-)

DeddyH 28. Mai 2014 07:25

AW: Selbstprogrammierung eines Vokabeltrainers
 
Delphi-Referenz durchsuchenTStrings.Values und Delphi-Referenz durchsuchenTStrings.Names könnten auch hilfreich sein, dann muss man nicht selbst mit Stringfunktionen herumhantieren, sofern die Datei das entsprechende Format hat.

Perlsau 28. Mai 2014 07:29

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Dejan Vu (Beitrag 1260539)
Ach, trennen musst Du ja noch:
Delphi-Quellcode:
Procedure TForm1,TrenneJahrUndEreignis (text : String; Var jahr, ereignis : string);
Begin
  ...
  jahr := ...
  ereignis := ...
End;
Hier wird dir 'Pos' und 'Copy' weiterhelfen, und die Tatsache, das z.B. das Semikolon Jahr und Ereignis trennt.

Mehr Hilfe gibt es aber nicht :-)

Also wenn schon liest man das nicht in eine unsichtbare Listbox ein und trennt dann mühevoll via Pos und Copy, sondern verwendet gleich zwei lokal deklarierte Stringlisten, wovon die eine zur Trennung der Werte der CSV-Datei dient. Das Ergebnis kommt dann in ein entsprechendes Record-Array, so daß Jahr und dazugehörendes geschichtliches Ereignis stets durch dieselbe ID verbunden sind. Auf die ID kann man dann locker einen Zufallsgenertator ansetzen.

DeddyH 28. Mai 2014 08:00

AW: Selbstprogrammierung eines Vokabeltrainers
 
Meine Variante kommt mit einer Stringliste aus.

Dejan Vu 28. Mai 2014 08:14

AW: Selbstprogrammierung eines Vokabeltrainers
 
Wollen wir den Fragesteller weiter verwirren? Ich wollte wirklich seinen unvollkommenen Ansatz nehmen und ihn nur minimalinvasiv in die richtige Richtung stupsen. Wenn er mit Stringlisten ankommt, die sein Lehrer vielleicht nicht auf dem Schirm hat, gibt es vielleicht Probleme. Schon das Einführen einer Prozedur hat mich Überwindung gekostet, denn es gibt ja Programmierer (und Lehrer halten sich dafür), die Prozeduren nur verwenden, um DRY zu vermeiden, aber nicht, um lesbaren Code zu schreiben.

Ich geh jetzt Kollegen ärgern ('Arbeiten').

DeddyH 28. Mai 2014 08:55

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ich meinte mit "Stringliste" nicht zwingend TStringlist, sondern allgemein jeden TStrings-Abkömmling, der die oben genannten Methoden bereitstellt, meinetwegen also auch TListBox.Items.

Soph6297 28. Mai 2014 13:48

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Perlsau (Beitrag 1260510)
Würdest du mal kurz erläutern, was du unter "typisierte Datei" vor dem Lesen der verlinkten Anleitung und dann nochmal kurz, was du nach dem Lesen des Tutorials darunter verstehst? Denn mit einer Listbox eine typisierte Datei laden zu wollen erscheint mir doch etwas arg naiv. Wenn du dem Link folgst, erhältst du eine umfassende Einführung in typisierte Dateien. Dein gezeigter Code ist auf keinen Fall bereit, eine typisierte Datei entgegenzunehmen, denn es fehlt – genau, du hast's erfaßt! – der Record.

Da fällt mir noch ein: Wieso schreibst du nicht ein Programm auf der Basis dessen, was ihr in der Schule gelernt habt? Man erwartet doch sicher nicht von dir, Programmiertechniken einzusetzen, die man dir nicht zuvor beigebracht hat, oder?

Ich arbeite, wie Dejan Vu erkannt hat, mit einer Textdatei. Wir hatten die Auswahl zwischen einer typisierten Datei und einer Textdatei; ich habe mich allerdings für eine Textdatei entschieden, da ich damit besser klar komme.
Es wird zwar von uns erwartet uns bereits bekanntes Wissen anzuwenden, allerdings auch, neues Wissen mit einzubinden, was wir vorher noch nicht behandelt haben.

@ Dejan Vu:
Danke für die bisherige Hilfe;
Zitat:

'FJahr' ist ein privates Feld.
Mh, nein tut mir leid. Ich habe leider keine Idee, wo ich ein privates Feld deklariere; nach implementation?


Also hätte ich jetzt die Möglichkeit entweder mit pos und copy zu arbeiten oder mit einer CSV-Datei (von der ich leider noch nie etwas gehört habe)? Ebenso wenig habe ich Erfahrung mit TString aus.
Lässt es sich denn empfehlen mit Pos und Copy zu arbeiten?

Danke!
MfG

DeddyH 28. Mai 2014 13:58

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ein privates Feld deklariert man im private-Abschnitt der Klasse, zu der es gehören soll. In üblicher Nomenklatur stellt man dem Bezeichner ein F voran. Beispiel:
Delphi-Quellcode:
type
  TDings = class
  private
    FIntwert: integer;
  end;
FIntwert ist somit ein privates Feld vom Typ integer der Klasse TDings. Zu den TStrings: da Du eine Listbox verwendest, hast Du diese TStrings bereits verfügbar, nämlich in deren Items-Eigenschaft.

p80286 28. Mai 2014 14:11

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Soph6297 (Beitrag 1260607)
Also hätte ich jetzt die Möglichkeit entweder mit pos und copy zu arbeiten oder mit einer CSV-Datei (von der ich leider noch nie etwas gehört habe)? Ebenso wenig habe ich Erfahrung mit TString aus.
Lässt es sich denn empfehlen mit Pos und Copy zu arbeiten?

Falsche Fragestellung. Mit
Delphi-Quellcode:
pos()
und
Delphi-Quellcode:
Copy()
und ggf.
Delphi-Quellcode:
Delete()
machst Du zu Fuß das, was schon als Funktionalität in
Delphi-Quellcode:
Tstringlist.DelimitedText
steckt.
Wenn Du den Fußweg nicht beherschst, bist Du bei einem anderen Compiler/Sprache die den "DelimitedText" nicht bietet verloren.

Was CSV angeht hier gibt's einen Einstieg.

Gruß
K-H

DeddyH 28. Mai 2014 14:28

AW: Selbstprogrammierung eines Vokabeltrainers
 
Für gerade einmal 2 Werte je Datensatz finde ich CSV eher kontraproduktiv. Was habt Ihr eigentlich alle gegen Namens-/Wertepaare? Viel einfacher geht es doch kaum noch.
Delphi-Quellcode:
procedure TFormTest.btnTestClick(Sender: TObject);
var
  Items: TStrings; //als Ersatz für die Items der Listbox
  i: integer;
  AName, AValue: string;
begin
  Items := TStringlist.Create;
  try
    //wird ja normalerweise aus der Datei ausgelesen
    Items.Add('Dings=Bums');
    Items.Add('Hau=Ruck');
    Items.Add('Blabb=Blubb');
    Items.Add('Die Frage nach dem Leben, dem Universum und einfach Allem=42');
    for i := 0 to Items.Count - 1 do
      begin
        AName := Items.Names[i];
        AValue := Items.ValueFromIndex[i];
        ShowMessage('Frage: ' + AName + sLineBreak + 'Antwort: ' + AValue);
      end;
  finally
    Items.Free;
  end;
end;

Jumpy 28. Mai 2014 15:07

AW: Selbstprogrammierung eines Vokabeltrainers
 
Nur um das nochmal aufzugreifen und da ich vermute, das der TE als Anfänger evtl. Verständnisschwierigkeiten hat und evtl. in der Schule andere Begrifflichkeiten verwendet werden:

a) In Klassen nennt man was sonst so unter dem Namen Variablen läuft auch Felder, genauso wie man Prozeduren/Funktionen dort Methoden nennt. "Private" Felder heißt dann in dem Zusammenhang noch, dass diese Felder/Variablen nur innerhalb der Klasse sichtbar sind, d.h. benutzt werden können. Wie das im Code aussieht hat DeddyH ja schon gezeigt.

b) Und als Ergänzung zu #12 von DeddyH, bzw. allgemein, ist es vllt. auch hilfreich zu zeigen, wie der Inhalt der Textdatei dann aussehen könnte:

Code:
Dings=Bums
Hau=Ruck
Blabb=Blubb
Die Frage nach dem Leben, dem Universum und einfach Allem=42
bzw. auf die Aufgabe bezogen

Code:
1714=Kartoffelkrieg
1896=1. olymp. Spiele der Neuzeit
2014=Deutschland wird Fußballweltmeister
usw.

DeddyH 28. Mai 2014 15:09

AW: Selbstprogrammierung eines Vokabeltrainers
 
Dazu habe ich allerdings in meinem ersten Post die Doku verlinkt, ein wenig eigene Recherche sollte schon sein ;)

Sir Rufo 28. Mai 2014 15:20

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Jumpy (Beitrag 1260626)
bzw. auf die Aufgabe bezogen
Code:
1714=Kartoffelkrieg
1896=1. olymp. Spiele der Neuzeit
2014=Deutschland wird Fußballweltmeister
usw.

Das wäre aber für die Namens-/Werte-Paare suboptimal, denn jetzt kannst du pro Jahreszahl eine Frage stellen :)

Um gänzlich unabhängig zu sein empfiehlt es sich auf folgende Struktur zu gehen:
Code:
<Frage>;<Antwort>
Der Fragenkatalog kann dann einfach in eine StringListe geladen werden (ist und bleibt ja eine Textdatei) und das Frage-Antwort-Paar kann dann so ausgelesen werden:
Delphi-Quellcode:
type
  TItem = record
   Question : string;
   Answer : string;
  end;

function StrToItem( const AStr : string ) : TItem;
var
  LRow : TStringList;
begin
  LRow := TStringList.Create;
  try
    LRow.Delimiter := ';';
    // LRow.StrictDelimiter := True; // erst ab Delphi xxx
    LRow.DelimitedText := AStr;

    // Diese Prüfung kann man auch weglassen, es knallt sowieso :)
    if LRow.Count < 2
    then
      raise Exception.CreateFmt( 'Ungültiges Format für Frage-Antwort <%s>', [AStr] );

    Result.Question := LRow[0];
    Result.Answer := LRow[1];
  finally
    LRow.Free;
  end;
end;

function GetItem( ACatalog : TStrings; Index : Integer ) : TItem;
begin
  Result := StrToItem( ACatalog[Index] );
end;

Soph6297 13. Jun 2014 12:49

AW: Selbstprogrammierung eines Vokabeltrainers
 
Entschuldigt meine kürzliche Inaktivität.

Zitat:

Zitat von Dejan Vu (Beitrag 1260539)
Er liest eine Textdatei in eine Listbox ein. Wo ist da das Problem? Die Vorgabe war 'Textdatei oder typisierte Datei'.

Textdateien sind bei einfachen Sachen vorzuziehen, das man sie mit jedem Notepad-Derivat bearbeiten kann.

In deiner Textdatei muss neben dem Text, der das geschichtliche Ereignis beschreibt, auch die Jahreszahl stehen.
Damit das Programm die beiden Werte voneinander unterscheiden kann, sollte man sie markieren, z.B. mit einem Trennzeichen: "1939;Beginn des 2.Weltkrieges"

Damit kannst Du die Daten aber nicht einfach so ins Ereignispanel schreiben, sondern musst vorher Jahr von Ereignis trennen,

Delphi-Quellcode:
// Statt
// EreignisPanel.Caption:=ListBox1.Items.Strings[Zufall];
  TrenneJahrUndEreignis (ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
  EreignisPanel.Caption := Ereignis;
...
'Ereignis' ist eine lokale String-Variable (die musst Du deklarieren, weißt Du, wo?)
'FJahr' ist ein privates Feld. Weißt Du auch, wo du das deklarieren musst?

Im OnClick des OK-Buttons vergleichst Du nun die Jahreszahleinfabe mit dem Feld 'FJahr' und gibst eine entsprechende Meldung aus.

Ach, trennen musst Du ja noch:
Delphi-Quellcode:
Procedure TForm1,TrenneJahrUndEreignis (text : String; Var jahr, ereignis : string);
Begin
  ...
  jahr := ...
  ereignis := ...
End;
Hier wird dir 'Pos' und 'Copy' weiterhelfen, und die Tatsache, das z.B. das Semikolon Jahr und Ereignis trennt.

Mehr Hilfe gibt es aber nicht :-)

Um nochmal darauf zurückzukommen - ich habe versucht mich mit all den gegebenen Möglichkeiten vertraut zu machen, finde aber, dass ich mit dieser Variante am besten klar kommen werde, da wir es z.T. auch schon behandelt haben.
Ich hab mich mal dran versucht mit Pos und Copy zu arbeiten, komme allerdings nicht wirklich weiter; Delphi zeigt Fehler an, wo ich weiß, dass es falsch ist, ich aber auf keinen grünen Zweig komme... /:

Delphi-Quellcode:
private
    { Private-Deklarationen }
    FJahr:string;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var Jahreszahl:Integer;
     Datei: file of byte;
     
procedure Trennung(text:String);
var Jahr,Ereignis,Gesucht:String;

begin
AssignFile(Datei,'TextEreignis.txt');
Reset(Datei);
while not eof(Datei) do
begin
 Readln(Datei,Gesucht);
 if pos(';',Datei) > 0 then
 copy (Datei,5,20);
 ...
jahr:=
ereignis:=
end;
Es scheitert bei mir an der Verwendung von Pos und Copy. Ich weiß, wozu man sie benutzt, aber WIE ist mir in diesem Fall unklar. Ich weiß, dass sich in dem Quelltextausschnitt Fehler verstecken und wenn ihr einen findet, würde ich mich freuen, wenn ihr ihn mir nennen würdet.
D.h. ich bräuchte jetzt nochmal einen Anstoß für die richtige Verwendung von Pos und Copy...


@ Sir Rufo;
Wenn ich mit TString arbeiten würde, wo würde ich denn dann in deinem Quelltext den Zugriff auf meine Textdatei unterbringen?


Danke! :)

DeddyH 13. Jun 2014 12:57

AW: Selbstprogrammierung eines Vokabeltrainers
 
Delphi-Quellcode:
const
  FRAGE_ANTWORT = 'Die Frage nach dem Leben, dem Universum und einfach Allem;42';
  TRENNER = ';';
var
  iPos: integer;
  Frage, Antwort: string;
begin
  (* Position des Trennzeichens ermitteln *)
  iPos := Pos(TRENNER, FRAGE_ANTWORT);
  (* Wenn gefunden *)
  if iPos > 0 then
    begin
      (* Von Stringanfang bis ausschließlich Trennzeichen kopieren *)
      Frage := Copy(FRAGE_ANTWORT, 1, iPos - 1);
      (* Nun alles hinter dem Trennzeichen *)
      Antwort := Copy(FRAGE_ANTWORT, iPos + 1);
      ShowMessage('Frage: ' + Frage + sLineBreak + 'Antwort: ' + Antwort);
    end;
end;

Soph6297 13. Jun 2014 13:09

AW: Selbstprogrammierung eines Vokabeltrainers
 
Müsste ich dann für jeden Frage-Antwort Paar so etwas deklarieren?
Oder gibt es einen einfacheren Weg?

DeddyH 13. Jun 2014 13:12

AW: Selbstprogrammierung eines Vokabeltrainers
 
Noch einfacher? Mach aus dem Beispiel eine Funktion oder Prozedur, die kannst Du dann je Zeile abarbeiten. Oder schau Dir mein Beispiel von oben mit den TStrings noch einmal an, das Add() entfällt dabei, da Du die Liste ja dann aus einer Datei befüllst.

Soph6297 13. Jun 2014 13:16

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ich hatte ja schon die procedure Trennung erstellt mit der ich eigentlich arbeiten wollte.
Wenn ich also Zeile für Zeile abarbeiten will, muss ich also immer das, entsprechend der Frage und Antwort, wiederholen?

Delphi-Quellcode:
begin
  (* Position des Trennzeichens ermitteln *)
  iPos := Pos(TRENNER, FRAGE_ANTWORT);
  (* Wenn gefunden *)
  if iPos > 0 then
    begin
      (* Von Stringanfang bis ausschließlich Trennzeichen kopieren *)
      Frage := Copy(FRAGE_ANTWORT, 1, iPos - 1);
      (* Nun alles hinter dem Trennzeichen *)
      Antwort := Copy(FRAGE_ANTWORT, iPos + 1);
      ShowMessage('Frage: ' + Frage + sLineBreak + 'Antwort: ' + Antwort);

DeddyH 13. Jun 2014 13:20

AW: Selbstprogrammierung eines Vokabeltrainers
 
Deine Prozedur Trennung macht aber zuviel, sie sollte wirklich nur einen übergebenen String-Parameter in Frage und Antwort aufteilen.
Delphi-Quellcode:
procedure Trennen(const Eingabe: string; out Frage, Antwort: string);
begin
  (* Hier nun Eingabe auftrennen und Frage und Antwort zuweisen *)
end;

Soph6297 16. Jun 2014 20:22

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ich hab erstmal ein Anfang gewagt...

Delphi-Quellcode:
procedure Trennung(text:String);

const
Frage_Antwort='Rheinbund;1806';
Trenner=';';

var Frage, Antwort:String;
    iPos:integer;

begin
iPos:=Pos(';','Rheinbund;1806');
if iPos > 0 then
 begin
  Frage:=Copy('Rheinbund;1806', iPos+1);
  Antwort:=Copy('Rheinbund;1806', iPos-1);
 ShowMessage('Hier Nachricht eingeben');
 end;
end;
Dazu zwei Fragen...

1)Delphi zeigt mir an, dass es zu wenig wirkliche Parameter gibt - was kann ich dagegen tun?
2)Wozu genau ist die ShowMessage da/welchen Zweck erfüllt sie?

mkinzler 16. Jun 2014 20:52

AW: Selbstprogrammierung eines Vokabeltrainers
 
1) Copy() besitzt 3 Parameter
2) Zeigt eine Meldungsfenster an.

Soph6297 16. Jun 2014 20:57

AW: Selbstprogrammierung eines Vokabeltrainers
 
1) Aber wie kann ich es anders schreiben, dass Delphi "nicht mehr rummotzt"...?
Ich hab als Bsp gefunden:
"s := 'Dies ist ein Test';
COPY(s, 14, 4);
ergibt:
'Test'"
Demnach fehlt bei mir ein Parameter, aber welches? Bzw. was sollen die Zahlen darstellen?
2) Ja, das weiß ich, aber welchen Zweck erfüllt das Meldungsfenster im Zusammenhang mit vorher geschriebenen? Was wird dem Benutzer damit gesagt/soll damit gesagt werden?

mkinzler 16. Jun 2014 21:03

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Soph6297 (Beitrag 1262521)
1) Aber wie kann ich es anders schreiben, dass Delphi "nicht mehr rummotzt"...?

Den fehlenden Parameter ergänzen:
Delphi-Quellcode:
Frage:=Copy('Rheinbund;1806', 1, iPos-1);
2) Ja, das weiß ich, aber welchen Zweck erfüllt das Meldungsfenster im Zusammenhang mit vorher geschriebenen? Was wird dem Benutzer damit gesagt/soll damit gesagt werden?[/QUOTE]
Da musst du den autor fragen.

Soph6297 16. Jun 2014 21:15

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ok danke, dann funktioniert das mit den Parametern soweit! (:
Nun ergeben sich aber zwei weitere "Probleme".

1) Die Zeile
Delphi-Quellcode:
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
weist zu viele Parameter auf. Nämlich FJahr und Ereignis. Müssen die da wirklich rein?

2) Wenn ich, zur Probe, FJahr und Ereignis lösche und das Programm starte und den "Neues Ereignis" Button klicke kommt eine Fehlermeldung von Delphi, dass der Listenindex das Maximum übersteigt. Kann ich das irgendwo eingrenzen, so dass es im Limit bleibt?


Desweiteren bleibt die Frage mit der ShowMessage offen...

Sir Rufo 16. Jun 2014 22:03

AW: Selbstprogrammierung eines Vokabeltrainers
 
Ohne dir zu nahe treten zu wollen, aber du solltest dich dringend mit den Grundlagen von Delphi und auch mit der Benutzung der Online-Hilfe vertraut machen.

Das liest sich wie als ob du das Licht einschalten möchtest und überall drückst, obwohl du nicht weisst, was ein Schalter ist, du aber gehört hast, dass man da wohl was drücken muss.

Delphi-Referenz durchsuchenVcl.Dialogs.ShowMessage
Delphi-Referenz durchsuchenSystem.Copy

Perlsau 16. Jun 2014 22:12

AW: Selbstprogrammierung eines Vokabeltrainers
 
1. In deinem Quelltext oben verfügt die Methode Trennung nur über einen einzigen Parameter. Daran solltest du dich halten.

2. Wenn du ein Array[1..2] hast und du rufst ein Item daraus ab, dessen Index kleiner 1 oder dessen Index größer 2 ist, erzeugt dies einen Fehler, denn es existiert nur der Index 1 und der Index 2. Genauso ist das z.B. bei Stringlisten: Wenn du 15 Items darin hast (0..14] und du rufst z.B: das Item mit dem Index 15 auf, das gar nicht existiert, erzeugst du denselben Fehler: Listenindex übersteigt das Maximum.

3. Kannst du ein wenig Englisch? Ja? Dann weißt du sicher, was show und was message auf deutsch heißen: zeige Nachricht. Und genau das macht die Procedure: Sie zeigt die Nachricht an, die im Parameter übergeben wird.

Dringende Empfehlung: Grundkenntnisse aneignen, Basis-Wissen erlernen, Tutorials durcharbeiten ...

himitsu 16. Jun 2014 22:16

AW: Selbstprogrammierung eines Vokabeltrainers
 
Copy besitzt in aktuelleren Delphis 3 oder 2 Parameter.

Bei 2 Parametern entspricht das dann "Kopiere Alles ab hier, bis zum Ende".

Delphi-Quellcode:
Teil := Copy(S, Start, Anzahl);
Teil := Copy(S, Start {, Length(S) - Start + 1});
Und dann gibt es auch noch Delphi-Referenz durchsuchenLeftStr, Delphi-Referenz durchsuchenRightStr, Delphi-Referenz durchsuchenMidStr, Delphi-Referenz durchsuchenReverseString und einige Funktionen, mit 'nem "ähnlichen" Verhalten wie das Delphi-Referenz durchsuchenPos.

DeddyH 17. Jun 2014 07:20

AW: Selbstprogrammierung eines Vokabeltrainers
 
Alles schon vorgekaut :? Ein Mindestmaß an Eigeninitiative kann man allerdings erwarten.

Soph6297 17. Jun 2014 17:28

AW: Selbstprogrammierung eines Vokabeltrainers
 
Tut mir leid, ich versuche nur zu verstehen, was genau ich programmiere; da frage ich vielleicht zu viel /:

Zitat:

2. Wenn du ein Array[1..2] hast und du rufst ein Item daraus ab, dessen Index kleiner 1 oder dessen Index größer 2 ist, erzeugt dies einen Fehler, denn es existiert nur der Index 1 und der Index 2. Genauso ist das z.B. bei Stringlisten: Wenn du 15 Items darin hast (0..14] und du rufst z.B: das Item mit dem Index 15 auf, das gar nicht existiert, erzeugst du denselben Fehler: Listenindex übersteigt das Maximum.
Ok, das versteh ich!

Ich hab versucht auf den Index der ListBox zuzugreifen:

Delphi-Quellcode:
procedure TForm1.EreignisButtonClick(Sender: TObject);
var zufall:Integer;
     Ereignis:String;


begin

ListBox1.Items.LoadFromFile('TextEreignis.txt');

randomize;
ListBox1.Items.Strings[2];
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
EreignisPanel.Caption:=Ereignis;




end;
Delphi-Quellcode:
ListBox1.Items.Strings[2];
Allerdings wird mir immer noch angezeigt, dass ich das Maximum überschreite.
Müsste ich dann ein Array bei den var einfügen, zB
Delphi-Quellcode:
Ereignis:Array [1..3] of String
?

mkinzler 17. Jun 2014 17:31

AW: Selbstprogrammierung eines Vokabeltrainers
 
Wieviele Zeilen hat die Textdatei?
Das randomize ist hier falsch. Es sorgt dafür, das die Fragen immer iin der selben Reihenfolge gewählt werden.

Soph6297 17. Jun 2014 17:33

AW: Selbstprogrammierung eines Vokabeltrainers
 
Momentan hat die Textdatei 3 Zeilen, es soll aber später möglich sein, die Textdatei um Zeilen zu erweitern.

Oh, ok.
Aber wenn das randomize dort falsch ist, wo muss ich es dann hinschreiben, damit die Fragen/Antworten aus der Textdatei zufällig gewählt werden?

Sir Rufo 17. Jun 2014 17:34

AW: Selbstprogrammierung eines Vokabeltrainers
 
Was für einen Wert hat denn
Delphi-Quellcode:
Zufall
?

Soph6297 17. Jun 2014 17:36

AW: Selbstprogrammierung eines Vokabeltrainers
 
Einen Integer Wert, wenn du das meinst?

Delphi-Quellcode:
var zufall:Integer;
     Ereignis:String;


begin

ListBox1.Items.LoadFromFile('TextEreignis.txt');

randomize;
ListBox1.Items.Strings[2];
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
EreignisPanel.Caption:=Ereignis;

Sir Rufo 17. Jun 2014 17:44

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Zitat von Soph6297 (Beitrag 1262622)
Einen Integer Wert, wenn du das meinst?

Da wäre ich nie drauf gekommen :roll:

Welcher konkrete
Delphi-Quellcode:
Integer
-Wert befindet sich denn in
Delphi-Quellcode:
Zufall
wenn du die Methode
Delphi-Quellcode:
Trennung
aufrufst?

(So wie ich das sehe ist der zufälliger als dir lieb ist)

himitsu 17. Jun 2014 17:54

AW: Selbstprogrammierung eines Vokabeltrainers
 
Zitat:

Delphi-Quellcode:
randomize;
ListBox1.Items.Strings[2];
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);

Randomize darf sollte man nur einmal bei Programmstart aufrufen.

Wozu ist das
Delphi-Quellcode:
ListBox1.Items.Strings[2]
?
Du liest da den 3. Wert aus, machst damit aber nichts. (wird nirgendwo zugewiesen)

Was ist mit Zufall?
Dein Compiler sollte dir da auch sagen, daß du vergessen hast diese Variable zu initialisieren. :!:!
Initialisieren = einen Wert zuweisen (hier z.B. über Delphi-Referenz durchsuchenRandom), bevor man diese Variable ausliest/verwendet.


PS: Bei
Delphi-Quellcode:
ListBox1.Items.Strings[2]
kann man das Strings auch weglassen (
Delphi-Quellcode:
ListBox1.Items[2]
), wenn man möchte,
denn als "Default"-Array-Property baut das Delphi implizit wieder ein.

Soph6297 17. Jun 2014 17:55

AW: Selbstprogrammierung eines Vokabeltrainers
 
Delphi-Quellcode:
zufall:=random(ListBox1.Items.Count);
Wenn ich das allerdings in der procedure aufrufe, kommt die Fehlermeldung, dass ListBox1 undefiniert ist.

Delphi-Quellcode:
procedure Trennung(text:String; var TAntwort,TFrage:String);

const
Frage_Antwort='Rheinbund;1806';
Trenner=';';

var Frage, Antwort:String;
    iPos,zufall:integer;

begin

ListBox1.Items.LoadFromFile('TextEreignis.txt');

randomize;
zufall:=random(ListBox1.Items.Count);
end;

iPos:=Pos(';','Rheinbund;1806');
if iPos > 0 then
 begin
  Frage:=Copy('Rheinbund;1806',0, iPos+1);
  Antwort:=Copy('Rheinbund;1806',0, iPos-1);
 ShowMessage('Hier Nachricht eingeben');
 end;
end;
Packe ich es allerdings in den OnClick vom EreignisButton läuft das Programm, allerdings öffnet sich dann die ShowMessage von der procedure.

Delphi-Quellcode:
procedure TForm1.EreignisButtonClick(Sender: TObject);
var zufall:Integer;
     Ereignis:String;


begin

ListBox1.Items.LoadFromFile('TextEreignis.txt');

randomize;
zufall:=random(ListBox1.Items.Count);
ListBox1.Items.Strings[2];
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
EreignisPanel.Caption:=Ereignis;




end;
Zitat:

Wozu ist das ListBox1.Items.Strings[2] ?
Du liest da den 3. Wert aus, machst damit aber nichts. (wird nirgendwo zugewiesen)
Damit wollte ich (leider vergeblich) versuchen, dass die ListBox nicht an ihr Maximum stößt... Allerdings läuft das Programm jetzt, wo ich Zufall deklariert habe. (Hatte ich irgendwie gelöscht, die zeile....)


Also im Endeffekt: Das Problem mit dem Maximum der ListBox besteht nicht mehr. Allerdings wird noch kein Ereignis im dafür vorgesehenen Panel angezeigt.

Perlsau 17. Jun 2014 19:27

AW: Selbstprogrammierung eines Vokabeltrainers
 
Mein liebes Soph6297, dir fehlen offenbar die einfachsten Grundlagen der Delphi-Programmierung:

Zitat:

Zitat von Soph6297 (Beitrag 1262632)
Wenn ich das allerdings in der procedure aufrufe, kommt die Fehlermeldung, dass ListBox1 undefiniert ist.

Das ist doch völlig normal, daß du von einer Procedure aus, die du nicht als Methode deines Formulars deklarierst, auch keinen Zugriff auf die Komponenten hast, die sich auf diesem Formular befinden. Deklariere die Procedure Trennung im Private-Abschnitt deines Interface-Abschnitts, drücke dann die Tastenkombination Strg-Shift-C und schreibe in den daraufhin erzeugten Procedure-Rumpf deine Implementation.
Delphi-Quellcode:
procedure TForm1.Trennung(text:String; var TAntwort,TFrage:String);
begin
end;
Zitat:

Zitat von Soph6297 (Beitrag 1262632)
Packe ich es allerdings in den OnClick vom EreignisButton läuft das Programm, allerdings öffnet sich dann die ShowMessage von der procedure.

Ist doch klar: Hier stellt die Procedure eine Methode deiner Form-Klasse dar. Du siehst das an dem vorangestellten TForm1.

Zitat:

Zitat von Soph6297 (Beitrag 1262632)
Delphi-Quellcode:
procedure TForm1.EreignisButtonClick(Sender: TObject);
var zufall:Integer;
     Ereignis:String;
begin
ListBox1.Items.LoadFromFile('TextEreignis.txt');
randomize;
zufall:=random(ListBox1.Items.Count);
ListBox1.Items.Strings[2];
Trennung(ListBox1.Items.Strings[Zufall], FJahr, Ereignis);
EreignisPanel.Caption:=Ereignis;
end;
Also im Endeffekt: Das Problem mit dem Maximum der ListBox besteht nicht mehr. Allerdings wird noch kein Ereignis im dafür vorgesehenen Panel angezeigt.

An dieser Stelle möchte ich dir noch einmal empfehlen, mindestens ein, besser mehrere Anfänger-Tutorials sorgfältig durchzuarbeiten. Wollte man dir deinen ganzen Kot Code korrigieren, käme das beinahe dem Schreiben eines Tutorials nahe, und dazu hab zumindest ich keine Lust. Du stocherst da wie wild in deinem Programmcode herum und hoffst, irgendwo ein Korn zu finden. So wird das nix. Da hilft auch kein Code-Korrigieren und -Liefern, denn offensichtlich begreifst du nicht wirklich, warum dies und jenes ein Fehler ist. Noch ein Hinweis: Formatiere deinen Code, arbeite zumindest mit Einrückungen, das kann doch sonst keiner lesen!

Soph6297 21. Jun 2014 17:20

AW: Selbstprogrammierung eines Vokabeltrainers
 
An dieser Stelle Danke an eure Hilfe, schlussendlich läuft das Programm jetzt wie geplant. :)

MfG


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz