Delphi中是否有* SysUtils.Format *的逆函数
时间:2020-03-05 18:56:03 来源:igfitidea点击:
是否有人为Delphi编写了" UnFormat"例程?
我在想的是SysUtils.Format的逆函数,看起来像这样
UnFormat('数字%n和另一个%n',[float1,float2]);
因此,我们可以使用格式字符串将字符串解压缩为一系列变量。
我已经看过SysUtils中的"格式"例程,但是我从未使用过汇编,因此对我来说毫无意义。
解决方案
回答
这在C中称为scanf,为此我制作了一个Delphi外观:
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;
回答
我倾向于使用一个简单的解析器来解决这个问题。我有两个函数,一个叫做NumStringParts,它用一个特定的定界符(在情况下,空格上方)返回字符串中"部分"的数目,GetStrPart从一个具有特定定界符的字符串中返回特定的部分。自从我在Turbo Pascal时代起就在许多项目中使用了这两个例程。
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;
用法示例:
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;
这些例程对于简单或者严格的逗号分隔字符串也能产生奇迹。这些例程在Delphi 2009/2010中表现出色。
回答
我知道它会吓到人们,但是我们可以编写一个简单的函数来使用正则表达式来做到这一点。
'a number (.*?) and another (.*?)
如果我们担心reg表达式,请访问www.regexbuddy.com,我们永远都不会回头。