Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - for-in-Schleife
noo.bee - So 13.06.10 16:45
Titel: for-in-Schleife
folgende überlegung habe ich:
ich habe in einem memo knapp 1000 zeilen mit zahlen belegt. gegeben werden die variablen a - f durch benutzereingaben in ein edit-feld.
jetzt soll jede memozeile geprüft werden, wie oft in ihr der inhalt des edit-feldes vorkommt
bsp:
memo.lines:
1 4 6 2 8 7 5
2 4 5 7 9
1 3 5
inhalt der edit.felder
feld1 "3"
feld2 "7"
feld3 "1"
alle edit-felder werden nun mit jeder memozeile nacheinander abgeglichen. das ergebnis wäre also:
1. memo.line: 2 (treffer)
2. memo.line: 1 (treffer)
3. memo.line: 2 (treffer)
meine for-in schleife würde dann so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm2.Button1Click(Sender: TObject); var x1 : Integer; begin
for (a=strtoint(memo1.lines.text)) or (b=strtoint(memo1.lines.text)) or (c=strtoint(memo1.lines.text)) in Memo1.Lines do begin inc(x1);
end; |
warum bekomme ich folgende fehler ?
erwartet: Bezeichner, aber ( erhalten
erwartet: END, aber DO erhalten
erwartet: ., aber ; erhalten <-- das verschwindet, sobald ich das "end;" lösche, welches ich doch aber bei jedem "begin" brauche, oder ?
ALF - So 13.06.10 16:55
Hi
Delphi-Quelltext
1: 2: 3: 4:
| for (a:=strtoint(memo1.lines.text)) or (b:=strtoint(memo1.lines.text)) or (c:=strtoint(memo1.lines.text)) in Memo1.Lines do begin inc(x1) end; |
erst mal so gesehen :wink:
Gruss Alf
noo.bee - So 13.06.10 17:04
denk ich grad falsch ? wollte nix zuweisen sonder vergleichen, deshalb nur "=" statt ":="
ALF - So 13.06.10 17:18
Ich glaube vergleichen macht man mit if
In einer For schleife kanst du links nur was zuweisen also
Delphi-Quelltext
1: 2: 3: 4: 5:
| For a := 1 to 100 do begin if (a = 50) or (a = 70) then exit; end; |
Was anderes habe ich bis jetzt noch nicht gesehen
Ansonsten musst Du ne
While schleife nehmen. Dort kanst Du auch vergleichen!
oder
Delphi-Quelltext
1: 2: 3: 4:
| if (a=strtoint(memo1.lines.text)) or (b=strtoint(memo1.lines.text)) or (c=strtoint(memo1.lines.text)) in Memo1.Lines then begin inc(x1); end; |
Gruss ALf
jaenicke - So 13.06.10 18:20
ALF hat folgendes geschrieben : |
In einer For schleife kanst du links nur was zuweisen also |
Falsch, seit den Spracherweiterungen mit Turbo Delphi / Delphi 2006 geht auch das:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var c: Char; MyString: string; begin MyString := 'abc'; for c in MyString do if c in ['1', '3'] then ... |
Die Kombination wie oben verstehe ich allerdings nicht, man kann so "nur" alle Elemente einer Menge durchgehen, mehr nicht.
ALF - So 13.06.10 18:34
Sorry @
jaenicke Ich bezog dies auf
Delphi-Quelltext
1:
| for (a=...) or (b=...) |
Hab mich wieder mal blöd ausgedrückt :oops:
Gruss Alf
noo.bee - So 13.06.10 18:50
Zitat: |
man kann so "nur" alle Elemente einer Menge durchgehen, mehr nicht. |
wie lässt sich denn jede zeile durchsuchen und von jeder zeile das ergebnis ausgeben ? oder kann ich memo nur komplett durchsuchen und die gesamtsumme ausgeben lassen ? das wäre natürlich mächtig blöd :/
jaenicke - So 13.06.10 18:55
Die Frage ist vor allem, ob es grundsätzlich einstellige Zahlen sind oder auch mehrstellige vorkommen können.
Denn wenn es nur einstellig sein kann, dann reicht es zeichenweise zu arbeiten.
noo.bee - So 13.06.10 19:19
mhhh, es können zahlen von 1-99 vorkommen... also leider auch zweistellig
jaenicke - So 13.06.10 19:55
Dann würde ich bei der geringen Anzahl an Zeilen einfach den trivialen Weg ohne Optimierung gehen und in jeder Zeile mit Pos nach jeder Zahl suchen.
Dabei muss auch beachtet werden, dass in mehrstelligen Zahlen nicht Teile als eine Zahl erkannt werden. Dafür können zum Beispiel die Leerzeichen einbezogen werden.
noo.bee - Mo 14.06.10 17:27
ist POS nicht zur berechnung der position eines strings da ? versteh da nicht ganz, wie mir das bei meinem prob helfen soll :shock:
Tropby - Mo 14.06.10 20:29
Du kannst doch so suchen, ob die Zeichen (Zahlen) in der Zeile vorkommen. Wenn Pos größer 0 ist dann kommt er in der Zeile vor.
Delphi-Quelltext
1: 2: 3:
| for i := 0 to Memo.Lines.Count - 1 do if(pos('1', Memo.Lines[I]) > 0)then inc(x); |
Wenn jetzt eine Zahl aber öfters vorkommen kann in einer Zeile dann musst du das auch noch beachten.
noo.bee - Mo 14.06.10 21:02
also in den zeilen kommen keine zahlen doppelt vor. aber muss ich jetzt für a, b, c, d, e und f jedesmal
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| var a, b, c, d, e, f, x1 : Integer; var I: array[1..1000] of integer; begin for a := 0 to Memo1.Lines.Count - 1 do if(pos('1', Memo1.Lines[I]) > 0)then inc(x1); end; |
schreiben ?
ZeitGeist87 - Mo 14.06.10 21:29
Meine Damen und Herren,
nach langer Zeit mal wieder ein (hoffentlich) sinnvoller Post von mir.
Du deklarierst dir ein
Array of Integer.
Dieses ist dynamisch und entspricht der Länge der Zeilen deines Memos.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| var meineTreffer: array of Integer; def_a, def_b, def_c, def_d, def_e, def_f: String; Treffer: Integer; Zeile: String; i: Integer; begin; setlength(meineTreffer, 0); setlength(meineTreffer, meinMemo.Lines.Count);
def_a:= edit_a.text; def_b:= edit_b.text; def_c:= edit_c.text; def_f:= edit_f.text;
Treffer:= 0;
for i:= 0 to meinMemo.Lines.Count-1 do begin Zeile:= meinMemo.Lines[i]; if length(Zeile) <= 0 then begin meineTreffer[i]:= 0; continue; end; if pos(def_a, Zeile) then inc(Treffer);
if pos(def_b, Zeile) then inc(Treffer);
if pos(def_f, Zeile) then inc(Treffer);
meineTreffer[i]:= Treffer; Treffer:= 0; end;
for i:= low(meineTreffer) to high(meineTreffer) do begin meinMemo.lines.clear; meinMemo.lines.add('Zeile ' + inttostr(i+1) + ': ' + IntToStr(meineTreffer[i]) + ' Treffer');
end; end; |
Geschafft. Ausm Kopf. Hoffentlich funktionstüchtig.
Guten Abend.
Stefan
noo.bee - Mi 16.06.10 18:22
huu, erstmal danke für die hilfe. habs mal durchgeackert. sieht soweit gut aus ausser dass
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| if <span style="color: orange">pos(def_a, Zeile)</span> then inc(Treffer);
if <span style="color: orange">pos(def_b, Zeile)</span> then inc(Treffer);
if <span style="color: orange">pos(def_f, Zeile)</span> then inc(Treffer); |
alle nicht boolean sind
Jakob_Ullmann - Mi 16.06.10 18:27
pos() gibt nur den Index des gesuchten Zeichens im String zurück. Du könntest schreiben if pos(...) > 0 then, denn wenn das Zeichen nicht vorkommt, ist pos() null.
ZeitGeist87 - Mi 16.06.10 18:27
noo.bee hat folgendes geschrieben : |
huu, erstmal danke für die hilfe. habs mal durchgeackert. sieht soweit gut aus ausser dass
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| if <span style="color: orange">pos(def_a, Zeile)</span> then inc(Treffer);
if <span style="color: orange">pos(def_b, Zeile)</span> then inc(Treffer);
if <span style="color: orange">pos(def_f, Zeile)</span> then inc(Treffer); |
alle nicht boolean sind |
Mea maxima culpa!
Natürlich ist die Rückgabe von
pos() ein Integer.
Somit musst du prüfen
if pos(def_a, zeile) > 0 then
Aber durch Lesen der Hilfe... :P
noo.bee - Mi 16.06.10 20:54
ja passt ;) habs durch probieren auch hinbekommen mit > 0. aber leider spuckt er mir immer nur die treffer der letzten zeile aus :(
ZeitGeist87 - Mi 16.06.10 20:59
Magst du mal bitte deinen Code posten? ;-)
noo.bee - Mi 16.06.10 21:10
ist eig. dein funktionierender code. hab nur sachen geändert wie die richtigen edits oder memos und sowas
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88:
| procedure TForm2.Button1Click(Sender: TObject); var meineTreffer: array of Integer; def_a, def_b, def_c, def_d, def_e, def_f: String; Treffer: Integer; Zeile: String; i: Integer; begin setlength(meineTreffer, 0);
setlength(meineTreffer, Memo1.Lines.Count);
def_a:= edit1.text; def_b:= edit2.text; def_c:= edit3.text; def_d:= edit4.text; def_e:= edit5.text; def_f:= edit6.text;
Treffer:= 0;
for i:= 0 to Memo1.Lines.Count-1 do begin Zeile:= Memo1.Lines[i];
if length(Zeile) <= 0 then begin meineTreffer[i]:= 0; continue; end;
if pos(def_a, Zeile) > 0 then inc(Treffer);
if pos(def_b, Zeile) > 0 then inc(Treffer);
if pos(def_c, Zeile) > 0 then inc(Treffer);
if pos(def_d, Zeile) > 0 then inc(Treffer);
if pos(def_e, Zeile) > 0 then inc(Treffer);
if pos(def_f, Zeile) > 0 then inc(Treffer);
meineTreffer[i]:= Treffer;
Treffer:= 0; end;
for i:= low(meineTreffer) to high(meineTreffer) do begin Memo2.lines.clear; Memo2.lines.add('Zeile ' + inttostr(i+1) + ': ' + IntToStr(meineTreffer[i]) + ' Treffer');
end; end; end. |
ZeitGeist87 - Mi 16.06.10 21:15
Entweder bin ich blind, blöd oder es liegt daran, dass ich seit heute Kontaktlinsen tragen: Ich finde gerade keinen Fehler.
Würde es dir was ausmachen, das Projekt anzuhängen und eine Datei?
Falls du es nicht öffentlich machen willst, gern auch per PN.
LG
Stefan
---
Moderiert von
Narses: Beiträge zusammengefasst---
Ganz einfach :)
Geh runter zur Ausgabe und such diese Zeilen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| for i:= low(meineTreffer) to high(meineTreffer) do begin Memo2.lines.clear; Memo2.lines.add('Zeile ' + inttostr(i+1) + ': ' + IntToStr(meineTreffer[i]) + ' Treffer');
end; |
Du bist in einer Schleife und leerst bei jedem Durchlauf das Memo2 :)
Setz das
.clear einfach vor die Schleife.
LG
Stefan
noo.bee - Mi 16.06.10 22:19
tja dann würde ich sagen, dass du das prob gelöst hast ;) DANKEEEEE
ZeitGeist87 - Mi 16.06.10 22:20
Da macht sich Erleichterung in mir breit und ich kann nun ruhigen Gewissens mich meinem Lesestoff widmen :)
Viel Spaß damit und gute Nacht.
noo.bee - Do 17.06.10 20:27
so, programm ausgiebig getestet ;) ABER ich habe folgendes festgestellt: der suchlauf berücksichtigt nicht, ob nach ein- oder zweistelligen zahlen gesucht werden sollen.
wenn ich also die zahlenkombi "1, 23, 4, 6, 11, 15, 19" nach der "1" durchsuche, müßte das ergebnis eigentlich 1 sein, da die "1" ja nur einmal drin ist. ich bekomm aber das ergebnis "5" wegen der "11" und der "15" und der "19".
ZeitGeist87 - Do 17.06.10 20:51
Da hast du recht :)
Du könntest eine StringList einbauen, den Delimiter auf Leerzeichen stellen und die Zeile so aufsplitten lassen.
Dann musst du die StringList durchgehen und hättest das Problem gelöst.
Anderer Ansatz: Du prüfst, ob vor oder nach der Position ein Leerzeichen ist. Wenn ja, erhöhen ansonsten ignorieren.
Pass aber auf, wenn du ganz am Anfang bei jeder Zeile bist.
String geht bei 1 los. 1-1 (davor) = 0 = Zugriffsverletzung.
LG
Stefan
noo.bee - Do 17.06.10 20:58
was, wie ? nochmal für mich zum mitschreiben... also ich versteh beide möglichkeiten nicht :( hast noch eine, die ich auch hinbekomm :wink:
ZeitGeist87 - Do 17.06.10 21:15
Entschuldige. :)
Ich würde dir die zweite Möglichkeit ans Herz legen.
Im Moment haben wir es so *Ich such mal den Quelltext*
Ah.
Wir suchen einfach mit
pos() das Vorkommen der Zahl, unabhängig davon, ob ein- oder zweistellig.
Ich würde vorschlagen, wir basteln jetzt einfach eine Funktion, die uns die Arbeit abnimmt. Vorteil: Einmal etwas Aufwand und dann nur eine Zeile :)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
| function checkVorkommen(Zeile, Zahl: String): Boolean; var _pos: Integer; _len: Integer; begin; try result:= false; _pos:= pos(Zahl, Zeile); _len:= length(Zeile);
case _pos of 1: begin if (_pos+length(Zahl)) <= _len then begin if not (Zeile[_pos+length(Zahl)] = #32) then exit; end; end; else begin if _pos-1 < 1 then exit; if _pos = _len then begin if Zeile[_pos-1] <> #32 then exit; end;
if _pos+length(Zahl) <= _len then begin if (Zeile[_pos-1] <> #32) or (Zeile[_pos+length(Zahl)] <> #32) then exit; end else begin if Zeile[_pos-1] <> #32 then exit; end; end; end;
result:= true; except on e: exception do messagebox(application.handle, pchar(e.message), pchar('Fehler'), MB_IconERROR); end; end; |
Im bisherigen Quelltext entfallen die Zeilen
if pos(def_a, zeile) > 0 then und werden durch
Delphi-Quelltext
1: 2:
| if checkVorkommen(Zeile, def_a) then inc(Treffer); |
ersetzt.
Ich hoffe, ich hab es ohne Logikfehler getippt.
LG
Stefan
Edit: Zur Sicherheit bau ich mir schnell ein Testprogramm
Edit die Zweite: Bekannter Bug: Da immer nur das erste Vorkommende Zeichen relevant ist, werden spätere, einstellige in der gleichen Zeile nicht gefunden.
Bsp.:
45 36 8 3 6 und nach 6 wird gesucht: Findest Position 4, ist aber fehlerhaft, da davor kein Leerzeichen. 6 an letzter Position wird nicht mehr gefunden.
Wie kompensieren: An entsprechender Stelle einen weiteren
pos()-Aufruf in einem
REPEAT...UNTIL suchpos = _len;
noo.bee - Fr 18.06.10 18:14
bekannter bug ? also bei mir läufts ohne prob. oder hab ich den fehler nicht gefunden ?
ich hab nirgends "An entsprechender Stelle einen weiteren pos()-Aufruf in einem REPEAT...UNTIL suchpos = _len;" eingefügt
EDIT: doch n fehler gefunden. schau mal auf den screenshot. warum hab ich in zeile 1 keinen treffer ? dort wäre doch die "1" vorhanden :/
ZeitGeist87 - Fr 18.06.10 18:24
Ist mir gestern aufgefallen, als ich das Testprogramm schnell geschrieben hab.
Wie gesagt, nimm meine Zahlenreihe: {code]45 36 8 3 6[/code]
Füg in def_a (edit1.text) 6 ein und die restlichen Felder 0 oder leer lassen.
Klick auf auswerten.
Wir rutschen dann in die Routine des Auswertens herein und dort passiert folgendes.
Über pos('6', '45 36 8 3 6') wird die Position 5 ausgegeben, da die 6 das erste Mal bei 36 auftaucht.
Nun ist diese Position mitten in der Zeichenkette und es wird geprüft, ob davor und danach ein Leerzeichen ist. Ist jedoch nicht der Fall, also kein Treffer.
Und genau da müsste die zeichenweite Suche ansetzen, dass du den String von der gefundenen Stelle bis zum Schluss durchläufst, um wirklich sicher zu sein :)
Das ist der Bug.
Zu deinem Edit: Ich tipp es mal bei mir ein und analysier :)
ZeitGeist87 - Fr 18.06.10 18:31
Konnte keinen Fehler feststellen.
Screenshot anbei
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!