Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Liste von Namen auf Charakteristiken überprüfen (https://www.delphipraxis.net/170464-liste-von-namen-auf-charakteristiken-ueberpruefen.html)

diavy 18. Sep 2012 17:20

Liste von Namen auf Charakteristiken überprüfen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen, wiedermal habe ich ein Problem.

Es geht um folgendes:
Ich soll ein Programm schreiben, bei dem eine Liste von Namen auf 2 Sachen überprüft werden sollen:
a) ob sie mit einem/r ausgewählten Buchstaben/Buchstabenkombination beginnen
b) ob kein genannter Buchstabe im Namen vorkommt

Jene Namen die die ausgewählte Bedingung erfüllen, sollen dargestellt werden.

Ich habe zu erst das Programm ohne die "Liste" geschrieben, sprich nur mit einem Namen, um zu überprüfen ob ich das mit den Bedingungen hinbekommen. Das hat 1A geklappt.
Nun hänge ich jedoch an der "Liste". Ich habe die Variablen die von mehreren Objekten benutzt werden sollen unter "public" deklariert, da ich mir dadurch erhofft habe, sie würden global werden (was ja Pflicht sein sollte wenn mehrere Objekte drauf zugreifen sollen, oder?).

Irgendetwas haut trotzdem nicht hin.


Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    edt_name: TEdit;
    Label1: TLabel;
    Button1: TButton;
    edt_start: TEdit;
    lbl_name: TLabel;
    lbl_letter: TLabel;
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    i:integer;name:array of string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.RadioButton1Click(Sender: TObject);
var error:boolean; j,l:integer; word:string;
begin
for l:=1 to i do
        begin
        word:=name[l];
        error:=false;
        for j:=1 to Length(word) do
                if edt_start.Text[j]<>word[j] then error:=true;
        if error=false then label1.Caption:=Label1.Caption + word
        else Label1.Caption:=label1.Caption + '';
        end;
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
var error:boolean; j,k,l:integer; word:string;
begin
for l:=1 to i do
        begin
        word:=name[l];
        error:=false;
        for j:=1 to Length(edt_start.Text) do
                for k:=1 to Length(word) do
                        if edt_start.text[j]=word[k] then error:=true;
        if error=true then Label1.Caption:=Label1.Caption+''
        else Label1.Caption:=Label1.Caption + word
        end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
SetLength(name,(i+1));
name[i]:=edt_name.Text;
inc(i);
edt_name.text:='';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i:=1;
end;

end.
Wär nett wenn mir wieder wer helfen könnte. :)

mkinzler 18. Sep 2012 17:23

AW: Liste von Namen auf Charakteristiken überprüfen
 
a) Pos() = 1
b) Pos()

Jumpy 18. Sep 2012 17:46

AW: Liste von Namen auf Charakteristiken überprüfen
 
Nur als Tips:

Mit High(Array) / Low(Array) kann man obere und untere Grenze eines Array ermitteln und dieses mit
for i:=Low(Array) to High(Array)
durchlaufen. Damit könntest du dir die Variable i sparen.

Und der Vergleich if error=true / if error=false ist unschön und doppeltgemoppelt (und birgt auch eine Fehlerquelle, auch wenn ich die trotz der vielen Erklärungen die an dieser Stelle immer kommen, nicht verstanden habe).
if error then reicht vollkommen bzw. if not error then.
Liest sich doch auch schöner.

Die Access Violation klingt danach, das auf ein nicht vorhandenen Array-Element zugegriffen wird. Ich glaube da du immer nach dem hinzufügen eines neuen Namens schon ein Inc(i) machst, bist du mit dem Zähler um eines zu hoch.

DeddyH 18. Sep 2012 17:55

AW: Liste von Namen auf Charakteristiken überprüfen
 
Zitat:

Zitat von Jumpy (Beitrag 1183454)
(und birgt auch eine Fehlerquelle, auch wenn ich die trotz der vielen Erklärungen die an dieser Stelle immer kommen, nicht verstanden habe)

Ganz einfach: False ist mit 0, True mit 1 deklariert (die Konstanten meine ich). Der Unterschied zwischen
Delphi-Quellcode:
if Dings = true then
und
Delphi-Quellcode:
if Dings then
liegt darin, dass die erste Variante auf 1, die zweite aber auf <> 0 prüft. Von daher kann man also genausogut schreiben
Delphi-Quellcode:
if Dings <> false
, aber das sieht irgendwie *bäh* aus, oder nicht? ;)

mkinzler 18. Sep 2012 17:59

AW: Liste von Namen auf Charakteristiken überprüfen
 
Genaugenomnmen ist False 0 und True <> 0. Das macht einen Vergleich auf True noch gefährlicher, da bei Delphi True 1 ist und bei (der) Windows (API) -1 ( Komplement). hat man nun ein False veiner Funktion der API und vergleicht diese gegen die Konstante kommt was Falsches raus. Deshalb sollte man nie auf True Prüfen!

Uwe Raabe 18. Sep 2012 17:59

AW: Liste von Namen auf Charakteristiken überprüfen
 
Die Access-Violation kommt, da nach dem SetLength(name, I+1) ein Inc(I) kommt. Der Array Index beginnt immer bei 0, daher ist ein Zugriff auf name[I] immer außerhalb der Arraygrenzen. Wenn du das Range-Checking eingeschaltet hättest, wäre die Fehlermeldung auch hilfreicher.

Unschön: Die Verwendung von "name", da TForm bereits ein Property "Name" hat, und "word" ist ein Datentyp. Die Delphi-Syntax lässt das zwar zu, aber es verwirrt eigentlich nur.

Warum schreibst du nicht eine Prozedur, die ein einzelnes Wort überprüft, und diese fütterst du dann in einer Schleife mit den einzelnen Listenelementen?

DeddyH 18. Sep 2012 18:07

AW: Liste von Namen auf Charakteristiken überprüfen
 
Zitat:

Zitat von mkinzler (Beitrag 1183457)
Genaugenomnmen ist False 0 und True <> 0. Das macht einen Vergleich auf True noch gefährlicher, da bei Delphi True 1 ist und bei (der) Windows (API) -1 ( Komplement). hat man nun ein False veiner Funktion der API und vergleicht diese gegen die Konstante kommt was Falsches raus. Deshalb sollte man nie auf True Prüfen!

Ich schrieb ja, dass ich die Delphi-Konstanten meine :zwinker:

mkinzler 18. Sep 2012 18:09

AW: Liste von Namen auf Charakteristiken überprüfen
 
Ich habe dich ja nicht verbessert, sondern deine Ausführungen etwas vertieft.

DeddyH 18. Sep 2012 18:12

AW: Liste von Namen auf Charakteristiken überprüfen
 
Wir können das am Freitag bei einem Bierchen ja vertiefen :lol:

p80286 18. Sep 2012 18:40

AW: Liste von Namen auf Charakteristiken überprüfen
 
Das ist zuviel des Guten:
Delphi-Quellcode:
for j:=1 to Length(word) do
                if edt_start.Text[j]<>word[j] then error:=true;
ich würde das verwenden:
Delphi-Quellcode:
error:=false;
j:=0;
repeat
  inc(j,1);
  if if edt_start.Text[j]<>wort[j] then error:=true;
until (j>=length(wort)) or error;
und wort statt word, da word ein Typ ist.

Gruß
K-H

DeddyH 18. Sep 2012 18:42

AW: Liste von Namen auf Charakteristiken überprüfen
 
"if if" ist aber auch zuviel des Guten (SCNR^^)

p80286 18. Sep 2012 18:45

AW: Liste von Namen auf Charakteristiken überprüfen
 
Oh man, wird Zeit nach Haus zu gehen:oops:

Gruß
K-H

diavy 21. Sep 2012 17:30

AW: Liste von Namen auf Charakteristiken überprüfen
 
Tut mir leid dass ich so lange gebraucht habe um zu antworten, mir ist einiges dazwischen bekommen.

Zunächst einen großen Dank an euch alle, wiedermal gab es schnelle, viele und vor allem sehr nützliche Antworten. :)

Ich habe versucht mir so viel als mögliche Ratschläge zu Herzen zu nehmen und das hat sich mehr als ausgezahlt, da der Code übersichtlicher wurde, und vor allem jetzt hinhaut. :D

Hier mein jetziger Code (wenn es noch Dinge auszusetzen gibten, lass es mich wissen):

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    edt_name: TEdit;
    Label1: TLabel;
    Button1: TButton;
    edt_start: TEdit;
    lbl_name: TLabel;
    lbl_letter: TLabel;
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    i,counter:integer;firstname:array of string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function checkifstarting(a,b:string):boolean;
var i:integer;
begin
result:=true;
for i:=1 to Length(a) do
                if a[i]<>b[i] then result:=false;
end;

function checkifwithout(a,b:string):boolean;
var i,k:integer;
begin
result:=true;
for i:=1 to Length(a) do
                for k:=1 to Length(b) do
                        if a[i]=b[k] then result:=false;
end;

procedure TForm1.RadioButton1Click(Sender: TObject);
var l:integer;
begin
Label1.Caption:='';
for l:=low(firstname) to high(firstname) do
        if checkifstarting(edt_start.Text,firstname[l])=true then Label1.Caption:=Label1.Caption + ' ' + firstname[l]
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
var l:integer;
begin
label1.Caption:='';
for l:=low(firstname) to high(firstname) do
        if checkifwithout(edt_start.Text,firstname[l])=true then Label1.Caption:=Label1.Caption + ' ' + firstname[l]
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if counter <>0 then inc(i);
SetLength(firstname,i+1);
firstname[i]:=edt_name.Text;
edt_name.text:='';
inc(counter);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i:=0;
counter:=0;
end;

end.
Eine Frage stelle ich mir noch, wenn ich zB ein Mal das Programm mit 4 Namen benutze, und ein ander Mal 2 Namen verwende, habe ich ja eigentlich nur die 2 ersten Plätze im Array neu "belegt". Wenn ich dann auf den array zugreifen lasse zB mit high(array), hat das Programm dann nicht noch die 2 weiteren Namen (die nicht überschrieben wurden) gespeichert und greift auf diese zu obwohl sie nicht zu dem Zeitpunkt eingegeben wurden?

p80286 21. Sep 2012 17:55

AW: Liste von Namen auf Charakteristiken überprüfen
 
Zitat:

Zitat von diavy (Beitrag 1183907)
Eine Frage stelle ich mir noch, wenn ich zB ein Mal das Programm mit 4 Namen benutze, und ein ander Mal 2 Namen verwende, habe ich ja eigentlich nur die 2 ersten Plätze im Array neu "belegt". Wenn ich dann auf den array zugreifen lasse zB mit high(array), hat das Programm dann nicht noch die 2 weiteren Namen (die nicht überschrieben wurden) gespeichert und greift auf diese zu obwohl sie nicht zu dem Zeitpunkt eingegeben wurden?

Äh, Ja! Nein!
Hab ich es übersehen, oder fehlt es wirklich, woher sollen denn die Inhalte für Firstname/Name kommen?
Es ist Deine Sache, ob Du vor dem Füllen des Arrays, erst einmal eine Löschung durchführst und ggf in einer Variablen die maximale Belegung zu finden ist.

Wenn Du im weitesten Sinne mit Text umgehen willst, kann ich Dir nur die Stringlist/Strings empfehlen.
(meiner Meinung nach die letzte echte Innovation)

Warum muß jeder für irgendwelche Problemlösungen mindestens ein Array am besten noch ein dyn. Array benutzen??????

Es wäre nicht schlecht wenn Du Dir das Formatieren Deines Quelltextes angewöhnen könntest. Der kann dadurch nur gewinnen, und im allg. ist er dann auch schneller zu erfassen.

Gruß
K-H

P.S.
ich weiß, daß die Stringlist im innersten ein Array of pointer ist, und da soll er auch bleiben.

diavy 21. Sep 2012 20:51

AW: Liste von Namen auf Charakteristiken überprüfen
 
Der Wert wird mit "procedure TForm1.Button1Click(Sender: TObject);" gegeben.

Und meine Befürchtung hat sich nicht bestätigt, der Array wird zurückgesetzt. :)

Das mit Stringlist/String werde ich mal googlen.

Was ist denn so verstörend an einem dynamischen Array?

Und das tu ich wie?


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:08 Uhr.

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