2008-09-16 12 views
10

में * SysUtils.Format * का एक व्यस्त कार्य है क्या किसी ने डेल्फी के लिए 'अनफॉर्मेट' दिनचर्या लिखी है?क्या डेल्फी

क्या मैं कल्पना कर रहा हूँ SysUtils.Format का प्रतिलोम है और इस

unformat तरह दिखता है ('एक नंबर% n और एक अन्य% एन', [float1, float2]);

तो आप फ़ॉर्म स्ट्रिंग का उपयोग करके चर की श्रृंखला में स्ट्रिंग को अनपैक कर सकते हैं।

मैंने SysUtils में 'प्रारूप' दिनचर्या को देखा है, लेकिन मैंने कभी असेंबली का उपयोग नहीं किया है, इसलिए यह मेरे लिए व्यर्थ है।

उत्तर

12

यह सी में scanf कहा जाता है, मैं इस के लिए एक डेल्फी नज़र-ए-तरह कर दिया है:

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; 
+0

इसके लिए धन्यवाद। बस मैं यह चाहता हूं। उदाहरण उपयोग: स्कैनफॉर्मैट ('संख्या 27 स्ट्रिंग हैलो', 'संख्या% डी स्ट्रिंग% s', [@ anInt, @ aString]); नोट: एक स्ट्रिंग निकालने से स्ट्रिंग के बाद पहला अक्षर स्ट्रिंग में भी निहित होता है। –

1

मैं एक सरल पार्सर का उपयोग कर इस की देखभाल करते हैं। मेरे पास दो कार्य हैं, जिन्हें नोमस्ट्रिंगपार्ट कहा जाता है जो एक विशिष्ट डिलीमीटर (अंतरिक्ष के ऊपर आपके मामले में) के साथ एक स्ट्रिंग में "भागों" की संख्या देता है और 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; 

इन दिनचर्या साधारण या सख्त अल्पविराम से परे भी तार के लिए चमत्कार काम करते हैं। ये दिनचर्या डेल्फी 200 9/2010 में अद्भुत काम करते हैं।

4

मैं इसे लोगों को डराने के लिए जाता है पता है, लेकिन आप नियमित अभिव्यक्ति

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

का उपयोग कर आप reg भाव के बारे में चिंतित www.regexbuddy.com पर एक नज़र डालें रहे हैं, तो यह करने के लिए एक सरल समारोह लिख सकता है और तुम देखो नहीं करेंगे वापस।