delphi - tenga - inversa de una funcion cuadratica
¿Hay una función inversa de*SysUtils.Format*en Delphi (3)
¿Alguien ha escrito una rutina ''UnFormat'' para Delphi?
Lo que estoy imaginando es el inverso de SysUtils.Format y se ve algo como esto
UnFormat (''un número% n y otro% n'', [float1, float2]);
Por lo tanto, podría descomprimir una cadena en una serie de variables utilizando cadenas de formato.
Miré la rutina ''Formato'' en SysUtils, pero nunca utilicé el ensamblaje, así que no tiene sentido para mí.
Esto se llama scanf en C, he hecho un Delphi look-like para esto:
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;
Sé que tiende a asustar a la gente, pero podrías escribir una función simple para hacer esto usando expresiones regulares
''a number (.*?) and another (.*?)
Si le preocupan las expresiones de registro, eche un vistazo a www.regexbuddy.com y nunca mirará hacia atrás.
Tiendo a cuidar esto usando un analizador simple. Tengo dos funciones, una se llama NumStringParts que devuelve el número de "partes" en una cadena con un delimitador específico (en su caso sobre el espacio) y GetStrPart devuelve la parte específica de una cadena con un delimitador específico. Ambas rutinas se han utilizado desde mis días de Turbo Pascal en muchos proyectos.
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;
Ejemplo de uso:
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;
Estas rutinas también hacen maravillas para cadenas simples o estrictas delimitadas por comas. Estas rutinas funcionan maravillosamente en Delphi 2009/2010.