حسین اتحادی سه شنبه 14 آبان 1398 06:06 ب.ظ نظرات ()

توابع یک خطی Statement Functions

وقتی توابعی که بکار می برید، آنچنان کوتاه هستند که در یک خط تمام می شوند، می توانید از این ساختار استفاده کنید.

Function_name({list of parameters}) = expression

مثلاً تابع نیوتن که در بالا تعریف شد را می توان با این ساختار به شکل زیر نوشت.

Newton(m1, m2, r) = -6.672E-11*m1*m2/r**2

زیربرنامه های خارجی External Subroutines

ساختار زیر برنامه ها به شکل زیر است.


SUBROUTINE name {dummy argument list}
   local variables declaration
   body of subroutine…
END SUBROUTINE name

در فرترن تمام متغیرها با آدرس فرستاده می شوند “call by reference” (مانند VAR arg در Pascal یا &arg در C++)، یعنی آدرس متغیر در حافظه به زیربرنامه فرستاده می شود، و زیربرنامه می تواند متغیر را مستقیماً تغییر دهد. در توابع نیز چنین است، اما فرض می گردد که توابع متغیرهای ورودی را تغییر نمی دهند.

دستورات RETURN, SAVE, EXTERNAL, INTERNAL

همه روالهای خوب باید یک نقطه ورود و یک نقطه خروج داشته باشند، اما گاهی لازم است که زیربرنامه در نقطه ای دیگر پایان یابد (برای مثال هنگام ایجاد خطا). برای اینکار از دستور RETURN استفاده می گردد. این دستور اجرای زیر برنامه را متوقف کرده و برنامه را به روال فراخوانی کننده این زیر برنامه باز می گرداند.

پس از پایان یک زیربرنامه، مقدار همه متغیرهای محلی از بین می رود. اگر بخواهیم این مقادیر در اجرای بعدی زیربرنامه موجود باشد(STATIC ALLOCATION)، باید این موضوع را برای مترجم مشخص کنیم تا مترجم بداند که باید مقدار متغیرها را ذخیره کند. این موضوع را با دستور SAVE به مترجم اصلاع می دهیم. ساختار این دستور به این شکل است:

 SAVE [{list of local variables to be saved}]

وقتی یک تابع بعنوان متغیر به یک روال دیگر فرستاده می شود، نوع تابع باید قبل از ارسال بعنوان داخلی یا خارجی تعریف گردد. این تعریف با دستورات زیر صورت می گیرد.

INTRINSIC {list of function names} EXTERNAL {list of function names}

برای مثال

PROGRAM func
EXTERNAL CTN
INTRINSIC SIN, COS
REAL::angle=0.785 !...pi/4
REAL::sine,cosine,tangent
CALL TRIG(angle,SIN,sine)
WRITE(*,*) 'SIN(0.785)=',sine
CALL TRIG(angle,COS,cosine)
WRITE(*,*) 'COS(0.785)=',cosine
CALL TRIG(angle,CTN,cotangent)
WRITE(*,*) 'COTAN(0.785)=',cotangent
PAUSE
END PROGRAM func
SUBROUTINE TRIG(X,F,Y)
Y = F(X)
RETURN
END SUBROUTINE TRIG
FUNCTION CTN(X)
CTN = COS(X)/SIN(X)
RETURN
END FUNCTION CTN

ساختارهای کنترلی

ساختارهای کنترلی جهت اجرای برنامه را کنترل می کنند.

ساختار IF

این ساختار یک ساختار تصمیم گیری است. در این ساختار بنابر حاصل یک مقایسه اجرای برنامه به جای دیگری منتقل می شود. ساختار عمومی آن به شکل زیر است.


IF (First condition statement) THEN
   First sequence of commands
ELSE IF (Second condition statement) THEN
   Second sequence of commands
ELSE IF …
   …
ELSE
   Alternative sequence of commands
END IF

برای مثال برای یافتن علامت یک عدد می توان از بخش زیر استفاده کرد:

IF (number .LT. 0) THEN
sign=-1
ELSE IF (number .GT. 0) THEN
sign=1
ELSE
sign=0
END IF
view rawsignWithIF.f90 hosted with ❤ by GitHub

می توان برای اجرای یک IF با یک دستور، آنرا در یک خط خلاصه کرد. در این حالت از THEN ، ELSE و END IF صرفنظر می شود.


IF (Condition statement) Statement to be executed
IF (r==0) WRITE(*,*) 'r=0'

حلقه Do

این حلقه برای تکرار بخشی از برنامه است. چون استفاده از حلقه GOTO در برنامه نویسی پیشرفته بسیار بد است (گفته می شود که امکان اشتباه این دستور بسیار زیاد است). در هر حال جالب نیست که در هنگام اجرای برنامه به بخش دیگری پرش کرد، حداقل اینکار خوانایی برنامه را بسیار کاهش خواهد داد. ساختار دستوری استفاده از حلقه DO به شکل زیر است:

label: DO counter=start, limit, step Sequence of commands to be looped through END DO label

برای پیاده سازی حلقه های دیگر مثل حلقه for و while در زبان C می توان از دستورات زیر استفاده کرد. دستور EXIT برای خروج از اجرای حلقه و دستور CYCLE برای تکرار حلقه از ابتدا می باشد. برای استفاده از این دستورات باید برای حلقه ها برچسب (label) در نظر گرفت این کار را با دقت بسیار زیاد انجام دهید زیرا اینکار نیز مانند استفاده از دستور GOTO است! ساختار این دستورات به شکل زیر است:

EXIT [name of loop]
CYCLE [name of loop]

پیشنهاد می کنم تا جای ممکن از این دستورات استفاده نکنید، چون شما می توانید بجای استفاده از این دستورات با تغییراتی در کد برنامه را به شکل دیگری بنویسید. به مثال زیر توجه کنید که برای روشنتر شدن روش استفاده از این دستورات بیان شده است. در این مثال داده های موجود در یک آرایه بترتیب جذر گرفته و معکوس می گردد. مشخص است که اعداد نباید صفر یا منفی باشند.

REAL:: array(5)
Outer: DO
READ(*,*) array
Inner: DO k=1, 5
IF (array(k)==0) CYCLE inner
IF (array(k)<0) EXIT
Array(k)=1/SQRT(array(k))
END DO inner
WRITE(*,*) array
END DO outer
view rawDoInDo.f90 hosted with ❤ by GitHub

در برنامه بالا یک حلقه بینهایت وجود دارد (حلقه DO بدون محدودیت). برای خروج از چنین حلقه هایی از دستور EXIT استفاده می گردد.
ساختار حلقه DO در فرترن 77 بشکل زیر است:


DO label, counter=start, limit, step
    Sequence of commands to be looped through
label CONTINUE

دستور GOTO

از این دستور تا حد امکان استفاده نکنید. ساختار این دستور بسیار ساده است.

GOTO label

و یک برچسب در هر جای برنامه که بخواهید! و اجرای برنامه به آن محل منتقل می گردد.

دستور GOTO شرطی

استفاده از این دستور هم مانند دستور قبل منع شده است.

دستور STOP

اگر بخواهیم برنامه را متوقف کنیم و کنترل را به سیستم عامل بازگردانیم! از این دستور استفاده می گردد. ساختار این دستور به شکل زیر است:

STOP [‘message’]

آرایه ها Arrays

یکی از مهمترین ساختارهای داده در برنامه نویسی مهندسی آرایه ها هستند مخصوصاً وقتی با تعداد زیادی عدد در نقاط مختلف کار می کنیم. ساختار آرایه ها مانند انواع دیگر داده ها می باشد فقط تعداد داده ها مشخص می گردد. البته در شرایطی که می خواهیم که تعداد بصورت دینامیک اختصاص داده شود، تعداد را مشخص نمی کنیم.

type array_name({lower bound in nth dimention:Upper bound in nth dimention})

برای مثال فرض کنید که می خواهید داده های دمای نقاط در یک شبکه را ذخیره کنید، نوع داده را اعداد حقیقی در نظر می گیریم. شماره نقاط در طول از 50 تا 70 می باشد و در عرض از 1 تا 20 است:

REAL:: temperature(50:70, 1:20)

یا

REAL:: temperature(50:70, 20)

حد پایین آرایه بصورت پیش فرض از یک شروع می شود. آرایه در فرترن 77 می تواند تا 7 بعد داشته باشد. آرایه ها بترتیب ستون در حافظه قرار می گیرند و اگر بخواهیم با دستور DO به آرایه ها دسترسی داشته باشیم بهتر است که حلقه شمارنده ستونها داخل حلقه شمارنده سطر ها قرار گیرد (برای سرعت دسترسی بالاتر). دسترسی به هریک از اجزائ آرایه ها با استفاده از اندیسهای آن صورت می گیرد، البته دستوراتی در فرترن 90 وجود دارد که کار با آرایه ها را سریعتر و کارآمدتر کرده است و در صورتی که چنین دستوراتی وجود داشته باشد، از آنها استفاده کنید. مخصوصاً اگر برای استفاده از کامپیوترهای چند پردازنده ای برنامه نویسی می کنید.

در مثال بالا فرض کنید که دمای نقطه ای با طول 55 و عرض 12 را بیابیم و در متغیر temp قرار دهیم و همچنین دمای نقطه 56 و 13 را برابر 400 کلوین قرار دهیم.

temp = temperature(55,12)
temperature(56,13) = 400.0

برای خواندن یا چاپ آرایه ها می توان اندیسها را نادیده گرفت تا عمل مورد نظر روی کل آرایه انجام گیرد. برای مثال برای نمایش کل آرایه temperatureروی صفحه نمایش از دستور زیر استفاده کرد.

WRITE(*,*) temperature

این نمایش در صورتی که تعداد اعضاء در یک سطر جا نگیرد کمی گیج کننده است.

ارسال آرایه بعنوان یک پارامتر به تابع

بسیاری از موارد شما می خواهید که یک آرایه را به یک تابع ارسال کنید, تنها مشکل عدم اطلاع آرایه از اندازه خودش می باشد, پس باید آرایه فرستاده شده به تابع دارای اندازه ثابت باشد (fixed-size array) یا باید اندازه آرایه را هم بعنوان یک پارامتر دیگر به تابع ارسال کنیم تا مبادا از مرزهای آرایه فراتر برویم! اگر اندازه آرایه مشخص نباشد می توانیم آن آرایه را با آرگومان * برای آخرین پارامتر آرایه (فقط یک بعد از آرایه را می توان به این شکل تعریف کرد) به تابع ارسال کنیم. در هر حال بخاطر داشته باشید که مترجم برنامه از طول آرایه اطلاع نخواهد داشت و شما خودتان باید مطمئن شوید که فراتر از محدوده اعضاء آرایه نروید.