Frage

Hat jemand geschrieben, ein "UnFormat" routine für Delphi?

Was ich mir vorstelle, ist die inverse von SysUtils.Format und sieht ungefähr so aus

UnFormat('eine Nummer %n und andere %n',[float1, float2]);

Man könnte also packen Sie eine Zeichenfolge in eine Reihe von Variablen, die Verwendung von format-strings.

Ich habe die 'Format' - routine in SysUtils, aber ich habe noch nie verwendet-Montage, so es ist bedeutungslos für mich.

War es hilfreich?

Lösung

Dies nennt man scanf in C, ich habe eine Delphi-look-a-like für dieses :

function ScanFormat(const Input, Format: string; Args: array of Pointer): Integer;
var
  InputOffset: Integer;
  FormatOffset: Integer;
  InputChar: Char;
  FormatChar: Char;

  function _GetInputChar: Char;
  begin
    if InputOffset <= Length(Input) then
    begin
      Result := Input[InputOffset];
      Inc(InputOffset);
    end
    else
      Result := #0;
  end;

  function _PeekFormatChar: Char;
  begin
    if FormatOffset <= Length(Format) then
      Result := Format[FormatOffset]
    else
      Result := #0;
  end;

  function _GetFormatChar: Char;
  begin
    Result := _PeekFormatChar;
    if Result <> #0 then
      Inc(FormatOffset);
  end;

  function _ScanInputString(const Arg: Pointer = nil): string;
  var
    EndChar: Char;
  begin
    Result := '';
    EndChar := _PeekFormatChar;
    InputChar := _GetInputChar;
    while (InputChar > ' ')
      and (InputChar <> EndChar) do
    begin
      Result := Result + InputChar;
      InputChar := _GetInputChar;
    end;

    if InputChar <> #0 then
      Dec(InputOffset);

    if Assigned(Arg) then
      PString(Arg)^ := Result;
  end;

  function _ScanInputInteger(const Arg: Pointer): Boolean;
  var
    Value: string;
  begin
    Value := _ScanInputString;
    Result := TryStrToInt(Value, {out} PInteger(Arg)^);
  end;

  procedure _Raise;
  begin
    raise EConvertError.CreateFmt('Unknown ScanFormat character : "%s"!', [FormatChar]);
  end;

begin
  Result := 0;
  InputOffset := 1;
  FormatOffset := 1;
  FormatChar := _GetFormatChar;
  while FormatChar <> #0 do
  begin
    if FormatChar <> '%' then
    begin
      InputChar := _GetInputChar;
      if (InputChar = #0)
      or (FormatChar <> InputChar) then
        Exit;
    end
    else
    begin
      FormatChar := _GetFormatChar;
      case FormatChar of
        '%':
          if _GetInputChar <> '%' then
            Exit;
        's':
          begin
            _ScanInputString(Args[Result]);
            Inc(Result);
          end;
        'd', 'u':
          begin
            if not _ScanInputInteger(Args[Result]) then
              Exit;

            Inc(Result);
          end;
      else
        _Raise;
      end;
    end;

    FormatChar := _GetFormatChar;
  end;
end;

Andere Tipps

Ich weiß, dass es dazu neigt, Leute zu erschrecken, aber Sie konnten schreiben Sie eine einfache Funktion, um dies mit regulären Ausdrücken

'a number (.*?) and another (.*?)

Wenn Sie besorgt über die reg Ausdrücke werfen Sie einen Blick auf www.regexbuddy.com und Sie werden nie Blick zurück.

Ich Neige dazu, darauf achten, dieses mit einem einfachen parser.Ich habe zwei Funktionen, eine ist genannt NumStringParts gibt die Anzahl der "Teile" in einem string mit einem bestimmten Trennzeichen (in Ihrem Fall über den Raum) und GetStrPart gibt den bestimmten Teil aus einem string mit einem bestimmten Trennzeichen.Diese beiden Routinen verwendet wurden, da mein Turbo Pascal Tagen in vielen ein Projekt.

function NumStringParts(SourceStr,Delimiter:String):Integer;
var
  offset : integer;
  curnum : integer;
begin
  curnum := 1;
  offset := 1;
  while (offset <> 0) do
    begin
      Offset := Pos(Delimiter,SourceStr);
      if Offset <> 0 then
        begin
          Inc(CurNum);
            Delete(SourceStr,1,(Offset-1)+Length(Delimiter));
        end;
    end;
  result := CurNum;
end;

function GetStringPart(SourceStr,Delimiter:String;Num:Integer):string;
var
  offset : integer;
  CurNum : integer;
  CurPart : String;
begin
  CurNum := 1;
  Offset := 1;
  While (CurNum <= Num) and (Offset <> 0) do
    begin
      Offset := Pos(Delimiter,SourceStr);
      if Offset <> 0 then
        begin
          CurPart := Copy(SourceStr,1,Offset-1);
          Delete(SourceStr,1,(Offset-1)+Length(Delimiter));
          Inc(CurNum)
        end
      else
        CurPart := SourceStr;
    end;
  if CurNum >= Num then
    Result := CurPart
  else
    Result := '';
end;

Beispiel der Nutzung:

 var
    st : string;
    f1,f2 : double; 
  begin
     st := 'a number 12.35 and another 13.415';
     ShowMessage('Total String parts = '+IntToStr(NumStringParts(st,#32)));
     f1 := StrToFloatDef(GetStringPart(st,#32,3),0.0);
     f2 := StrToFloatDef(GetStringPart(st,#32,6),0.0);
     ShowMessage('Float 1 = '+FloatToStr(F1)+' and Float 2 = '+FloatToStr(F2)); 
  end; 

Diese Routinen, die Arbeit Wunder für die einfachen oder strengen Komma getrennten Zeichenfolgen zu.Diese Routinen funktionieren wunderbar in Delphi 2009/2010.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top