سؤال

هل قام أحد بكتابة روتين "UnFormat" لدلفي؟

ما أتخيله هو معكوس ل SysUtils.Format ويبدو شيء من هذا القبيل

UnFormat('رقم %n وآخر %n',[float1, float2]);

لذلك يمكنك فك سلسلة إلى سلسلة من المتغيرات باستخدام سلاسل التنسيق.

لقد ألقيت نظرة على روتين "التنسيق" في SysUtils، لكنني لم أستخدم التجميع مطلقًا، لذا فهو لا معنى له بالنسبة لي.

هل كانت مفيدة؟

المحلول

وهذا ما يسمى scanf في لغة C، لقد قمت بعمل نموذج دلفي لهذا:

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 بإرجاع الجزء المحدد من سلسلة ذات محدد محدد.تم استخدام كلا الإجراءين منذ أيام 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; 

تعمل هذه الإجراءات الروتينية بشكل رائع مع السلاسل البسيطة أو الصارمة المحددة بفواصل أيضًا.تعمل هذه الإجراءات بشكل رائع في دلفي 2009/2010.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top