Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Zahlen finden mit Pos


D. Annies - Sa 25.02.12 08:38
Titel: Zahlen finden mit Pos
Hi, Delpher,

wie kann ich mit Pos auch die Zahl 0 oder 2 oder 3 finden?


Delphi-Quelltext
1:
2:
PosZahl := Pos('1', sRecord);                  // 2. Finde die erste / nächste Zahl
  if PosZahl > 0 then ...



Danke, Detlef


Delete - Sa 25.02.12 10:23

Wieso glaubst du, daß das Auffinden eines anderen Teilstrings sich von der oben dargestellten Methode unterscheiden müsse?
Gehe ich recht in der Annahme, daß dir nicht so ganz klar ist, was der Befehl POS macht?
Ich weiß zwar nicht, wie du sRecord deklariert hast, aber mit POS kann man keine Records durchsuchen, sondern lediglich Strings.
Normalerweise sollte man Variablennamen so wählen, daß man leicht auf ihren Variablentyp schließen kann ...


Xion - Sa 25.02.12 10:52

user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Normalerweise sollte man Variablennamen so wählen, daß man leicht auf ihren Variablentyp schließen kann ...

Ich vermute deßhalb steht da auch ein s bei sRecord ;)

Pos: http://delphi.about.com/od/beginners/l/blrtlPos.htm


rushifell - Sa 25.02.12 12:44

Hallo,

hier eine Möglichkeit wie Du herausfindest, ob es sich bei dem Buchstaben um eine Zahl handelt oder nicht:

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:
//Position der Nummer
Function PosNumber(s:AnsiString):Integer;
Var i:Integer;
Begin
 Result:=0;
 For i:=1 to Length(s) do 
     IF s[i] in ['0'..'9'then
        BEGIN
         Result:=i;
         Break;
        END;
End;


procedure TForm1.Button1Click(Sender: TObject);
Var i:Integer;
    s:AnsiString;
begin
 s:='Test01';
 Repeat
  i:=PosNumber(s);
  IF i>0 then
     BEGIN
      ShowMessage(s[i]);
      Delete(s,i,1);
     END;
 Until i=0;
end;

Vielleicht suchst Du so etwas?

Viele Grüße


Delete - Sa 25.02.12 17:14

user profile iconXion hat folgendes geschrieben Zum zitierten Posting springen:
Ich vermute deßhalb steht da auch ein s bei sRecord ;)


Und was sagt das deiner Ansicht nach über den Variablentyp aus?


Xion - Sa 25.02.12 17:37

s wie String?


jaenicke - Sa 25.02.12 18:02

Das nennt sich ungarische Notation und ist in Delphi nicht üblich. Für Komponenten macht diese durchaus Sinn, weil man diese dann beim Schreiben von Code deutlich schneller findet. Für alle anderen Bezeichner braucht man das aber nicht, denn wenn man so viele Variablen und/oder so lange Codeabschnitte hat, dass das nötig wäre, hat man ganz andere Probleme. ;-)


D. Annies - Sa 25.02.12 21:00

@all:

vielen, vielen Dank für eure Mühe und Ideen,
XION hat recht, s von sRecord steht für String, hat mal einen Record aus einer .CSV aufgenommen.
Hätte ich besser schon mal anders benennen sollen. SCUSI.

Ich hatte überlegt in Richtung Fallunterscheidung. Gibt es da eine Idee?

Danke, Detlef


jaenicke - Sa 25.02.12 21:24

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
Ich hatte überlegt in Richtung Fallunterscheidung. Gibt es da eine Idee?
Mir ist noch nicht einmal klar was du eigentlich erreichen willst und wo das Problem liegt. ;-)


D. Annies - Sa 25.02.12 23:51

Das kann jetzt nicht wahr sein!

Ich meine eine Fallunterscheidung:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if (PosZahl := Pos('1', sRecord) or 
   (Poszahl := Pos('0', sRecord) or
   (Poszahl := Pos('2', sRecord) or
   (Poszahl := Pos('3', sRecord) then
begin
// TaDaaaa
end;


Wieso bin ich da unverständlich??

Grußlos,
Detlef


vagtler - So 26.02.12 00:11

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
[...] Wieso bin ich da unverständlich?? [...]

Weil Du nicht in klaren Worten Deine detaillierten Anforderungen darlegen kannst.

Hast Du eigentlich den Code von user profile iconrushifell verstanden?


D. Annies - So 26.02.12 08:22

Sorry, Delpher,

also der Code von rushifell ist in Ordnung, er ist sogar für meine "Versteh-den-Dozenten" - Aufgabe
fast zu mächtig, aber ich werde mal mein Glück versuchen. (Ich hatte an etwas einfacheres gedacht.)

Gruß, Detlef


Tranx - So 26.02.12 08:54

Zitat Annies:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if (PosZahl := Pos('1', sRecord) or 
   (Poszahl := Pos('0', sRecord) or
   (Poszahl := Pos('2', sRecord) or
   (Poszahl := Pos('3', sRecord) then
begin
// TaDaaaa
end;



Entschuldige, aber einen derartigen Konstrukt kannst Du in Delphi nicht machen. Du schreibst dort in den Bedingungen Zuweisungen. Außerdem fehlt die rechte schließende Klammer. Das geht gar nicht. Was Du wahrscheinlich meinst, ist:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if (Pos('1', sRecord)>0or 
   (Pos('0', sRecord)>0or
   (Pos('2', sRecord)>0or
   (Pos('3', sRecord)>0then
begin
// TaDaaaa
end;


Pos(Substr, Str) ist eine Funktion, welche den Substr in Str sucht und das erste Vorkommen als Position ausgibt:

Pos('1', 'Wert=1') wäre demnach 6
Pos('2', 'Wert=1') wäre 0, weil 2 nicht in 'Wert=1' vorkommt.

Kleiner Tip: Bei Delphi gibt es eine Hilfe Dort ist alles zu Funktionen erklärt. Da sind auch oft Beispiele. So auch bei "Pos". GTehe einfach mit dem Cursor auf Pos und drücke F1.


D. Annies - So 26.02.12 09:32

Hi, Gunther,

ich habe es jetzt so gelöst:


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:
procedure TForm1.GibGebdatAusClick(Sender: TObject);
var Poszahl0, Poszahl1, Poszahl2, Poszahl3, min : integer;
begin
  sRecord := StringE.Text;
  stringL.Caption := '';

  PosZahl0 := Pos('0', sRecord);
  PosZahl1 := Pos('1', sRecord);
  PosZahl2 := Pos('2', sRecord);
  PosZahl3 := Pos('3', sRecord);

  showmessage(inttostr(poszahl0)+'*'+inttostr(poszahl1)+'*'+inttostr(poszahl2)+'*'+inttostr(poszahl3));

  min := length(sRecord);
  if (poszahl0 > 0and (Poszahl0 < min) then min := Poszahl0
  else
  if (poszahl1 > 0and (Poszahl1 < min) then min := poszahl1
  else
  if (poszahl2 > 0and (Poszahl2 < min) then min := poszahl2
  else
  if (poszahl3 > 0and (Poszahl3 < min) then min := poszahl3;

  showmessage(inttostr(min));

  sField := Copy(sRecord, min, 10);      // 3.a Spalte links von der Zahl ab

  stringL.Caption := stringL.Caption + sField;   // 4. In das Label schreiben

end;


Beachte bitte: Ich muss es quasi nach den Anweisungen eines "begnadeten" Dozenten coden.

Und gut is,
LG, Detlef


jaenicke - So 26.02.12 10:03

Wofür du die Caption vom Label am Ende noch einmal ausliest, wenn du dieses doch als erstes gelöscht hast, ist mir nicht ganz klar. Es kann doch nur leer sein.

Und warum deine lokal benutzten Variablen (sRecord, sField) global sind... das ist kein guter Programmierstil.

Deine if-Abfrage stimmt jedenfalls noch nicht. Probiere einmal das heutige Datum z.B. aus. :zwinker:
Tipp: else ist schlecht, wenn du immer alle Bedingungen testen willst. ;-)

Gut, du willst also ein Datum im Format TT.MM.JJJJ anhand der ersten Zahl in einem String finden und herauskopieren. Die einfachste Möglichkeit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  sRecord: string;
  CurrentStrPos: PChar;
begin
  sRecord := 'dffgdfgsd01.02.2012fdgfd';
  CurrentStrPos := PChar(sRecord);
  while not (CurrentStrPos^ in ['0'..'3'#0]) do
    Inc(CurrentStrPos);
  ShowMessage(Copy(CurrentStrPos, 110));
Aber wenn du deins korrigierst, funktioniert das auch.


Tranx - So 26.02.12 10:11

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:



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:
procedure TForm1.GibGebdatAusClick(Sender: TObject);
const
  MaxZiffer = 3//MaxZiffer als maximale Ziffer, die untersucht werden soll
var
  sField, sRecord : string;
  i, minZ : integer;  //min ändern in minZ, weil sonst Komplikation wegen der Funktion Min !!, i = Schleifenvariable 
  s : string;
  Poszahl : Array[0..MaxZiffer] of integer;
begin
  sRecord := StringE.Text;
  stringL.Caption := '';
  s := '';
  minZ := 256;
  for i := 0 to MaxZiffer do
  begin
    PosZahl[i] := Pos(IntToStr(i), sRecord);
    s := s + IntToStr(PosZahl[i])+'*';
    if PosZahl[i]>0 then 
      minZ := Min(PosZahl[i],minZ); // Min ist in der Unit MATH. Diese bitte am Anfang der Unit durch Uses mit einbinden!
  end;
  if Length(s)>0 then
    s := Copy(s,1, Length(s)-1);  // letztes '*' löschen
  showMessage(s);  
  showmessage(inttostr(minZ));
  sField := Copy(sRecord, minZ, 10);      // 3.a Spalte links von der Zahl ab
  stringL.Caption := sField;   // 4. In das Label schreiben
end;


Schade, so ist es besser!!! Weil, besser erweiterbar auf 4, 5,6,7,...


Das solltest Du mal testen. Der Vorteil ist - wie geschrieben, dass diese Funktion durch ein einfaches Ändern der Konstanten MaxZiffer ohne weitere Änderung des Quelltextes auf den Vergleich mit 4, 5,6,... erweiterbar ist. Ansonsten müsstest Du ja die Vergleiche erweitern. Bei Geburtsdaten ist der Wert 3 sicher ausreichend. Da es ja nur 0 .. 3 als erste Ziffer des Tages gibt. Allerdings setzt die ganze Unit voraus, dass Du das Geburtsdatum immer in der Form tt.mm.jjjj eingibst, also mit führenden Nullen. Denn wenn Du eingibst:
9.1.1984, dann geht das schief, denn dann ist minZ = 3 und es wird ausgegeben: '1.1984 ....'
Also klappt es nur bei:
'09.01.1984' Und auch nur bei Deutscher Notation. Englisch stände ja das Jahr vorne: 1984/01/09 Das würde auch funktionieren, jedoch nicht, wenn das Jahr nur zweistellig wäre: 84/01/09

Auch ein weiteres Problem, das Du dabei unbedingt beachten solltest: Vor dem Geburtsdatum darf keine der Ziffern 0..3 in irgendeiner Form stehen:
"3. Dieses Datum ist 12.12.2012" funktioniert nicht
"Der 2. Teilnehmer ist am 13.07.1981 geboren" ebenfalls nicht

Liebe Grüße

Gunther


vagtler - So 26.02.12 12:17

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
[...] ich habe es jetzt so gelöst: [...]

Beachte bitte: Ich muss es quasi nach den Anweisungen eines "begnadeten" Dozenten coden. [...]

Wie lauten denn die Anweisungen? Schreib möglichst umständlichen und unüberlegten Code?

Der Dozent hat aber nichts mit Informatik zu tun, oder?...

btw: Deine Aufgabenstellung - die Du ja erst verheimlicht hast - löst man i.a. auch gerne mal elegant mit regulären Ausdrücken...


D. Annies - So 26.02.12 19:39

Danke, ihr drei (Musketiere) !

Ja, ja, das sind schöne Lösungen. Vielleicht hängt es auch mit dem (Schüler-) Publikum zusammen, - ich weiß es nicht.
Aber ich will einem "Mädchen = 21 J. alt" helfen, und da darf ich vieles nicht anwenden, was ich sonst täte - obwaohl ich auf so elegante Lösungen, wie ihr sie eingestellt habt, wohl auch nicht gekommen wäre.

Dankeschön,
Detlef