문제

Delphi용 'UnFormat' 루틴을 작성한 사람이 있나요?

내가 상상하는 것은 ~의 SysUtils.Format 그리고 이런 것 같아

UnFormat('숫자 %n과 또 다른 %n',[float1, float2]);

따라서 형식 문자열을 사용하여 문자열을 일련의 변수로 압축해제할 수 있습니다.

SysUtils의 'Format' 루틴을 살펴봤지만 어셈블리를 사용해 본 적이 없기 때문에 의미가 없습니다.

도움이 되었습니까?

해결책

이것은 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;

다른 팁

사람들이 겁을 먹는 경향이 있다는 건 알지만 정규식을 사용하여 이를 수행하는 간단한 함수를 작성할 수 있습니다.

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

reg 표현식이 걱정된다면 다음을 살펴보세요. www.regexbuddy.com 그리고 당신은 결코 뒤돌아보지 않을 것입니다.

나는 간단한 파서를 사용하여 이 문제를 처리하는 경향이 있습니다.두 가지 함수가 있습니다. 하나는 특정 구분 기호가 있는 문자열의 "부분" 수를 반환하는 NumStringParts(공백 위의 경우)이고 GetStrPart는 특정 구분 기호가 있는 문자열에서 특정 부분을 반환합니다.이 두 루틴은 터보 파스칼 시절부터 많은 프로젝트에서 사용되었습니다.

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에서 훌륭하게 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top