Fortran
ऐतिहासिक सुविधाओं के लिए आधुनिक विकल्प
खोज…
अव्यय चर प्रकार
जब फोरट्रान मूल रूप से विकसित किया गया था स्मृति एक प्रीमियम पर था। चर और प्रक्रिया नाम अधिकतम 6 वर्ण हो सकते हैं, और चर अक्सर अनुमानित टाइप किए जाते थे। इसका अर्थ है कि चर नाम का पहला अक्षर इसके प्रकार को निर्धारित करता है।
- I, j, ..., n से शुरू होने वाले चर
integer
- बाकी सब कुछ (ए, बी, ..., एच, और ओ, पी, ..., जेड)
real
निम्नलिखित जैसे कार्यक्रम स्वीकार्य हैं फोरट्रान:
program badbadnotgood
j = 4
key = 5 ! only the first letter determines the type
x = 3.142
print*, "j = ", j, "key = ", key, "x = ", x
end program badbadnotgood
आप अपने स्वयं के निहित नियमों को भी implicit
बयान के साथ परिभाषित कर सकते हैं:
! all variables are real by default
implicit real (a-z)
या
! variables starting with x, y, z are complex
! variables starting with c, s are character with length of 4 bytes
! and all other letters have their default implicit type
implicit complex (x,y,z), character*4 (c,s)
अवैध टाइपिंग को अब सबसे अच्छा अभ्यास नहीं माना जाता है। अंतर्निहित टाइपिंग का उपयोग करके गलती करना बहुत आसान है, क्योंकि टाइपो किसी का ध्यान नहीं जा सकता है, जैसे
program oops
real :: somelongandcomplicatedname
...
call expensive_subroutine(somelongandcomplEcatedname)
end program oops
यह कार्यक्रम खुशी से चलेगा और गलत काम करेगा।
निहित टाइपिंग को बंद करने के लिए, implicit none
कथन का उपयोग नहीं किया जा सकता है।
program much_better
implicit none
integer :: j = 4
real :: x = 3.142
print*, "j = ", j, "x = ", x
end program much_better
यदि हमने ऊपर दिए प्रोग्राम oops
में implicit none
का उपयोग implicit none
किया है, तो संकलक ने तुरंत ध्यान दिया होगा, और एक त्रुटि उत्पन्न की होगी।
कथन यदि अंकगणित
अंकगणितीय if
कथन एक अंकगणितीय अभिव्यक्ति के परिणाम के आधार पर तीन शाखाओं का उपयोग करने की अनुमति देता है
if (arith_expr) label1, label2, label3
if
यह कथन किसी कोड में लेबल में से किसी एक पर नियंत्रण प्रवाह स्थानांतरित करता है। यदि arith_expr
का परिणाम नकारात्मक label1
शामिल है, यदि परिणाम शून्य label2
का उपयोग किया जाता है, और यदि परिणाम सकारात्मक है तो अंतिम label3
लागू होता है। अंकगणित if
सभी तीन लेबल की आवश्यकता है, लेकिन यह लेबल के पुन: उपयोग की अनुमति देता है, इसलिए इस कथन को दो शाखा में सरल किया जा सकता है if
।
उदाहरण:
if (N * N - N / 2) 130, 140, 130
if (X) 100, 110, 120
अब यह सुविधा समान कार्यक्षमता के साथ अप्रचलित है if
स्टेटमेंट और if-else
निर्माण द्वारा। उदाहरण के लिए, टुकड़ा
if (X) 100, 110, 120
100 print*, "Negative"
goto 200
110 print*, "Zero"
goto 200
120 print*, "Positive"
200 continue
हो सकता है कि if-else
निर्माण के रूप में लिखा जाए
if (X<0) then
print*, "Negative"
else if (X==0) then
print*, "Zero"
else
print*, "Positive"
end if
if
एक बयान के लिए प्रतिस्थापन
if (X) 100, 100, 200
100 print *, "Negative or zero"
200 continue
शायद
if (X<=0) print*, "Negative or zero"
गैर-ब्लॉक DO निर्माण करता है
गैर ब्लॉक do
की तरह दिखता है निर्माण
integer i
do 100, i=1, 5
100 print *, i
वह है, जहां लेबल समाप्ति कथन एक continue
बयान नहीं है। बयान पर विभिन्न प्रतिबंध हैं जिन्हें समाप्ति कथन के रूप में इस्तेमाल किया जा सकता है और पूरी बात आम तौर पर बहुत भ्रामक है।
इस तरह के एक गैर-ब्लॉक निर्माण को ब्लॉक रूप में फिर से लिखा जा सकता है
integer i
do 100 i=1,5
print *, i
100 continue
या बेहतर, समाप्ति कथन का उपयोग end do
हुए,
integer i
do i=1,5
print *, i
end do
वैकल्पिक वापसी
वैकल्पिक वापसी एक सबरूटीन से वापसी पर निष्पादन के प्रवाह को नियंत्रित करने की सुविधा है। इसे अक्सर त्रुटि से निपटने के रूप में उपयोग किया जाता है:
real x
call sub(x, 1, *100, *200)
print*, "Success:", x
stop
100 print*, "Negative input value"
stop
200 print*, "Input value too large"
stop
end
subroutine sub(x, i, *, *)
real, intent(out) :: x
integer, intent(in) :: i
if (i<0) return 1
if (i>10) return 2
x = i
end subroutine
वैकल्पिक रिटर्न को तर्कों *
द्वारा सबरूटीन डमी तर्क सूची में चिह्नित किया गया है।
*100
और *200
ऊपर के call
स्टेटमेंट में क्रमशः 100
और 200
लेबल वाले स्टेटमेंट्स देखें।
सबरूटीन में ही वैकल्पिक रिटर्न के return
दिए गए विवरणों में एक संख्या होती है। यह संख्या एक रिटर्न वैल्यू नहीं है, लेकिन प्रदान किए गए लेबल को दर्शाता है, जिस पर रिटर्न पर अमल किया जाता है। इस स्थिति में, 100
लेबल किए गए स्टेटमेंट में return 1
पास निष्पादन return 2
और 200
लेबल वाले स्टेटमेंट के लिए return 2
पास निष्पादन देता है। एक सादा return
विवरण, या सबरूटीन निष्पादन के पूरा होने के एक के बिना return
बयान, कॉल बयान के तुरंत बाद के passess निष्पादन।
वैकल्पिक रिटर्न सिंटैक्स तर्क संघ के अन्य रूपों से बहुत अलग है और सुविधा आधुनिक स्वाद के विपरीत प्रवाह नियंत्रण का परिचय देती है। अधिक मनभावन प्रवाह नियंत्रण को पूर्णांक "स्थिति" कोड की वापसी के साथ प्रबंधित किया जा सकता है।
real x
integer status
call sub(x, 1, status)
select case (status)
case (0)
print*, "Success:", x
case (1)
print*, "Negative input value"
case (2)
print*, "Input value too large"
end select
end
subroutine sub(x, i, status)
real, intent(out) :: x
integer, intent(in) :: i
integer, intent(out) :: status
status = 0
if (i<0) then
status = 1
else if (i>10)
status = 2
else
x = i
end if
end subroutine
फिक्स्ड सोर्स फॉर्म
फोरट्रान मूल रूप से 80 कॉलम वाले कार्ड के आधार पर एक निश्चित प्रारूप के लिए डिज़ाइन किया गया था:
हां: यह लेखक के अपने कोड की एक पंक्ति है
इन्हें कार्ड पंच मशीन पर बनाया गया था, जो इस प्रकार है:
लेखक द्वारा छवियाँ मूल फोटोग्राफी हैं
प्रारूप, जैसा कि सचित्र नमूना कार्ड पर दिखाया गया है, पहले पांच कॉलम स्टेटमेंट लेबल के लिए आरक्षित थे। पहले स्तंभ का उपयोग पत्र C द्वारा टिप्पणियों को दर्शाने के लिए किया गया था। छठे स्तंभ का उपयोग एक बयान निरंतरता को निरूपित करने के लिए किया गया था (शून्य '0' के अलावा किसी भी वर्ण को सम्मिलित करके)। अंतिम 8 कॉलम का उपयोग कार्ड की पहचान और अनुक्रमण के लिए किया गया था, जो कि आपके कार्ड के डेक को फर्श पर गिरा देने पर काफी मूल्यवान था! छिद्रित कार्ड के लिए वर्ण कोडिंग में केवल पात्रों का एक सीमित सेट था और केवल ऊपरी मामला था। परिणामस्वरूप, फोरट्रान कार्यक्रम इस तरह दिखते थे:
DIMENSION A(10) 00000001
C THIS IS A COMMENT STATEMENT TO EXPLAIN THIS EXAMPLE PROGRAM 00000002
WRITE (6,100) 00000003
100 FORMAT(169HTHIS IS A RATHER LONG STRING BEING OUTPUT WHICH GOES OVE00000004
1R MORE THAN ONE LINE, AND USES THE STATEMENT CONTINUATION MARKER IN00000005
2COLUMN 6, AND ALSO USES HOLLERITH STRING FORMAT) 00000006
STOP 00000007
END 00000008
अंतरिक्ष वर्ण को भी हर जगह नजरअंदाज कर दिया गया, सिवाय एक हॉलेरिथ के चरित्र के अंदर (जैसा कि ऊपर दिखाया गया है)। इसका मतलब था कि रिक्त स्थान आरक्षित शब्दों और स्थिरांक के अंदर हो सकते हैं, या पूरी तरह से छूट सकते हैं। इसके कुछ भ्रामक कथनों का दुष्प्रभाव था जैसे:
DO 1 I = 1.0
वैरिएबल DO1I
असाइनमेंट है जबकि:
DO1I = 1,0
वास्तव में चर I
पर एक DO
लूप है।
आधुनिक फोरट्रान को अब इनपुट के इस निश्चित रूप की आवश्यकता नहीं है और किसी भी कॉलम का उपयोग करके मुफ्त फॉर्म की अनुमति देता है। टिप्पणियाँ अब एक द्वारा इंगित कर रहे हैं !
जिसे स्टेटमेंट लाइन में भी जोड़ा जा सकता है। रिक्त स्थान अब कहीं भी अनुमति नहीं है और विभाजक के रूप में उपयोग किया जाना चाहिए, अधिकांश अन्य भाषाओं में। उपरोक्त कार्यक्रम को आधुनिक फोरट्रान में लिखा जा सकता है:
! This is a comment statement to explain this example program
Print *,"THIS IS A RATHER LONG STRING BEING OUTPUT WHICH no longer GOES OVER MORE THAN ONE LINE, AND does not need to USE THE STATEMENT CONTINUATION MARKER IN COLUMN 6, or the HOLLERITH STRING FORMAT"
यद्यपि पुरानी शैली की निरंतरता का उपयोग नहीं किया जाता है, उपरोक्त उदाहरण से पता चलता है कि बहुत लंबे बयान अभी भी आएंगे। आधुनिक फोरट्रान निरंतरता के अंत और शुरुआत में एक &
प्रतीक का उपयोग करता है। उदाहरण के लिए, हम उपरोक्त को अधिक पठनीय रूप में लिख सकते हैं:
! This is a comment statement to explain this example program
Print *,"THIS IS A RATHER LONG STRING BEING OUTPUT WHICH still &
&GOES OVER MORE THAN ONE LINE, AND does need to USE THE STATEMENT &
&CONTINUATION notation"
सामान्य ब्लॉक
फोरट्रान और कार्यों से दिखाई देने वाले वैश्विक वैरिएबल स्टोर बनाने के लिए फोरट्रान के शुरुआती रूपों में COMMON
ब्लॉक तंत्र का उपयोग करना है। इसने चर के अनुक्रमों को नाम और आम में साझा करने की अनुमति दी।
नामित कॉमन ब्लॉक्स के अलावा एक ब्लैंक (अनाम) कॉमन ब्लॉक भी हो सकता है।
एक रिक्त आम ब्लॉक की तरह घोषित किया जा सकता है
common i, j
जबकि नामित ब्लॉक variables
की तरह घोषित किया जा सकता है
common /variables/ i, j
एक पूर्ण उदाहरण के रूप में, हम एक हीप स्टोर की कल्पना कर सकते हैं जो रूटीन द्वारा उपयोग किया जाता है जो मूल्यों को जोड़ और हटा सकता है:
PROGRAM STACKING
COMMON /HEAP/ ICOUNT, ISTACK(1023)
ICOUNT = 0
READ *, IVAL
CALL PUSH(IVAL)
CALL POP(IVAL)
END
SUBROUTINE PUSH(IVAL)
COMMON /HEAP/ ICOUNT, ISTACK(1023)
ICOUNT = ICOUNT + 1
ISTACK(ICOUNT) = IVAL
RETURN
END
SUBROUTINE POP(IVAL)
COMMON /HEAP/ ICOUNT, ISTACK(1023)
IVAL = ISTACK(ICOUNT)
ICOUNT = ICOUNT - 1
RETURN
END
आम बयानों का उपयोग एक चर के प्रकार को स्पष्ट रूप से घोषित करने और dimension
विशेषता को निर्दिष्ट करने के लिए किया जा सकता है। अकेले यह व्यवहार अक्सर भ्रम का एक पर्याप्त स्रोत है। इसके अलावा, निहित भंडारण संघ और कार्यक्रम इकाइयों में दोहराया परिभाषाओं के लिए आवश्यकताओं को आम ब्लॉक त्रुटियों के लिए उपयोग करता है।
अंत में, सामान्य ब्लॉक उन वस्तुओं में बहुत प्रतिबंधित हैं जो उनके पास हैं। उदाहरण के लिए, एक सामान्य ब्लॉक में एक सरणी स्पष्ट आकार की होनी चाहिए; आवंटन योग्य वस्तुएँ नहीं हो सकती हैं; व्युत्पन्न प्रकारों में डिफ़ॉल्ट आरंभीकरण नहीं होना चाहिए।
आधुनिक फ़ोर्ट्रान में चर के बंटवारे को मॉड्यूल के उपयोग द्वारा नियंत्रित किया जा सकता है। उपरोक्त उदाहरण के रूप में लिखा जा सकता है:
module heap
implicit none
! In Fortran 2008 all module variables are implicitly saved
integer, save :: count = 0
integer, save :: stack(1023)
end module heap
program stacking
implicit none
integer val
read *, val
call push(val)
call pop(val)
contains
subroutine push(val)
use heap, only : count, stack
integer val
count = count + 1
stack(count) = val
end subroutine push
subroutine pop(val)
use heap, only : count, stack
integer val
val = stack(count)
count = count - 1
end subroutine pop
end program stacking
नामांकित और रिक्त सामान्य ब्लॉक में थोड़ा अलग व्यवहार होता है। टिप्पणी का:
- सामान्य ब्लॉक नाम की वस्तुओं को शुरू में परिभाषित किया जा सकता है; रिक्त आम वस्तुएं नहीं होंगी
- रिक्त कॉमन ब्लॉक्स में वस्तुएं व्यवहार करती हैं जैसे कि कॉमन ब्लॉक में
save
एट्रिब्यूट है;save
विशेषता के बिना नाम वाले सामान्य ब्लॉकों में ऑब्जेक्ट तब अपरिभाषित हो सकते हैं जब ब्लॉक एक सक्रिय प्रोग्राम यूनिट के दायरे में न हो
इस बाद वाले बिंदु को आधुनिक कोड में मॉड्यूल चर के व्यवहार के साथ विपरीत किया जा सकता है। फोरट्रान 2008 में सभी मॉड्यूल चर स्पष्ट रूप से सहेजे गए हैं और मॉड्यूल के दायरे से बाहर जाने पर अपरिभाषित नहीं होते हैं। फोरट्रान 2008 मॉड्यूल चर से पहले, नामांकित सामान्य ब्लॉकों में चर की तरह, मॉड्यूल के दायरे से बाहर जाने पर भी अपरिभाषित हो जाएगा।
GOTO को सौंपा
असाइन किया गया GOTO पूर्णांक चर का उपयोग करता है जिसमें ASSIGN स्टेटमेंट का उपयोग करके एक स्टेटमेंट लेबल दिया जाता है।
100 CONTINUE
...
ASSIGN 100 TO ILABEL
...
GOTO ILABEL
असाइन किया गया GOTO, फोरट्रान 90 और फोरट्रान 95 में और बाद में हटा दिया गया है। प्रक्रियाओं, आंतरिक प्रक्रियाओं, प्रक्रिया बिंदुओं और अन्य सुविधाओं का उपयोग करके आधुनिक कोड में इसे टाला जा सकता है।
गणना की गई गोटो
कंप्यूटेड गोटो एक पूर्णांक अभिव्यक्ति के मूल्य के अनुसार कार्यक्रम की शाखाकरण की अनुमति देता है।
GOTO (label_1, label_2,... label_n) scalar-integer-expression
यदि scalar-integer-expression
1 के बराबर है, तो प्रोग्राम स्टेटमेंट label_1
पर जारी label_1
, यदि यह 2 के बराबर है तो यह label_2
और इसी तरह label_2
। यदि यह कम है तो अगली पंक्ति पर n
प्रोग्राम की तुलना में 1
या बड़ा जारी है।
उदाहरण:
ivar = 2
...
GOTO (10, 20, 30, 40) ivar
स्टेटमेंट लेबल 20 पर कूदेंगे।
goto
का यह रूप फोरट्रान 95 और बाद में, select case
कंस्ट्रक्शन द्वारा अलग किया गया है।
निर्दिष्ट प्रारूप निर्दिष्ट करता है
फोरट्रान 95 से पहले इनपुट या आउटपुट के लिए निर्दिष्ट प्रारूप का उपयोग करना संभव था। विचार करें
integer i, fmt
read *, i
assign 100 to fmt
if (i<100000) assign 200 to fmt
print fmt, i
100 format ("This is a big number", I10)
200 format ("This is a small number", I6)
end
assign
स्टेटमेंट एक पूर्णांक चर के लिए एक स्टेटमेंट लेबल प्रदान करता है। इस पूर्णांक चर को बाद में print
स्टेटमेंट में प्रारूप विनिर्देशक के रूप में उपयोग किया जाता है।
इस तरह के प्रारूप निर्दिष्ट असाइनमेंट को फोरट्रान 95 में हटा दिया गया था। इसके बजाय, अधिक आधुनिक कोड निष्पादन प्रवाह नियंत्रण के कुछ अन्य रूप का उपयोग कर सकता है
integer i
read *, i
if (i<100000) then
print 100, i
else
print 200, i
end if
100 format ("This is a big number", I10)
200 format ("This is a small number", I6)
end
या एक चरित्र चर प्रारूप विनिर्देशक के रूप में इस्तेमाल किया जा सकता है
character(29), target :: big_fmt='("This is a big number", I10)'
character(30), target :: small_fmt='("This is a small number", I6)'
character(:), pointer :: fmt
integer i
read *, i
fmt=>big_fmt
if (i<100000) fmt=>small_fmt
print fmt, i
end
कथन कार्य
कार्यक्रम पर विचार करें
implicit none
integer f, i
f(i)=i
print *, f(1)
end
यहाँ f
एक स्टेटमेंट फंक्शन है। इसका पूर्णांक परिणाम प्रकार होता है, जो एक पूर्णांक डमी तर्क लेता है। 1
ऐसा स्टेटमेंट फंक्शन उस दायरे के भीतर मौजूद होता है जिसमें इसे परिभाषित किया जाता है। विशेष रूप से, इसकी चर और पहुंच वाले नाम हैं, जो उस दायरे में सुलभ हैं।
हालाँकि, स्टेटमेंट फ़ंक्शंस कई प्रतिबंधों के अधीन हैं और संभावित रूप से भ्रमित कर रहे हैं (एक कैजुअल एलीमेंट असाइनमेंट स्टेटमेंट की तरह आकस्मिक नज़र में)। महत्वपूर्ण प्रतिबंध हैं:
- फ़ंक्शन परिणाम और डमी तर्क स्केलर होना चाहिए
- डमी तर्क फ़ंक्शन के समान दायरे में हैं
- बयान कार्यों का कोई स्थानीय चर नहीं है
- बयान कार्यों को वास्तविक तर्कों के रूप में पारित नहीं किया जा सकता है
बयान कार्यों का मुख्य लाभ आंतरिक कार्यों द्वारा दोहराया जाता है
implicit none
print *, f(1)
contains
integer function f(i)
integer i
f = i
end function
end
आंतरिक फ़ंक्शन उपरोक्त उल्लिखित प्रतिबंधों के अधीन नहीं हैं, हालांकि यह संभवतः ध्यान देने योग्य है कि एक आंतरिक उपप्रोग्राम में आगे आंतरिक उपप्रोग्राम नहीं हो सकता है (लेकिन इसमें कथन फ़ंक्शन हो सकता है)।
आंतरिक कार्यों का अपना दायरा है, लेकिन मेजबान संघ भी उपलब्ध है।
1 वास्तविक पुराने कोड उदाहरणों में, यह स्पष्ट नहीं होगा कि किसी स्टेटमेंट फ़ंक्शन के डमी तर्क को स्पष्ट रूप से टाइप किया जा रहा है, भले ही परिणाम स्पष्ट प्रकार का हो।