2012-08-08 6 views
6

मुझे कुछ फोरट्रान 90 कोड का अनुवाद करना है और एक दिलचस्प भाषा सुविधा मिली है।अभिलेखों की एक सरणी को देखते हुए, मैं प्रत्येक से एक फ़ील्ड का प्रतिनिधित्व करने वाला सरणी कैसे प्राप्त कर सकता हूं?

TYPE WallInfo 
    CHARACTER(len=40) :: Name 
    REAL    :: Azimuth 
    REAL    :: Tilt 
    REAL    :: Area 
    REAL    :: Height 
END TYPE WallInfo 

TYPE(WallInfo), ALLOCATABLE, DIMENSION(:) :: Wall 

कोड में बाद में, वे एक समारोह फोन:

एक उदाहरण के रूप में, वे निम्न प्रकार के और गतिशील सरणी चर को परिभाषित,

CALL HeatFlow(Wall%Area, Wall%Azimuth) 

एक डेल्फी प्रोग्रामर के रूप में इस फेंक दिया मुझे थोड़ा सा क्योंकि दीवार रिकॉर्ड की एक सरणी है!

दिनचर्या में उपयोग से, यह स्पष्ट है कि फोरट्रान रिकॉर्ड सरणी से खेतों को अपने स्वयं के सरणी के रूप में प्रोजेक्ट कर सकता है।

SUBROUTINE HeatFlow(Area, Azimuth) 
    REAL, INTENT(IN), DIMENSION(:) :: Area 
    REAL, INTENT(IN), DIMENSION(:) :: Azimuth 

किसी को भी अगर वहाँ डेल्फी (मैं संस्करण 2010 का उपयोग कर रहा है) के साथ यह करने के लिए एक तरीका है पता है?

मैं एक सरणी के रूप में रिकॉर्ड मान निकालने के लिए एक फ़ंक्शन लिख सकता हूं लेकिन यह थोड़ा कठिन है क्योंकि मुझे हर क्षेत्र के लिए एक समर्पित दिनचर्या लिखनी होगी (और कुछ बहुत हैं)।

मुझे उम्मीद है कि डेल्फी 2010 में कुछ भाषा सुविधा है जिसे मैंने याद किया है।

+0

क्या आपने वॉलइन्फो के अपने केस सरणी में सरणी या रिकॉर्ड के साथ प्रयास किया था? डेल्फी समर्थन डाइनैमिक सरणी। नए मान दर्ज करने से पहले पहले सरणी के साथ सेटलेथ के आकार को सेट करें। –

+0

रेमी के आरटीटीआई उत्तर के रूप में ठंडा है, मैं उपरोक्त रिकॉर्ड प्रकार को अलग रैखिक सरणी में अनुवाद करने का लुत्फ उठाऊंगा: 'नाम: स्ट्रिंग का ऐरे; अजीमुथ: डबल का ऐरे; ... 'और फिर मुझे इस सुंदर आरटीटीआई हैक का उपयोग करके डेटा एकत्र नहीं करना पड़ेगा क्योंकि यह पहले ही इकट्ठा होगा। –

उत्तर

8

विस्तारित RTTI का उपयोग करना, यह एक सामान्य समारोह है कि सरणी और इनपुट के रूप में एक फ़ील्ड नाम लेता है बनाने के लिए संभव है और उस फ़ील्ड के मान निकालने के लिए सरणी के आरटीटीआई का उपयोग करता है और सही डेटा प्रकार के साथ उनके साथ एक नई सरणी बना देता है।

निम्नलिखित कोड XE2 में मेरे लिए काम करता है:

uses 
    System.SysUtils, System.Rtti; 

type 
    FieldArray<TArrElemType, TFieldType> = class 
    public 
    class function Extract(const Arr: TArray<TArrElemType>; const FieldName: String): TArray<TFieldType>; 
    end; 

class function FieldArray<TArrElemType, TFieldType>.Extract(const Arr: TArray<TArrElemType>; const FieldName: String): TArray<TFieldType>; 
var 
    Ctx: TRttiContext; 
    LArrElemType: TRttiType; 
    LField: TRttiField; 
    LFieldType: TRttiType; 
    I: Integer; 
begin 
    Ctx := TRttiContext.Create; 
    try 
    LArrElemType := Ctx.GetType(TypeInfo(TArrElemType)); 
    LField := LArrElemType.GetField(FieldName); 
    LFieldType := Ctx.GetType(TypeInfo(TFieldType)); 
    if LField.FieldType <> LFieldType then 
     raise Exception.Create('Type mismatch'); 
    SetLength(Result, Length(Arr)); 
    for I := 0 to Length(Arr)-1 do 
    begin 
     Result[I] := LField.GetValue(@Arr[I]).AsType<TFieldType>; 
    end; 
    finally 
    Ctx.Free; 
    end; 
end; 

type 
    WallInfo = record 
    Name: array[0..39] of Char; 
    Azimuth: Real; 
    Tilt: Real; 
    Area: Real; 
    Height: Real; 
    end; 

procedure HeatFlow(const Area: TArray<Real>; const Azimuth: TArray<Real>); 
begin 
    // Area contains (4, 9) an Azimuth contains (2, 7) as expected ... 
end; 

var 
    Wall: TArray<WallInfo>; 
begin 
    SetLength(Wall, 2); 

    Wall[0].Name := '1'; 
    Wall[0].Azimuth := 2; 
    Wall[0].Tilt := 3; 
    Wall[0].Area := 4; 
    Wall[0].Height := 5; 

    Wall[1].Name := '6'; 
    Wall[1].Azimuth := 7; 
    Wall[1].Tilt := 8; 
    Wall[1].Area := 9; 
    Wall[1].Height := 10; 

    HeatFlow(
    FieldArray<WallInfo, Real>.Extract(Wall, 'Area'), 
    FieldArray<WallInfo, Real>.Extract(Wall, 'Azimuth') 
    ); 
end; 
+0

आपकी मदद के लिए धन्यवाद, मैं इस विधि को आजमाने की कोशिश कर रहा हूं। मुझे एहसास हो रहा है कि प्रत्यक्ष अनुवाद इतना आसान नहीं है। फोर्ट्रान में कुछ अच्छी मैट्रिक्स विशेषताएं हैं लेकिन डेल्फी में इन्हें अनुकरण करने की कोशिश करना बहुत ही कुशल नहीं है। सरणी को पार करने के बजाय, मैंने बस एक ही पैरामीटर में पूरी दीवार सरणी पारित की। – bruce

+0

रेमी, मुझे लूप को I: = 0 से लंबाई (Arr) -1 में बदलना था, इसे डेल्फी 2010 में काम करने के लिए करना। मैं प्रभावित हूं, यह समस्या को हल करता है और बहुत साफ है। – bruce

+0

कोड XE2 में लिखा और परीक्षण किया गया था। क्या आप कह रहे हैं कि 'उच्च() 'डी 2010 में गतिशील सरणी पर काम नहीं करता है? मैंने उस परिवर्तन के साथ अपना जवाब अपडेट किया। –

2

अपने प्रश्न का उत्तर देने के लिए, नहीं, रिकॉर्ड की सरणी से एक ही कॉलम को अपने स्वयं के एक सरल सरणी में विभाजित करने के लिए कोई भाषा निर्माण या सुविधा विधि नहीं है।

function SplitColumn(RecordArray : Array of {recordtype}) : Array of {columntype}; 
var 
    column : array of {type}; 
    x : Integer; 
begin 
    setlength(result, high(RecordArray) + 1); 
    for x := 0 to high(RecordArray) do 
    result[ x ] := RecordArray[ x ].{columnname}; 
end; 

है कि आप गतिशील सरणियों उपयोग करना चाहते हैं:

मैं निम्नलिखित की तरह कुछ की सिफारिश करेंगे। व्यक्तिगत रूप से, अगर आप इस पोर्टिंग कर रहे हैं, मैं सूची और सूची, का उपयोग करेंगे के रूप में:

type 
    TWallList = class(TList<TWallInfo>); 
    TDoubleList = class(TList<Double>); 

function SplitColumn(WallList : TWallList; AreaList, AzimuthList : TDoubleList); 
var 
    x : Integer; 
begin 
    for x := 0 to RecList.Count-1 do 
    begin 
    AreaList.add(RecordArray[ x ].Area); 
    Azimuth.add(RecordArray[ x ].Azimuth); 
    end; 
end; 
+0

विस्तारित आरटीटीआई का उपयोग करना, एक जेनेरिक फ़ंक्शन बनाना संभव हो सकता है जो सरणी और फ़ील्ड नाम इनपुट के रूप में लेता है और उस फ़ील्ड के मानों को निकालने के लिए सरणी के आरटीटीआई का उपयोग करता है और उनके साथ एक नया सरणी बनाता है। –

+0

मैंने कार्रवाई में विस्तारित आरटीटीआई के डेमो के साथ एक उत्तर पोस्ट किया। –

7

मैं एक जवाब के रूप में इस पोस्टिंग कर रहा हूँ क्योंकि टिप्पणियों थोड़ा भी वाक्यांश यह करने के लिए सीमित हैं।

इस उत्तर सरणियों और FORTRAN और डेल्फी में रिकॉर्ड की स्मृति लेआउट में अन्तर को स्पष्ट करने की कोशिश करता है और Todd Grigsby द्वारा answer और Remy Lebeau द्वारा answer (मैं दोनों upvoted) हरजाना।

फ़ोरट्रान और कुछ अन्य गणना केंद्रित भाषाओं column major order में नेस्टेड सरणी संग्रहीत करती हैं। डेल्फी और कई अन्य भाषाएं row major order का उपयोग करती हैं।

  • एक नाम और नहीं एक सूचकांक है
  • विभिन्न प्रकार

गणना गहन के लिए हो सकता है:

एक स्मृति दृष्टिकोण से, एक रिकार्ड फ़ील्ड की एक सरणी की तुलना में और कुछ भी नहीं है संचालन, जब आपके एल्गोरिदम स्तंभों का पक्ष लेते हैं तो यह नेस्टेड सरणी कॉलम प्रमुख आदेश को स्टोर करने के लिए समझ में आता है। पंक्ति प्रमुख आदेश के लिए वही। तो लूप में, आपको match the order of your indexes with the order of your storage की आवश्यकता है।

इस रिकॉर्ड और सरणी FORTRAN में परिभाषा को देखते हुए:

TYPE WallInfo 
    CHARACTER(len=40) :: Name 
    REAL    :: Azimuth 
    REAL    :: Tilt 
    REAL    :: Area 
    REAL    :: Height 
END TYPE WallInfo 

TYPE(WallInfo), ALLOCATABLE, DIMENSION(:) :: Wall 

और डेल्फी में कार्यात्मक समकक्ष परिभाषा:

type 
    WallInfo = record 
    Name: array[0..39] of Char; 
    Azimuth: Real; 
    Tilt: Real; 
    Area: Real; 
    Height: Real; 
    end; 

var 
    Wall: array of WallInfo; 

और 3 WallInfo तत्वों की एक सरणी, यह कैसे स्मृति लेआउट है देखेंगे (वे सभी निरंतर मेमोरी एरिया होंगे, मैंने उन्हें पठनीय रखने के लिए लाइनों में विभाजित किया होगा):

फोरट्रान में:

Name[0,0]...Name[0,39], Name[1,0]...Name[1,39], Name[2,0]...Name[2,39], 
Azimuth[0], Azimuth[1], Azimuth[2], 
Tilt[0], Tilt[1], Tilt[2], 
Area[0], Area[1], Area[2], 
Height[0], Height[1], Height[2], 
डेल्फी में

:

Name[0,0]...Name[0,39], Azimuth[0], Tilt[0], Area[0], Height[0], 
Name[1,0]...Name[1,39], Azimuth[1], Tilt[1], Area[1], Height[1], 
Name[2,0]...Name[2,39], Azimuth[2], Tilt[2], Area[2], Height[2], 

तो यह FORTRAN कॉल:

कॉल HeatFlow (वॉल% क्षेत्र, वॉल% दिगंश)

सिर्फ संकेत दिए गए क्षेत्र के पास चला जाएगा [ 0] और अजीमुथ [0] स्मृति स्थानों और समारोह में उन स्मृति क्षेत्रों की लंबाई।

डेल्फी में, यह संभव नहीं है, तो आप

करने के लिए है
  1. का निर्माण नए क्षेत्र और दिगंश arays
  2. दीवार
  3. बुलाया WallInfo रिकॉर्ड उदाहरण के सरणी में जानकारी से उन्हें कॉपी उन्हें भेज समारोह
  4. यदि करने के लिए इन वर मानकों हैं: दो सरणियों से परिवर्तन दीवार
  5. को

वापस कॉपी Todd Grigsby और Remy Lebeau सीधे डेल्फी कोड, या डेल्फी रिकॉर्ड आरटीटीआई का उपयोग करके अपने उत्तर में पहले तीन चरणों को दिखाया।
चरण 4 इसी तरह से काम करता है।

दोनों समाधान जेनरिक कि डेल्फी 2009
Until Delphi 2010, RTTI on records was very minimal) में पेश किए गए का उपयोग करें, ताकि आप दोनों जवाब के लिए सही डेल्फी संस्करण मिला है।

नोट (दोबारा): फोरट्रान से डेल्फी तक अपने एल्गोरिदम का अनुवाद करते समय, सुनिश्चित करें कि आप कॉलम/पंक्ति प्रमुख परिवर्तन की वजह से सरणी में लूप और अन्य अनुक्रमण के लिए देखते हैं।

+0

जेरोइन, लूप इंडेक्सिंग के बारे में आपकी टिप्पणियों की सराहना की जाती है। मैं पहले से ही इस समस्या के खिलाफ ठोकर खाई है। मुझे डेल्फी और फोरट्रान के बीच सरणी आदेशों में अंतर के बारे में पता नहीं था। अब और अधिक समझ में आता है। – bruce

+0

मुझे खुशी है कि इससे अधिक अंतर्दृष्टि प्राप्त करने में मदद मिली। अच्छे प्रश्नों को जारी रखें! –

+0

मैं इस सवाल में कुछ भी नहीं देख सकता जो पंक्ति प्रमुख और कर्नल प्रमुख मुद्दों से संबंधित है। सवाल में वे कहां उठते हैं? प्रश्न प्रक्षेपण का समर्थन करने के लिए फोर्ट्रान सुविधा के बारे में मुझे लगता है। यह संभवतः एक लाइड एरे के साथ एक स्ट्रैड तकनीक के साथ लागू किया जाएगा। –

संबंधित मुद्दे

 संबंधित मुद्दे