<p>Has anyone written an 'UnFormat' routine for Delphi?</p>

<p>What I'm imagining is the <em>inverse</em> of <em>SysUtils.Format</em> and looks something like this  </p>

<p>UnFormat('a number %n and another %n',[float1, float2]);  </p>

<p>So you could unpack a string into a series of variables using format strings.</p>

<p>I've looked at the 'Format' routine in SysUtils, but I've never used assembly so it is meaningless to me.</p>

[{'answer_id': 72713, 'author': 'PatrickvL', 'author_id': 12170, 'author_profile': 'https://Stackoverflow.com/users/12170', 'pm_score': 5, 'selected': True, 'text': '<p>This is called scanf in C, I\'ve made a Delphi look-a-like for this :</p>\n\n<pre><code>function ScanFormat(const Input, Format: string; Args: array of Pointer): Integer;\nvar\n  InputOffset: Integer;\n  FormatOffset: Integer;\n  InputChar: Char;\n  FormatChar: Char;\n\n  function _GetInputChar: Char;\n  begin\n    if InputOffset &lt;= Length(Input) then\n    begin\n      Result := Input[InputOffset];\n      Inc(InputOffset);\n    end\n    else\n      Result := #0;\n  end;\n\n  function _PeekFormatChar: Char;\n  begin\n    if FormatOffset &lt;= Length(Format) then\n      Result := Format[FormatOffset]\n    else\n      Result := #0;\n  end;\n\n  function _GetFormatChar: Char;\n  begin\n    Result := _PeekFormatChar;\n    if Result &lt;&gt; #0 then\n      Inc(FormatOffset);\n  end;\n\n  function _ScanInputString(const Arg: Pointer = nil): string;\n  var\n    EndChar: Char;\n  begin\n    Result := \'\';\n    EndChar := _PeekFormatChar;\n    InputChar := _GetInputChar;\n    while (InputChar &gt; \' \')\n      and (InputChar &lt;&gt; EndChar) do\n    begin\n      Result := Result + InputChar;\n      InputChar := _GetInputChar;\n    end;\n\n    if InputChar &lt;&gt; #0 then\n      Dec(InputOffset);\n\n    if Assigned(Arg) then\n      PString(Arg)^ := Result;\n  end;\n\n  function _ScanInputInteger(const Arg: Pointer): Boolean;\n  var\n    Value: string;\n  begin\n    Value := _ScanInputString;\n    Result := TryStrToInt(Value, {out} PInteger(Arg)^);\n  end;\n\n  procedure _Raise;\n  begin\n    raise EConvertError.CreateFmt(\'Unknown ScanFormat character : "%s"!\', [FormatChar]);\n  end;\n\nbegin\n  Result := 0;\n  InputOffset := 1;\n  FormatOffset := 1;\n  FormatChar := _GetFormatChar;\n  while FormatChar &lt;&gt; #0 do\n  begin\n    if FormatChar &lt;&gt; \'%\' then\n    begin\n      InputChar := _GetInputChar;\n      if (InputChar = #0)\n      or (FormatChar &lt;&gt; InputChar) then\n        Exit;\n    end\n    else\n    begin\n      FormatChar := _GetFormatChar;\n      case FormatChar of\n        \'%\':\n          if _GetInputChar &lt;&gt; \'%\' then\n            Exit;\n        \'s\':\n          begin\n            _ScanInputString(Args[Result]);\n            Inc(Result);\n          end;\n        \'d\', \'u\':\n          begin\n            if not _ScanInputInteger(Args[Result]) then\n              Exit;\n\n            Inc(Result);\n          end;\n      else\n        _Raise;\n      end;\n    end;\n\n    FormatChar := _GetFormatChar;\n  end;\nend;\n</code></pre>\n'}, {'answer_id': 73750, 'author': 'skamradt', 'author_id': 9217, 'author_profile': 'https://Stackoverflow.com/users/9217', 'pm_score': 1, 'selected': False, 'text': '<p>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.</p>\n\n<pre><code>function NumStringParts(SourceStr,Delimiter:String):Integer;\nvar\n  offset : integer;\n  curnum : integer;\nbegin\n  curnum := 1;\n  offset := 1;\n  while (offset &lt;&gt; 0) do\n    begin\n      Offset := Pos(Delimiter,SourceStr);\n      if Offset &lt;&gt; 0 then\n        begin\n          Inc(CurNum);\n            Delete(SourceStr,1,(Offset-1)+Length(Delimiter));\n        end;\n    end;\n  result := CurNum;\nend;\n\nfunction GetStringPart(SourceStr,Delimiter:String;Num:Integer):string;\nvar\n  offset : integer;\n  CurNum : integer;\n  CurPart : String;\nbegin\n  CurNum := 1;\n  Offset := 1;\n  While (CurNum &lt;= Num) and (Offset &lt;&gt; 0) do\n    begin\n      Offset := Pos(Delimiter,SourceStr);\n      if Offset &lt;&gt; 0 then\n        begin\n          CurPart := Copy(SourceStr,1,Offset-1);\n          Delete(SourceStr,1,(Offset-1)+Length(Delimiter));\n          Inc(CurNum)\n        end\n      else\n        CurPart := SourceStr;\n    end;\n  if CurNum &gt;= Num then\n    Result := CurPart\n  else\n    Result := \'\';\nend;\n</code></pre>\n\n<p>Example of usage:</p>\n\n<pre><code> var\n    st : string;\n    f1,f2 : double; \n  begin\n     st := \'a number 12.35 and another 13.415\';\n     ShowMessage(\'Total String parts = \'+IntToStr(NumStringParts(st,#32)));\n     f1 := StrToFloatDef(GetStringPart(st,#32,3),0.0);\n     f2 := StrToFloatDef(GetStringPart(st,#32,6),0.0);\n     ShowMessage(\'Float 1 = \'+FloatToStr(F1)+\' and Float 2 = \'+FloatToStr(F2)); \n  end; \n</code></pre>\n\n<p>These routines work wonders for simple or strict comma delimited strings too.   These routines work wonderfully in Delphi 2009/2010.</p>\n'}, {'answer_id': 76566, 'author': 'Toby Allen', 'author_id': 6244, 'author_profile': 'https://Stackoverflow.com/users/6244', 'pm_score': 2, 'selected': False, 'text': '<p>I know it tends to scare people, but you could write a simple function to do this using regular expressions </p>\n\n<pre><code>\'a number (.*?) and another (.*?)\n</code></pre>\n\n<p>If you are worried about reg expressions take a look at <a href="http://www.regexbuddy.com" rel="nofollow noreferrer">www.regexbuddy.com</a> and you\'ll never look back.</p>\n'}]
['https://Stackoverflow.com/questions/72672', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/12376/']