मैं बहुत की तरह इस समारोह लिखना चाहते हैं:
procedure Concat(var Dest: string; const Source: array of string);
var
i: Integer;
OriginalDestLen: Integer;
SourceLen: Integer;
TotalSourceLen: Integer;
DestPtr: PChar;
begin
TotalSourceLen := 0;
OriginalDestLen := Length(Dest);
for i := low(Source) to high(Source) do begin
inc(TotalSourceLen, Length(Source[i]));
end;
SetLength(Dest, OriginalDestLen + TotalSourceLen);
DestPtr := PChar(Pointer(Dest)) + OriginalDestLen;
for i := low(Source) to high(Source) do begin
SourceLen := Length(Source[i]);
Move(Pointer(Source[i])^, DestPtr^, SourceLen*SizeOf(Char));
inc(DestPtr, SourceLen);
end;
end;
यह काफी है आत्म व्याख्यात्मक। जटिलताओं के कारण जटिलताएं होती हैं। रेंज जांच सक्षम होने पर रिक्त स्ट्रिंग के वर्णों को इंडेक्स करने का कोई भी प्रयास अपवादों का कारण बन जाएगा।
उस जटिलता को संभालने के लिए, आप if
मामले के लिए परीक्षण जोड़ सकते हैं जहां Move
कॉल में शामिल तारों में से एक खाली है। मैं एक अलग दृष्टिकोण पसंद करते हैं। मैं स्ट्रिंग वैरिएबल को पॉइंटर होने के बजाय डालना चाहता हूं। यह रेंज जांच को बाईपास करता है लेकिन if
कथन को छोड़ने की अनुमति देता है।
Move(Pointer(Source[i])^, DestPtr^, SourceLen*SizeOf(Char));
एक आश्चर्य हो सकता है तो क्या होता है Source[i]
खाली है। उस स्थिति में Pointer(Source[i])
nil
है और आप पहुंच उल्लंघन की अपेक्षा कर सकते हैं। वास्तव में, कोई त्रुटि नहीं है क्योंकि तीसरे तर्क द्वारा निर्दिष्ट चाल की लंबाई शून्य है, और nil
पॉइंटर वास्तव में कभी-कभी संदर्भित नहीं होता है।
टिप्पणी की दूसरी लाइन यहाँ है:
DestPtr := PChar(Pointer(Dest)) + OriginalDestLen;
हम PChar(Pointer(Dest))
बजाय PChar(Dest)
का उपयोग करें। उत्तरार्द्ध यह जांचने के लिए कोड आमंत्रित करता है कि Dest
खाली है या नहीं, और यदि ऐसा होता है तो एक पॉइंटर को एक नल-टर्मिनेटर में मिलता है। हम उस कोड को निष्पादित करने से बचना चाहते हैं, और Dest
में दिए गए पते को सीधे प्राप्त करें, भले ही यह nil
हो।
स्रोत
2015-11-03 09:13:38
RTL इस तरह के एक समारोह है। * System.pas * में '_LStrCatN' और इसके यूनिकोड समकक्ष देखें। जब आप एक ही कथन में तीन से अधिक तारों को जोड़ते हैं, तो संकलक स्वचालित रूप से उस फ़ंक्शन पर कॉल उत्पन्न करता है, जैसा कि 's1 + s2 + s3 + s4 + s5' में होता है। आरटीएल समारोह में एक ही इंटरफ़ेस नहीं है; यह एक सरणी के बजाय स्टैक पर तारों की अपनी सूची स्वीकार करता है। जब तक आप असेंबली लिखते हैं तब तक आप आरटीएल फ़ंक्शन को सीधे कॉल नहीं कर सकते। –