Is there an inverse function of *SysUtils.Format* in Delphi

后端 未结 3 1413
伪装坚强ぢ
伪装坚强ぢ 2020-12-09 20:01

Has anyone written an \'UnFormat\' routine for Delphi?

What I\'m imagining is the inverse of SysUtils.Format and looks something like this

<
相关标签:
3条回答
  • 2020-12-09 20:49

    I know it tends to scare people, but you could write a simple function to do this using regular expressions

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

    If you are worried about reg expressions take a look at www.regexbuddy.com and you'll never look back.

    0 讨论(0)
  • 2020-12-09 20:55

    I tend to take care of this using a simple parser. I have two functions, one is called NumStringParts which returns the number of "parts" in a string with a specific delimiter (in your case above the space) and GetStrPart returns the specific part from a string with a specific delimiter. Both of these routines have been used since my Turbo Pascal days in many a project.

    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;
    

    Example of usage:

     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; 
    

    These routines work wonders for simple or strict comma delimited strings too. These routines work wonderfully in Delphi 2009/2010.

    0 讨论(0)
  • 2020-12-09 20:56

    This is called scanf in C, I've made a Delphi look-a-like for this :

    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;
    
    0 讨论(0)
提交回复
热议问题