Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern (https://www.delphipraxis.net/173959-string-auf-bestimmtest-format-geokoordinaten-pruefen-und-verbessern.html)

BBoy 26. Mär 2013 09:30

Delphi-Version: 5

String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ich habe in einem String Geo-Koordinaten in der form von: N 09° 42.756 E 008° 30.061
Zumindest sollten die so aussehen bevor sie weiterverarbeitet werden.
Nun kann es aber passieren das der String die Koordinaten nicht in der optimalen Schreibweise enthält. Hier mal ein paar Varianten:
N 09° 41.766 E 8° 30.061 < E 8° statt 008°
N 9° 42.756 E 008° 30.061 < nur eine einstellige Ziffer bei 9
N 09° 42.756 E 008° 30.61 < nur zweistellige Ziffer bei 61
N 09° 42.756 E 008° 9.612 < nur einstellige Ziffer bei 9.612
N 9° 42.65 E 8° 9.546 < so ziemlich alles falsch
oder es fehlen Leerzeichen:
N09° 42.756 E008° 30.061

Wie bekomme ich es am einfachsten hin den String immer in das optimale Format zu bringen?

DeddyH 26. Mär 2013 09:35

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Zerlege das Original in seine Bestandteile und bring ihn dann mit Delphi-Referenz durchsuchenFormat in das gewünschte Format.

BBoy 26. Mär 2013 09:42

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
so ungefähr hatte ich mir das auch vorgestellt. aber wie geht das am einfachsten?

grad= copy(koordstr,2,2) und dann mit pos prüfen ob ein ° Zeichen enthalten ist ?? und dann entsprechend reagieren?
Mir kommt dieser Weg etwas umständlich vor. Das geht doch bestimmt einfacher, oder?

Sir Rufo 26. Mär 2013 09:47

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Hiermit
Delphi-Quellcode:
var
  LStrLst : TStringList;

LStrLst := TStringList.Create;
try

  LStrLst.Delimiter := ' ';
  LStrLst.StrictDelimiter := True; // evtl. in D2009 noch nicht bekannt, dann weglassen
  LStrLst.DelimitedText := 'N 09° 41.766 E 8° 30.061';

  // Jetzt ist jeder Teil in einer Zeile von LStrLst

finally
  LStrLst.Free;
end;

Nersgatt 26. Mär 2013 09:47

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ich würde den String an den Leerstellen in einzelne Parts zerlegen. Dann kannst Du anfangen, die Elemente zu untersuchen, ob sie ein gültiges Format darstellen.
Das erste Element muss ein N oder S sein. Wenn nicht -> Fehler schmeißen
Das zweite Element muss mit ° enden und der Rest muss ne Zahl sein
Das dritte Element muss eine Zahl mit Dezimaltrenner . sein.
usw.

Wenn diese Prüfungen alle erfolgreich sind, kannst Du die einzelnen Element formatieren und wieder zu einem String zusammen setzen.

CCRDude 26. Mär 2013 09:53

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Das aber geht davon aus, dass zwingend alle Teile durch Leerzeichen getrennt sind. Da obige Varianten nicht alle sind, würde ich davon nicht ausgehen. Im Gegenteil würde ich eventuell sogar alle Leerzeichen rausnehmen (damit ist der Teil schonmal normiert), den zweiten Buchstaben raussuchen, an der Stelle trennen (damit ist das ganze in zwei identische Teilprobleme zerlegt) und beide Teile dann nach den Trennzeichen parsen.

BBoy 26. Mär 2013 10:14

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Also so etwa:
1. alle leerzeichen löschen = N49°41.766E8°31.672
2.nach E oder O suchen und den String in 2 Stücke teilen = "N49°41.766" und "E8°31.672"
3.prüfen ob 1. Buchstabe ein N oder S ist... weiter
4. prüfen an wievielter stelle das ° Zeichen kommt. kommt es an 3. stelle dann eine 0 vor anfügen ansonsten alles ok. macht aus N9° ~ N09° oder aus E8° ~ E008°
5. prüfen an wievielter stelle der . kommt. ist er an 6. stelle dann eine 0 vor anfügen ansonsten alles ok macht aus N49°7.123 ~ N49°07.123
6. prüfen wiviel ziffern kommen nach dem punkt. sind es 2 dann eine 0 vor anfügen. macht aus N49°07.23 ~ N49°07.023
7. fertig :)

Müsste so OK sein, oder?

Sir Rufo 26. Mär 2013 10:22

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Dafür würde ich einen kleinen Parser schreiben, der diesen String dann entsprechend Zeichen für Zeichen verarbeitet.

Kann man auch sehr schön mit dem State-Pattern erledigen (auch wenn jetzt wieder der ein oder andere schreit, das wäre mit Kanonen auf Spatzen geschossen ;))

DeddyH 26. Mär 2013 10:40

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Kleiner Test ohne jegliche Fehlerbehandlung:
Delphi-Quellcode:
uses StrUtils;

procedure TForm24.Button1Click(Sender: TObject);
type
  TGeoData = record
    NSOrientation: char;
    NSDegree: integer;
    NSMinutes: double;
    EWOrientation: char;
    EWDegree: integer;
    EWMinutes: double;
  end;
const
  DEGREESIGN = '°';
  ORIGINAL = 'N 49° 41.766E8 °31.67 2';
var
  CurrentPos, NextPos: integer;
  Data: TGeoData;
  Settings: TFormatSettings;
  GeoData, s: string;
begin
  Settings := TFormatSettings.Create;
  Settings.DecimalSeparator := '.';
  ZeroMemory(@Data, SizeOf(Data));
  GeoData := StringReplace(ORIGINAL, ' ', '', [rfReplaceAll]);
  Data.NSOrientation := GeoData[1];
  CurrentPos := 2;
  NextPos := Pos(DEGREESIGN, GeoData);
  Data.NSDegree := StrToInt(Copy(GeoData, CurrentPos, NextPos - CurrentPos));
  CurrentPos := NextPos + 1;
  NextPos := PosEx('E', AnsiUpperCase(GeoData), CurrentPos);
  if NextPos = 0 then
    NextPos := PosEx('W', AnsiUpperCase(GeoData), CurrentPos);
  Data.NSMinutes := StrToFloat(Copy(GeoData, CurrentPos, NextPos - CurrentPos), Settings);
  CurrentPos := NextPos + 1;
  Data.EWOrientation := GeoData[NextPos];
  NextPos := PosEx(DEGREESIGN, GeoData, CurrentPos);
  Data.EWDegree := StrToInt(Copy(GeoData, CurrentPos, NextPos - CurrentPos));
  CurrentPos := NextPos + 1;
  Data.EWMinutes := StrToFloat(Copy(GeoData, CurrentPos, MAXINT), Settings);
  s := Format('%s %.2d%s %.3f %s %.3d%s %.3f', [
    Data.NSOrientation,
    Data.NSDegree,
    DEGREESIGN,
    Data.NSMinutes,
    Data.EWOrientation,
    Data.EWDegree,
    DEGREESIGN,
    Data.EWMinutes], Settings);
  ShowMessage(s);
end;

p80286 26. Mär 2013 10:55

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Mal ganz vorsichtig angemerkt, statt "N" könnte auch "S" vorkommen, und statt "E" "W".
Und auf das Gradzeichen würde ich mich auch nicht verlassen. Wenn dann sollte eher ein "allgemeines" Format zum Einsatz kommen
[Bstb][trenn][Integer][Sndrz][trenn][Float][trenn]
[Bstb][trenn][Integer][Sndrz][trenn][Float][NL]

Gruß
K-H

DeddyH 26. Mär 2013 11:01

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Und nun?

BBoy 26. Mär 2013 12:19

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Danke für die Routine!
data.NSMinutes und Data.EWMinutes zeigt er aber nur die 1. stelle an, also eine 4 bzw 3. Wüsste nicht woran das liegt..

DeddyH 26. Mär 2013 12:25

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Die Routine war eigentlich gar nicht in der Form für den Produktiveinsatz gedacht. Hast Du mal debuggt? Betrifft das nur die Ausgabe, oder sind die Daten schon falsch?

BBoy 26. Mär 2013 13:06

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Die Routine passt aber fast genau für mich, daher habe ich mich dieser bemächtigt :)
Es waren ein paar kleine Tippfehler drin, die habe ich verbessert. aber warum der nur die 1. stelle anzeigt verstehe ich nicht.
data.NSMinutes enthält 41,766 es liegt am Format Befehl.

DeddyH 26. Mär 2013 13:10

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Und Du hast den Code per C&P eingefügt? Bei mir kommt nämlich beim ShowMessage
Zitat:

N 49° 41.766 E 008° 31.672
heraus.

BBoy 26. Mär 2013 13:31

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ja C&P. Bei mir gibt es aber Settings := TFormatSettings.Create; und auch TFormatSettings.Create(LOCALE_USER_DEFAULT); nicht! Die Zeile habe ich weggelassen.

DeddyH 26. Mär 2013 13:35

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ich habe hier kein Delphi 5 zur Verfügung. Was kommt denn hierbei heraus?
Delphi-Quellcode:
var
  OldSep: char;
begin
  OldSep := DecimalSeparator;
  try
    DecimalSeparator := '.';
    ShowMessage(Format('%.3f', [12.34567]));
  finally
    DecimalSeparator := OldSep;
  end;
end;

BBoy 26. Mär 2013 13:43

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ergebnis=12.346

Kann es vlt. am , liegen bei data.NSMinutes (41,766) ?

Delphi 5? Habe Delphi 2009

DeddyH 26. Mär 2013 13:55

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Im Ausgangspost hast Du Delphi 5 angegeben. Ja, es wird wahrscheinlich am Komma liegen, deshalb ja der "Aufwand" mit den FormatSettings. Da musst Du mal in der Hilfe nachlesen, wie das unter Delphi 2009 genau funktioniert.

[edit] Neuer Versuch:
Delphi-Quellcode:
var
  Settings: TFormatSettings;
begin
  GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, Settings);
  Settings.DecimalSeparator := '.';
  ShowMessage(Format('%.3f', [12.34567], Settings));
end;
[/edit]

BBoy 26. Mär 2013 15:06

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Hier bekomme ich nur eine 1 als Ergebnis.
War das Ergebnis 12.346 aus dem letzten Test nicht ok?

Ich habe mal Data.EWMinutes := 41.278; direkt zugewiesen und mit Format ausgegeben. es wird immer noch nur die 1. stelle angezeigt. Ich komme nicht dahinter an was es liegt.

Edit:// wenn ich ShowMessage(Format('%.3f', [data.ewminutes])); mache dann funktioniert es!

Edit://
So geht es:
Delphi-Quellcode:
  DecimalSeparator := '.';
  showmessage(Format('%s %.2d%s %.3f %s %.3d%s %.3f', [
    Data.NSOrientation,
    Data.NSDegree,
    DEGREESIGN,
    Data.NSMinutes,
    Data.EWOrientation,
    Data.EWDegree,
    DEGREESIGN,
    Data.EWMinutes]));

DeddyH 26. Mär 2013 15:10

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Und wenn Du die "Delphi 5"-Variante nimmst und den Settings-Parameter beim Format-Befehl weglässt?

BBoy 26. Mär 2013 15:15

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Delphi-Quellcode:
 
  DecimalSeparator := '.';
showmessage(Format('%s %.2d%s %.3f %s %.3d%s %.3f', [
    Data.NSOrientation,
    Data.NSDegree,
    DEGREESIGN,
    Data.NSMinutes,
    Data.EWOrientation,
    Data.EWDegree,
    DEGREESIGN,
    Data.EWMinutes]));
So geht es. Danke für deine Geduld!

Leider macht er aus:
N 49° 41.66 E 8° 31.672
N 49° 41.660 E 8° 31.672
richtig wäre:
N 49° 41.066 E 8° 31.672
Gibt es da auch möglichkeiten?

DeddyH 26. Mär 2013 15:24

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Ich wüsste nicht, da ja die eingehende Zahl faktisch falsch ist, und zwar ihr Wert und nicht nur ihre Darstellung. Es sei denn, Du kennst Kriterien, anhand derer Du das erkennen könntest, dann müsstest Du sie halt korrigieren.

BBoy 26. Mär 2013 15:28

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
ok, dann werde ich einfach die anzahl der ziffern prüfen und wenn <3 dann füge ich eine 0 voran.

DeddyH 26. Mär 2013 15:31

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Bist Du wirklich sicher, dass das so stimmt? Immerhin sind 3,50 und 3,05 ja unterschiedliche Zahlen, ich hätte da meine Bedenken.

BBoy 26. Mär 2013 15:41

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
ja bei Geo Koordinaten gilt:
N 49° 8.66 E 8° 31.672 = N 49° 08.066 E 8° 31.672
Ist ja logisch es ist ja 8.66 also achttausendsechundsechzig, würde die null dahinter kommen N 49° 8.660 E 8° 31.672, wäre es ja achttausensechHUNDERTsechundsechzig und wäre ganz wo anders :)

DeddyH 26. Mär 2013 15:43

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Dann habe ich anscheinend die Notation nicht verstanden, ich war der Meinung, es geht um Fließkommazahlen.

BBoy 26. Mär 2013 16:02

AW: String auf bestimmtest Format (Geokoordinaten) prüfen und verbessern
 
Habe mir das nun so umgebaut und so funktioniert es für meine zwecke:

Delphi-Quellcode:
type
  TGeoData = record
    NSOrientation: char;
    NSDegree: integer;
    NSMinutes: string;
    EWOrientation: char;
    EWDegree: integer;
    EWMinutes: string;
  end;
const
  DEGREESIGN = '°';
  ORIGINAL = 'N 49° 8.66 E 8° 1.72';
var
  CurrentPos, NextPos: integer;
  Data: TGeoData;
  GeoData, s: string;
  tempstr : String;
  pos1 : Integer;
begin
  DecimalSeparator := '.';
  ZeroMemory(@Data, SizeOf(Data));
  GeoData := StringReplace(ORIGINAL, ' ', '', [rfReplaceAll]);
  Data.NSOrientation := GeoData[1];
  CurrentPos := 2;
  NextPos := Pos(DEGREESIGN, GeoData);
  Data.NSDegree := StrToInt(Copy(GeoData, CurrentPos, NextPos - CurrentPos));
  CurrentPos := NextPos + 1;
  NextPos := PosEx('E', AnsiUpperCase(GeoData), CurrentPos);
  if NextPos = 0 then
    NextPos := PosEx('W', AnsiUpperCase(GeoData), CurrentPos);
  TempStr := Copy(GeoData, CurrentPos, NextPos - CurrentPos);
  pos1 := pos('.',TempStr);
  if pos1 = 2 then
    insert('0',tempstr,1);
  pos1 := pos('.',TempStr);
  if (pos1 = 3) and (length(tempstr)=5) then
    insert('0',tempstr,4);
  data.nsminutes := tempstr;
  CurrentPos := NextPos + 1;
  Data.EWOrientation := GeoData[NextPos];
  NextPos := PosEx(DEGREESIGN, GeoData, CurrentPos);
  Data.EWDegree := StrToInt(Copy(GeoData, CurrentPos, NextPos - CurrentPos));
  CurrentPos := NextPos + 1;
  TempStr := Copy(GeoData, CurrentPos, MAXINT);
  pos1 := pos('.',TempStr);
  if pos1 = 2 then
    insert('0',tempstr,1);
  pos1 := pos('.',TempStr);
  if (pos1 = 3) and (length(tempstr)=5) then
    insert('0',tempstr,4);
  Data.EWMinutes := tempstr;
  s := Format('%s %.2d%s %s %s %.3d%s %s', [
    Data.NSOrientation,
    Data.NSDegree,
    DEGREESIGN,
    Data.NSMinutes,
    Data.EWOrientation,
    Data.EWDegree,
    DEGREESIGN,
    Data.EWMinutes]);
  ShowMessage(s);
end;
Noch mal Danke für deine Geduld!


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:02 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