بخش دوم آموزش برنامه‌نویسی را به زبان فرترن اختصاص داده‌ایم. فرترن زبانی بسیار قدرتمند (برای انجام محاسبات سنگین ریاضی) با روند یادگیری آسان است. این زبان علیرغم گذشت نیم قرن هنوز مورد استفاده جدی مهندسان است.
ابتدا از یک معرفی ساده شروع می کنم و همینطور که با دستور زبان فرترن آشنا خواهیم شد برنامه هایی برای درک بهتر برنامه نویسی خواهیم نوشت. پس لطفاً کامپایلر یا IDEخود را آماده کنید تا شروع کنیم.

بسیاری از مطالبی که در این بخش بیان خواهد شد مانند دستوراتی است که در الگوریتم نویسی از آنها استفاده نمودیم. دستوراتی که آنها را به عنوان شبه زبان معرفی کردیم. اگر الگوریتم نویسی را خوب نیاموخته اید پیشنهاد می کنم ابتدا آموزش الگوریتم نویسی را مطالعه نمایید و پس از آن به یادگیری زبان فرترن بپردازید! اجازه دهید شروع کنیم.

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

آموزش مقدماتی فرترن

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

معرفی و تاریخچه فرترن

همانطور که در اغلب کتابهای مکانیک دیده اید، در بسیاری از برنامه های مهندسی از این زبان استفاده می گردد. زبان برنامه نویسی فرترن با وجود سادگی از قدرت و سرعت بالایی برخوردار است، بطوریکه می توان از آن برای نوشتن برنامه های CFD استفاده کرد. فرترن اغلب با قابلیت فوق العاده در مورد اعداد معرفی می گردد و همانطور که از اسمش (FORmula TRANslation) پیداست، برای انجام محاسبات ریاضی در کارهای علمی خلق شده است. در گذشته این زبان دارای محدودیتهایی بوده که در نسخه های جدید این مشکلات حل شده است و این زبان به یک زبان بسیار قوی تبدیل شده است. اغلب کتابخانه های لازم برای انجام انواع محاسبات در این زبان وجود دارد. این زبان در استاندارد فرترن 90 از قابلیت نوشتن برنامه های محاسبات موازی برای کامپیوتر های چند پردازنده ای پشتیبانی می کند که آینده روشنی را برای محاسبات سنگین CFD نشان می دهد. در ویرایشهای بعدی این امکانات گسترش یافته است. این زبان جزء اولین زبانهای خلق شده برای کامپیوتر می باشد که در سال 1957 توسط تیمی به رهبری John Backus در شرکت IBM نوشته شده است. قابلیت محاسبات سریع با سادگی در برنامه نویسی باعث محبوبیت آن بین مهندسان و دانشمندان شده است. زبان فرترن در حال حاضر دارای قابلیت برنامه نویسی شیء گرا شده است.

در برنامه نویسی معمولاً از فرترن 77 و 90 استفاده می گردد که نسخه 90 آن محبوبیت عمومی تری دارد. در این متن از استاندارد های برنامه نویسی فرترن 90 استفاده می کنیم و در موارد لازم در مورد فرترن 77 هم بحث خواهیم کرد.

تاریخچه:

  • 1954 Fortran I
  • 1958 Fortran II
  • 1958 Fortran III
  • 1961 Fortran IV
  • 1966 Fortran 66 standard
  • 1978 Fortran 77 standard
  • 1991 Fortran 90 standard
  • 1997 Fortran 95 standard
  • 2004 Fortran 2003 standard
  • 2010 Fortran 2008 standard
  • 2018 Fortran 2015 standard

چرا فرترن؟

زبان اصلی برنامه نویسی در کاربردهای علمی فرترن است. اغلب کدهای قدیمی با این زبان نوشته شده است. بنابراین لازم است که یک دانشجوی مهندسی با این زبان آشنایی داشته باشد. سالها پیش به نظر می رسید که با پیشرفت و محبوبیت عمومی زبانهایی مانند C زبان فرترن منسوخ گردد، اما با گذشت سالها این زبان همچنان استفاده فراوان دارد. این ماندگاری مدیون کتابخانه ها و کدهای موجود این زبان است. در هر حال استانداردهای جدید این زبان قدرت زیادی به این زبان داده است. این زبان همچنان بعنوان مهمترین زبان برای مهندسان و دانشمندان بشمار می آید. فرترن برای انجام محاسبات ریاضی با سرعت و قابلیت بالا طراحی شده است. البته زبان فرترن هنوز در ایجاد محیط گرافیکی کمبود دارد و اگر بخواهید برای فرترن یک رابط گرافیکی کاربر(Graphical User Interface) بنویسید، باید خود را درگیر فراخوانی توابع ویندوز (API ها!) کنید. انتخاب راحت تر استفاده از یک زبان ساده مانند Visual Basic یا Delphi برای ایجاد رابط گرافیکی کاربر است. در این روش GUI را در این زبانها می سازیم و موتور اصلی برنامه برای کار با معادلات و انجام محاسبات را در FORTRAN می نویسیم و بعد آنرا با فرمت DLL (Dynamic Link Library) در اختیار برنامه قرار می دهیم. اینکار را در مراحل پیشرفته تر آموزش (سطح متوسط) به شما آموزش خواهم داد.

فرترن 90

فرترن 90 فراتر از یک ویرایش جدید از استاندارد فرترن می باشد و برنامه نویسی را بسیار آسانتر کرده است. این ویرایش کدهای فرترن 77 را نیز پشتیبانی می کند. فرترن 90 یک زبان برنامه نویسی انعطاف پذیر و قوی است, این زبان امکانات برنامه نویسی شیء گرا را داراست. امکانات دسترسی به امکانات سیستمی مانند تخصیص حافظه, استفاده از اشاره گرها و بسیاری امکانات دیگر به آن اضافه شده است؛ بعبارت دیگر فرترن 90 بیشتر شبیه به C++ است تا فرترن 77! ارتقاء قابلیتهای عددی, استفاده از دستورات حالت موازی (چند پردازنده ای) که یک پیشرفت شایان ذکر در برنامه نویسی علمی و نوشتن کدهای موازی می باشد. این روند در فرترن 95 دنبال شده است و انتظار می رود در ویرایش های جدیدتر این زبان امکانات گسترده تری برای برنامه نویسی علمی به این زبان اضافه گردد.

استانداردهای کدنویسی

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

  1. همه کلمات کلیدی این زبان را به یک شکل بنویسید (بزرگ یا کوچک بودن حروف را رعایت کنید). در گذشته کلمات کلیدی برنامه با حروف بزرگ و همه چیز دیگر را با حروف کوچک نوشته می شد (این زبان بین حروف کوچک و بزرگ فرقی نمی داند!). البته این ساختار آنچنان مناسب نمی باشد و می تواند خوانایی برنامه را کاهش دهد و دلیل استفاده از آن قدمت این روش است. در هر حال استفاده از این روش در برنامه نویسی مدرن کار درستی نیست.
  2. از دندانه دار کردن در متن اصلی برنامه و همچنین بلوکهای دیگر استفاده کنید.
  3. اسم برنامه ها، زیر برنامه ها و توابع را در انتهای آنها ذکر کنید.

ساختار برنامه فرترن

ساختار برنامه در فرترن 90 به ساختار زبانهای برنامه نویسی دیگر شباهت زیادی دارد و به شکل زیر است.

PROGRAM program_name
	! Comment and program information
	Declaration of variables and/or external functions
	Program body
END PROGRAM program_name
Declaration and body of user-made functions

یک برنامه فرترن ساده را ببینید:

ساختار برنامه در فرترن 77 کمی متفاوت و پیچیده تر است! در فرترن 77، کل صفحه به ستونهایی تقسیم می گردد و هر بخش از برنامه محل مشخصی دارد. برنامه فرترن 77 باید از قوانین زیر پیروی کند:

  • تمام دستورات فرترن باید بین ستون 7 تا 72 از فایل قرار داشته باشند.
  • فاصله خالی برای مترجم برنامه معنایی ندارد ولی برای خوانایی برنامه باید از آنها استفاده کرد!
  •  دستوراتی که در ستون 1 تا 5 آنها خالی است اما در ستون 6 کاراکتری غیر از صفر قرار دارد به عنوان ادامه دستورات خط قبل به حساب می آیند (حداکثر تا 19 خط مجاز است!).
  •  شماره خط دستورات باید بین ستون 1 تا 5 نوشته شوند و حداکثر می تواند یک عدد 5 رقمی باشد (فرترن به شماره خط نیازی ندارد و فقط برای ارجاع از دستوراتی مانند GOTO استفاده می گردد.
  •  توضیحات برنامه در ستون اول خود C دارند.
  •  خوب است که حداکثر با دو دندانه در برنامه بخشهای مختلف را مشخص کنید.

با توجه به توضیحات بالا ساختار برنامه فرترن 77 به شکل زیر است.

PROGRAM program_name
C Comment and program information
Declare of variables and/or external functions
Body of program
END PROGRAM program_name
Declaration an body of user-made functions

می توان مثال قبل را برای فرترن 77 به شکل زیر نوشت:

متغیرها

پیشنهاد می گردد که همه متغیرهای برنامه در ابتدای برنامه تعریف (تعیین نوع) گردند. برای اینکه هیچ متغیری از قلم نیفتد، از دستور IMPLICIT NONE در ابتدای برنامه استفاده کنید. این دستور به مترجم برنامه خواهد گفت که اگر در برنامه به متغیر تعریف نشده ای برخورد، اعلام خطا کند. البته فرترن به تعیین نوع نیازی ندارد! اما این کار خطاهای برنامه نویسی شما را کاهش خواند داد. زبانهای برنامه نویسی زیادی در اولین استفاده از متغیر برای آن متغیر نوعی در نظر می گیرند و نیازی نیست که برنامه نویس نوع متغیرها را مشخص کند زبان فرترن نیز چنین است. تعریف متغیر توسط برنامه نویس یا مترجم برنامه در برنامه نویسی حرفه ای برای مدت زیادی مورد بحث بود تا اینکه ناسا یکی از سنسورهای سفینه فضایی ونوس را بعلت یک تعریف متغیر اشتباه توسط مترجم برنامه (مترجم نوع دیگری را برای متغیر در نظر گرفته بود) از دست داد. بنابراین تعریف متغیر توسط برنامه نویس بعنوان یک روش مناسب انتخاب شد. خوشبختانه در بسیاری از زبانهای برنامه نویسی مدرن تعریف متغیر توسط برنامه نویس اجباری است. فرترن برای داشتن سازگاری از تعریف داخلی متغیر توسط مترجم پشتیبانی می کند.

نام گذاری متغیرها

قوانین نامگذاری متغیرها عبارتند از :

  • حداکثر طول نام متغیرها 34 کاراکتر است.
  • فقط امکان استفاده از حروف کوچک و بزرگ انگلیسی (a…z A…Z,)، اعداد(0,1,..,9) و کاراکتر زیر-خط ( _ ) وجود دارد.
  • توجه داشته باشید که بزرگی یا کوچکی حروف برای فرترن فرقی ندارد.
  • اولین کاراکتر یک اسم باید حرف باشد.
  • از کلمات کلیدی در نامگذاری استفاده نکنید.

انواع داده ها

شما در برنامه متغیرها را برای انواع مختلفی از داده ها بکار می برید. انواعی از داده ها که در فرترن 77 پیشتیبانی می گردند به شرح زیر است:

  • نوع INTEGER برای اعداد صحیح
  • نوع REAL برای اعداد اعشاری (تقریباً 8 رقم)
  • نوع DOUBLE برای اعداد اعشاری با دقت بیشتر (تقریباً 16 رقم معنی دار) [این اعداد را دقت مضاعف می نامیم]
  • نوع CHARACTER برای یک کاراکتر یا رشته ای از کاراکترها
  • نوع LOGICAL برای مقادیر منطقی
  • نوع COMPLEX برای اعداد مختلط به عنوان یک جفت با دقت REAL، اغلب توابع فرترن 77 بر روی اعداد مختلط قابل استفاده هستند.

ثابت های هم به همین شکل بکار می روند مثلاً 1234 یک عدد ثابت صحیح است، 1234.0 یا 1.234E3 یک ثابت اعشار و 1.234D3 عدد اعشار با دقت مضاعف است. اعداد مختلط به شکل (3.14,-1E5) نمایش داده می شوند و کاراکترها بین دو کوتیشن قرار می گیرند “AbBa” یا “S”. ثابتهای منطقی فقط می توانند دو مقدار .TRUE. و .FALSE. را داشته باشند (به نقاط ابتدایی و انتهایی هر یک توجه کنید). اگر اعداد بسیار کوچک یا بسیار بزرگ باشند، ممکن است سیستم آنها را صفر در نظر گرفته و مشکل تقسیم بر صفر در محاسبات پیش آید یا اینکه سیستم دچار سر ریز گردد. این خطاها بسیار رایج هستند و اشکال گزارش شده به سیستم بستگی خواهد داشت.

تعریف متغیرها

برای تخصیص حافظه لازم به متغیرها، مترجم برنامه (Compiler) باید نام، نوع و اندازه هر متغیر را بداند. اگر از دستور IMPILICIT NONE استفاده گردد، لازم است که تمام متغیرها تعریف گردند. در غیر اینصورت نوع متغیر با حرف اول آن مشخص می گردد.

  • a..h و o..z برای متغیرهای اعشار
  • i,j,k,l,m,n برای متغیرهای صحیح

تعریف متغیر با دستور زیر صورت می گیرد (این تعریف در برنامه نویسی بسیار پسندیده است):

اگر بخواهید مقدار ثابتی را تعریف کنید از دستور PARAMETER استفاده می گردد PARAMETER ({list of names=value})

عبارات ساده (عبارات و عملیات محاسباتی)

عملگرهایی مانند + ، – ، / (همان ÷ است) و * (همان × است) را می شناسید. عملگر توان در فرترن به شکل ** است.

اولویت محاسبه در عبارات

این موضوع که ابتدا کدام محاسبات انجام خواهد شد در پاسخ یک عبارت ریاضی بسیار موثر است. ترتیب محاسبه و اولویت آنها به شکل زیر است:

  • پرانتز – اگر در عبارات، پرانتز وجود داشته باشد. اول داخلی ترین پرانتز محاسبه خواهد شد و به همین ترتیب عبارات داخل پرانتز اولویت اول را دارند.
  • توان
  • رب و تقسیم
  • جمع و منها

برای مثال عبارت A*B**n-C/D و (A*(B**n))-(C/D) یکسان هستند. اگر دو عبارت از اولویت یکسانی برخوردار باشند، محاسبه از چپ به راست خواهد بود. برای مثال عبارت A/B*C و (A*B)/C یکسان هستند. لازم است بدانید که حاصل عملیات بین دو اعشار، اعشار است و حاصل عملیات بین دو عدد صحیح، عدد صحیح است؛ حاصل عملیات بین عدد اعشار و عدد صحیح، عدد اعشار است. به عنوان مثال حاصل 1/5 برابر 0 صحیح است، حاصل 1./5. برابر 0.2 اعشار است و حاصل 1d0/1d5 برابر 0.2 مضاعف است. بطور کلی می توان گفت که در محاسبه عبارات اگر تبدیل نوع لازم باشد، متغیرها به متغیر با بالاترین دقت تبدیل می گردند. در استفاده از اعداد دقت کنید، عدد 4 صحیح است، عدد 4. اعشار و عدد 4d0 مضاعف است. برابر قرار دادن مقدار یک متغیر با یک عبارت یکی از ساده ترین عبارات هر زبان برنامه نویسی است.

variable = expression

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

مقایسه متغیرها

مقایسه متغیرها به کامپیوتر قدرت تصمیم گیری داده است. متأسفانه فرترن 77 عباراتی مانند <, > و … را به این شکل پشتیبانی نمی کند و بجای آنها مقایسه را با عباراتی چون .EQ. انجام می دهد.

  • .EQ. equal to
  • .GE. greater or equal to
  • .GT. greater than
  • .LE. less than or equal to
  • .LT. less than
  • .NE. not equal to

این مشکل در فرترن 90 حل شده است و فرترن 90 علامتهای <، >، >=، <=، == و != را هم پشتیبانی می کند. برای مثال عبارت (A .EQ. B) معادل (A==B) و یک عبارت منطقی است، این عبارت در صورتی صحیح است که مقدار متغیرها با هم برابر باشد. در هر حال حاصل یک عبارت مقایسه ای یک مقدار منطقی خواهد بود که می تواند درست یا اشتباه باشد.

عبارات منطقی

دستورات منطقی این زبان عبارتند از:

  • .NOT. logical negative
  • .AND. logical and
  • .OR.   logical or
  • .EQV. logical equivalence
  • .NEQV. logical non-equivalence (exclusive or)
    T: TRUE, F:FALSE
x y .NOT. x x .AND. y x .OR. y x .EQV. y x .NEQV. y
F F T F F T F
T F F F T F T
F T T F T F T
T T F T T T F

کاراکتر و رشته

در فرترن 77 رشته ها باید اندازه ای ثابت و از پیش تعیین شده داشته باشند. تعریف رشته در فرترن 77 به این شکل است:

CHARACTER name*length

همچنین می توان آرایه ای از رشته ها تعریف کرد:

CHARACTER array (size)*length

برای نوشتن رشته های ثابت تعداد لازم نیست و بجای آن از * استفاده می گردد.

CHARACTER format_scope*(*)
PARAMETER(format_scope=’this is constant character!’)

دو عملیات ساده با رشته های کاراکتری در فرترن 77 عبارتند از استخراج بخشی از رشته یا پیوند دو رشته به یکدیگر. استخراج بخشی از رشته با قرار دادن علامت : بین شروع و پایان بخش مورد نظر صورت می گیرد. برای ترکیب رشته ها از علامت // استفاده می گردد.

substring= string(start position: end position)

برای کاراکترهای شروع و پایان, می توان عدد شروع یا پایان را ننوشت.

CHARACTER first_word*8, second_word*5, third_word*20 first_word=’FORTRAN’
second_word=first_word(:3)
third_word=second_word // first_word(4:)

متغیر third_word پس از اجرای این دستورات برابر رشته کاراکتری FOR TRAN خواهد بود ( فاصله بعلت اندازه متغیر second_word است).

توابع رشته ای

در توابع داخلی فرترن، توابع رشته ای نیز وجود دارد. برای مثال تابع LEN اندازه رشته می دهد، توابع CHAR و ICHAR بترتیب برای تبدیل عدد صحیح به کاراکتر و تبدیل کاراکتر به عدد صحیح به کار می روند. INDEX برای یافتن یک رشته در رشته دیگر کاربرد دارد. توابع مقایسه رشته ها مانند LGE، LGT، LLE و LLT و بسیارس از توابع دیگر وجود دارند که در صورت نیاز امکان مطالعه آنها را خواهید داشت.

ورودی و خروجی

در اغلب برنامه ها نیاز داریم که اطلاعات ورودی را از صفحه کلید یا فایل بخوانیم و اطلاعات خروجی را در صفحه نمایش نشان دهیم یا آنها را در فایل خروجی ذخیره کنیم.

دستور READ

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

READ *, {input list} or 
RAED([UNIT=] unit type, [FMT=] format) {input list}

unit type عددی است که نوع ورودی را مشخص می کند، مثلاً 5 برای صفحه کلید، این عدد اغلب برای خواندن ورودی از فایل بکار می رود. format برای دریافت ورودی معمولاً * است، اما کاربرد اصلی آن برای خواندن ورودی فرمت شده از فایل است.

READ (*,*) a, b, c

دستور WRITE

این دستور برای نمایش خروجی در صفحه نمایش یا فرستادن خروجی به پرینتر یا فایل خروجی بکار می رود.

PRINT *,{output list}

WRITE([UNIT=] unit type, [FMT=] format) {output list}

مانند دستور READ، unit typeنوع خروجی را مشخص می کند و format فرمت خروجی را تعیین می کند. WRITE(*,*) ‘The total is:’, total این دستور ابتدا رشته The total is: و در ادامه مقدار متغیر total را روی صفحه نمایش نشان خواهد داد.

تعیین قالب ورودی و خروجی – دستور FORMAT

این دستور قالب بندی داده را تعیین می کند و در دستورات ورودی و خروجی بکار می رود. این دستور به دو صورت به کار می رود. یک روش استفاده مستقیم این دستور در بخش format در دستورات ورودی و خروجی است. روش دوم قرار دادن یک شماره خط قبل از این دستور (شماره خط در فرترن 77 بین خط 1 تا 5 قرار می گیرد.) و ارجاع این شماره در دستورات ورودی و خروجی است. ساختار این دستور به شکل زیر است.

FORMAT (format sequence)

یا اگر داخل دستوراتی چون WRITE قرار گیرد به شکل زیر خواهد بود.

FMT= (‘format sequence’)

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

ترتیب قالب بندی format sequence

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

Data description Data type
Iw, Iw.m Integer
Ew.d, Ew.dEe, Fw.d,Gw.d, Gw.dEe Floating Point
Lw Logical
A, Aw Character

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

I : متغیر صحیح
F : متغیر اعشار با اعشار مشخص
E : نمایش علمی عدد اعشار
G : مانند F، به دقت عدد بستگی دارد
L : متغیر منطقی
A : متغیر کاراکتری!

و حروف کوچک قالب متغیر را مشخص می کنند

w : تعداد کل ارقام
m : حداقل تعداد ارقامی که باید نمایش داده شود
d : تعداد ارقام بعد از ممیز (دقت)
e : تعداد ارقام توان

تعدادی از کاراکترهای کنترلی که کاربرد بیشتری دارند

/ انتفال به خط بعدی
‘Any string’ رشته ای را به خروجی انتقال می دهد
nX مکان نما را n خانه به راست هدایت می کند

برای مثال:

WRITE(UNIT=*,FMT=10) ‘The frequency is’, f, ‘Hz’
10 FORMAT(1X, A, F10.5, A)

ابتئا مکان نما یک خانه به راست حرکت می کند، رشته کاراکتری نمایش داده می سود، مقدار متغیر f با حداکثر 15 رقم و با دقت 5 رقم اعشار نمایش داده شده و دوباره رشته کاراکتر چاپ می گردد. می توان از کلمات کلیدی UNIT و FMT صرفنظر کرد و فقط مقدار آنها را نوشت.

WRITE(*,10) ‘The frequency is’, f, ‘Hz’
10 FORMAT(1X, A, F10.5, A)

مثال برنامه‌نویسی:

شاید از آموختن تئوری کمی خسته شده باشید، حال وقت آن است که آنچه را که آموخته ایم استفاده کنیم. می خواهیم برنامه ای بنویسیم که ریشه های حقیقی یک معادله درجه 2 را پیدا کند. ضرایب معادله درجه 2 را از ورودی خواهیم خواند.

ریاضیات مسئله:
می دانیم که هر معادله درجه 2 به شکل دارای دو ریشه است. در صورتی این ریشه ها حقیقی هستند که باشد. در اینصورت ریشه های حقیقی معادله از رابطه زیر بدست می آیند.

دیاگرام برنامه:

  1. شروع
  2. ضرایب ورودی
  3. معادله را بخوان
  4. دلتا را محاسبه کن
  5. اگر دلتا بزرگتر یا مساوی صفر است
    1. ریشه ها را محاسبه کن
    2. ریشه ها را چاپ کن
  6. در غیر اینصورت
    1. چاپ کن “معادله ریشه حقیقی ندارد”
  7. پایان

برنامه:

اگر در نوشتن برنامه اشتباهی نکرده باشید، برنامه اجرا خواهد شد. تبریک می گویم، شما اولین برنامه مهندسی خود را نوشته اید. در خواندن برنامه بالا نباید مشکلی داشته باشید. فقط ممکن است ساختار IF..THEN..ELSE و تابع SQRT() برایتان تازگی داشته باشد و همانطور که حدس زده اید، ساختار IF..THEN..ELSE ساختار تصمیم گیری و تابع SQRT() تابع جذر می باشد که در بخشهای بعدی در مورد آن بحث خواهیم کرد.   برنامه نویسی شما فقط محدود به تفکر شما در مورد برنامه هاست. هر آنچه که فکر کنید را می توانید بنویسید. حتی برنامه های پیچیده هوش مصنوعی نیز با همین دستورات ساده قابل نوشتن است. در هر حال اگر بدانید چه می خواهید برنامه نویسی بسیار لذت بخش خواهد بود. آموختن یک زبان برنامه نویسی مانند یادگرفتن استفاده از یک ابزار است. هر چه ابزار قویتری داشته باشید کارها ساده تر انجام خواهد گرفت، زبان فرترن یک ابزار برنامه نویسی مهندسی بسیار کارآمد است.

ورودی و خروجی فایل

کار کردن با فایلها در فرترن بسیار ساده است. ورودی وخروجی فایل هم مانند ورودی از صفحه کلید یا خروجی به نمایشگر با دستور READ و WRITE صورت می گیرد. در این حالت بخش UNIT در این دستورات مشخص کننده نوع ورودی و خروجی است. برای ورودی از صفحه کلید و خروجی به صفحه نمایش، بخش UNIT در این دستورات برابر * قرار می گیرد. برای ورودی و خروجی از فایل، ابتدا فایل را باز می کنیم، این کار یک عدد (UNIT) به فایل اختصاص می دهد.

دستور OPEN

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

OPEN(UNIT= number, FILE= ’Name of file’, STATUS= status, ACCESS= access…)

number عددی است که شما به فایل اختصاص می دهید (این عدد را بین 0 تا 255 انتخاب کنید – یعنی شما می توانید با خیال راحت تا 255 فایل مجزا را باز کنید!)، این عدد شناسه فایل است.   status وضعیت فایل را مشخص می کند و می تواند برای ایجاد فایل جدید ‘NEW’ باشد، یا ‘OLD’ برای باز کردن فایل موجود و اگر مطمئن نیستید ‘UNKNOWN’ بکار می رود و ‘SCRATCH’ برای ایجاد فایلهای موقت که با پایان برنامه یا بسته شدن فایل، فایل از بین می رود! وضعیت ‘REPLACE’ برای جایگزاری فایل جدید است. اگر فایل موجود باشد، پاک شده و فایل جدید جایگزین آن می گردد و اگر فایل موجود نباشد، فایل جدید ایجاد می گردد.   access نوع دسترسی به فایل را مشخص می کند که ممکن است، ‘DIRECT’ یا ‘SEQUENTAL’ باشد. نوع دسترسی به فایل بسیار مهم است، اما دسترسی ترتیبی ‘SEQUENTAL’ بسیار ساده است. در این فایلها داده ها بترتیب خط به خط خوانده و نوشته می شوند. پیش فرض دسترسی ترتیبی است.

دستور CLOSE

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

CLOSE (UNIT= unit, STATUS = status…)

 unit شماره شناسه فایل است وstatus وضعیت بستن می تواند ‘KEEP’ برای حفظ فایل و ‘DELETE’ برای حذف فایل است. پیش فرض حذف فایل است.

توابع و زیربرنامه ها

توابع داخلی Intrinsic Functions هر مترجم برنامه فرترن کتابخانه ای از توابع داخلی دارد. بعضی از مهمترین این توابع به شرح زیر هستند.

  • توابع مثلثاتی: SIN, COS, ASIN, ACOS, TAN, ATAN, COTAN
  • توابع ریاضی: قدرمطلق ABS، جذر SQRT، لگاریتم LOG, LOG10، تابع نمایی EXP، حداقل و حداکثر MIN,MAX، باقیمانده تقسیم MOD و…
  • توابع ماتریسی: DOT_PRODUCT, MATMUL, TRANSPOSE,…

توابع بسیار زیاد دیگری نیز وجود دارد؛ همچنین ممکن است که مترجم شما توابع بیشتری از توابع استاندارد در اختیار شما قرار دهد. در هر حال اگر احتیاج به تابعی داشتید، قبل از اینکه خودتان به فکر نوشتن آن باشید مطمئن شوید که آن تابع وجود ندارد!!   بعضی از این توابع انواع داده ها را بعنوان ورودی خود می پذیرند البته اگر چند ورودی وجود داشته باشد همه باید از یک نوع باشند، بعضی از این توابع نیز نوع مشخصی را پشتیبانی می کنند. بعضی از مترجم ها مانند Digital Visual Fortran برای مشخص کردن نوع داده ورودی و خروجی از پیشوند و پسوند برای توابع استفاده می کند (برای جزئیات به help نرم افزار خود مراجعه نمایید.). فراخوانی توابع مانند اختصاص یک مقدار به متغیر می باشد.

Result_variable = function_name({list of parameters})
برای مثال: a= sin(b)

b متغیری است که به تابع ارسال می گردد و a حاصل تابع سینوس خواهد بود!

زیربرنامه های داخلی Intrinsic Subroutines

فرق تابع و زیر برنامه در تعداد متغیرهای بازگشتی آنهاست. البته این تنها فرق آنها نیست! تابع یک متغیر بازگشتی دارد درحالیکه زیر برنامه می تواند بیش از یک مقدار را برگرداند. تابع یک مقدار را بر می گردانند اما حق تغییر متغیرهای ورودی را ندارند. زیر برنامه ها مقدار بازگشتی ندارند، در عوض امکان تغییر متغیرهای خود را دارند. زیربرنامه ها با دستور CALL به شکل زیر فراخوانی می شوند.

CALL subroutine_name({list of variables})

 بعضی از زیربرنامه های داخلی عبارتند از:

DATE_AND_TIME, MVBITS, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK

توابع خارجی External Functions

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


type FUNCTION name ({dummy arguments})
   local variable declaration
   body of function…
   name = expression
   body of function continued if needed
END FUNCTION name

type نوع تابع (نوع حاصل تابع) را مشخص می کند. حاصل تابع مقداری است که توسط تابع بازگردانده می شود. اگر به ساختار بالا توجه کنید دقیقاً جایی که نام تابع برابر یک عبارت قرار گرفته، حاصل تابع است. تابع باید حداقل یک مقدار خروجی داشته باشد. یعنی در جایی از تابع، مقداری به “نام” تابع اختصاص داده شود. متغیرهای ظاهری dummy arguments، شامل همه ثابت ها، متغیرها و حتی روالهای1 قابل دسترسی در بدنه تابع است. (منظور از روالها، توابع و زیربرنامه ها هستند). وقتی تابع فراخوانی می گردد باید لیستی از این متغیرها به آن فرستاده شود. نوع این متغیرهای واقعی باید با متغیرهای ظاهری موجود در تعریف تابع یکسان باشد، اما نام آنها مهم نیست. نوع متغیرها در هنگام ارسال به توابع توسط مترجم برنامه کنترل نمی گردد و اگر نوع متغیرهای یکسان نباشد با اشکالات عجیبی روبرو خواهید شد! بعنوان مثال برای محاسبه نیروی جاذبه بین دو جسم با استفاده از فرمول نیوتن، تابع نیوتن را به شکل زیر تعریف می کنیم.

توابع یک خطی 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}

برای مثال

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

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

ساختار 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 با یک دستور، آنرا در یک خط خلاصه کرد. در این حالت از 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]

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

در برنامه بالا یک حلقه بینهایت وجود دارد (حلقه 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) یا باید اندازه آرایه را هم بعنوان یک پارامتر دیگر به تابع ارسال کنیم تا مبادا از مرزهای آرایه فراتر برویم! اگر اندازه آرایه مشخص نباشد می توانیم آن آرایه را با آرگومان * برای آخرین پارامتر آرایه (فقط یک بعد از آرایه را می توان به این شکل تعریف کرد) به تابع ارسال کنیم. در هر حال بخاطر داشته باشید که مترجم برنامه از طول آرایه اطلاع نخواهد داشت و شما خودتان باید مطمئن شوید که فراتر از محدوده اعضاء آرایه نروید.