5. توابع و رویهها
5.1. تابعهای از پیش تعریفشده VBScript
ثروت یک زبان تا حد زیادی از کتابخانه توابع آن ناشی میشود که ممکن است به صورت متدها در اشیاء محصور شوند. از این نظر، VBScript را میتوان نسبتاً محدود دانست.
جدول زیر توابع VBScript را که جزئی از اشیاء نیستند، فهرست میکند. در اینجا به جزئیات آنها نمیپردازیم. نام آنها عموماً نشاندهنده هدفشان است. خوانندگان برای جزئیات مربوط به تابع خاص، باید به مستندات مراجعه کنند.
Abs | آرایه | Asc | Atn |
CBool | CByte | CCur | CDate |
CDbl | Chr | CInt | CLng |
تبدیلها | Cos | CreateObject | CSng |
تاریخ | DateAdd | DateDiff | DatePart |
DateSerial | DateValue | روز | ریاضیات مشتقشده |
ارزیابی | Expression | فیلتر | FormatCurrency |
FormatDateTime | FormatNumber | FormatPercent | GetLocale |
GetObject | GetRef | هگز | ساعت |
InputBox | InStr | InStrRev | داخلی، ثابت |
IsArray | IsDate | IsEmpty | IsNull |
IsNumeric | IsObject | پیوستن | LBound |
LCase | چپ | لن | LoadPicture |
لاگ | LTrim; RTrim; و Trims | ریاضی | میان |
دقیقه | ماه | MonthName | MsgBox |
اکنون | اکتبر | جایگزین کنید | RGB |
درست | Rnd | گرد | ScriptEngine |
ScriptEngineBuildVersion | ScriptEngineMajorVersion | ScriptEngineMinorVersion | دوم |
SetLocale | Sgn | گناه | فضا |
تکتکه | مربع | StrComp | رشته |
قهوهای | زمان | تایمر | TimeSerial |
TimeValue | TypeName | UBound | UCase |
VarType | روز هفته | WeekdayName | سال |
5.2. برنامهنویسی ماژولار
توصیف راهحل برنامهنویسیشده برای یک مسئله، یعنی توصیف توالی عملیات پایهای است که میتوان توسط کامپیوتر اجرا کرد و قادر به حل مسئله است. بسته به زبان برنامهنویسی، این عملیات پایهای از نظر پیچیدگی متفاوت هستند. مثالها عبارتند از:
- خواندن دادهها از صفحهکلید یا دیسک
- نوشتن دادهها روی صفحه نمایش، چاپگر، دیسک و غیره.
- محاسبه عبارتها
- پیمایش در یک فایل
- ...
توصیف یک مسئله پیچیده ممکن است به چندین هزار دستور پایه یا بیشتر نیاز داشته باشد. بنابراین درک تصویر کلی یک برنامه برای ذهن انسان بسیار دشوار است. در مواجهه با این دشواری در درک کل مسئله، آن را به زیرمسائلی تقسیم میکنیم که حل آنها سادهتر است. مسئله زیر را در نظر بگیرید: یک فهرست از مقادیر عددی را که از طریق صفحهکلید وارد شدهاند مرتب کنید و فهرست مرتبشده را روی صفحه نمایش دهید.
ما میتوانیم در ابتدا راهحل را به شکل زیر توصیف کنیم:
début
lire les valeurs et les mettre dans un tableau T
trier le tableau T
écrire les valeurs triées du tableau T à l'écran
fin
ما مسئله را به سه زیرمسئله تقسیم کردهایم که حل آنها سادهتر است. نشانهگذاری الگوریتمی اغلب رسمیتر از مورد قبلی است و الگوریتم به صورت زیر نوشته میشود:
که در آن T نشاندهنده یک آرایه است. عملیاتها
عملیات غیرابتدایی هستند که به نوبه خود باید توسط عملیات ابتدایی توصیف شوند. این کار در واحدهایی به نام ماژولها انجام میشود. داده T پارامتر ماژول نامیده میشود. این اطلاعاتی است که برنامه فراخواننده به ماژول فراخوانده شده میفرستد (پارامتر ورودی) یا از آن دریافت میکند (پارامتر خروجی). بنابراین، پارامترهای یک ماژول، اطلاعات مبادلهشده بین برنامه فراخواننده و ماژول فراخواندهشده هستند.
ماژول lire_tableau(T) | ![]() |
ماژول trier_tableau(T) | ![]() |
ماژول écrire_tableau(T) | ![]() |
ماژول lire_tableau(T) میتواند به شرح زیر توصیف شود:
début
écrire "Tapez la suite de valeurs à trier sous la forme val1 val2 ... : "
lire valeurs
construire tableau T à partir de la chaîne valeurs
fin
در اینجا، ما توضیح کافی از ماژول lire_tableau را ارائه کردهایم. در واقع، سه اقدام مورد نیاز معادل مستقیمی در VBScript دارند. اقدام آخر نیازمند استفاده از تابع SPLIT خواهد بود. اگر VBScript این تابع را نداشت، اقدام ۳ نیز به نوبه خود باید به اقدامات پایهای که معادل مستقیم در VBScript دارند، تقسیم میشد.
ماژول écrire_tableau(T) میتواند به شرح زیر توصیف شود:
début
construire chaîne texte "valeur1,valeur2,...." à partir du tableau T
écrire texte
fin
ماژول écrire_tableau(T) میتواند به صورت زیر توصیف شود (با فرض اینکه شاخصهای عناصر در T از 0 شروع میشوند):
début
N<-- indice dernier élément du tableau T
pour IFIN variant de N à 1
faire
//: جستجوی شاخص IMAX بزرگترین عنصر در T
//IFIN نمایه آخرین عنصر T است
chercher_max(T, IFIN, IMAX)
// بزرگترین عنصر T را با آخرین عنصر T جابهجا میکند
échanger (T, IMAX, IFIN)
finfaire
FIN
در اینجا، الگوریتم بار دیگر از عملیات غیرابتدایی استفاده میکند:
. chercher_max(T, IFIN, IMAX)
. échanger(T, IMAX, IFIN)
chercher_max(T, IFIN, IMAX) شاخص IMAX بزرگترین عنصر آرایه T را بازمیگرداند، جایی که شاخص آخرین عنصر IFIN است.
![]() |
تابع swap(T, IMAX, IFIN) دو عنصر از آرایه T را که شاخصهایشان IMAX و IFIN هستند، با هم جابجا میکند.
![]() |
بنابراین باید عملیات جدید غیرابتدایی را توصیف کنیم.
ماژول chercher_max(A, IFIN, IMAX) | |
ماژول تعویض (T IMAX, IFIN) |
مسئله اولیه با استفاده از عملیات پایهای VBScript بهطور کامل توصیف شده و بنابراین اکنون میتوان آن را به این زبان ترجمه کرد. شایان ذکر است که عملیات پایهای ممکن است از زبانی به زبان دیگر متفاوت باشد و در نتیجه، تحلیل یک مسئله باید در مقطعی زبان برنامهنویسی مورد استفاده را در نظر بگیرد. ابجکتی که در یک زبان وجود دارد ممکن است در زبان دیگری وجود نداشته باشد و بدین ترتیب الگوریتم مورد استفاده را تغییر دهد. بنابراین، اگر یک زبان تابع مرتبسازی داشت، بیمعنی است که از آن در اینجا استفاده نکنیم.
اصولی که در اینجا به کار گرفته شده است، به عنوان تحلیل از بالا به پایین شناخته میشود. اگر ساختار راهحل را ترسیم کنیم، با موارد زیر مواجه میشویم:
![]() |
ما یک ساختار درختی داریم.
5.3. توابع و رویههای VBScript
پس از انجام تحلیل مدولار، برنامهنویس میتواند ماژولهای الگوریتم خود را به توابع VBScript مانند fonctions یا procédures تبدیل کند. هر دو fonctions و procédures پارامترهای ورودی/خروجی را میپذیرند، اما fonction نتیجهای را بازمیگرداند که امکان استفاده از آن را در عبارتها فراهم میکند، در حالی که procédure چنین امکانی را ندارد.
5.3.1. اعلام توابع و رویههای VBScript
یک رویه VBScript به صورت زیر اعلام میشود
و تابع به شرح زیر اعلام میشود
برای بازگرداندن نتیجه، تابع باید شامل یک عبارت تخصیص باشد که نتیجه را به متغیری با همان نام تابع تخصیص میدهد:
functionName=result
اجرای یک تابع یا رویه به دو صورت پایان مییابد:
- با برخورد به دستور 'end function' یا 'end sub'
- با برخورد با دستور 'exit function' یا 'exit sub'
برای یک تابع، مهم است به خاطر داشته باشید که نتیجه باید قبل از پایان تابع با دستور 'end function' یا 'exit function' به متغیری با همان نام تابع تخصیص داده شده باشد.
5.3.2. روشهای ارسال پارامترها به یک تابع یا رویه
هنگام اعلام پارامترهای ورودی و خروجی یک تابع یا رویه، مد (byRef, byVal) که پارامتر از برنامه فراخوانیکننده به برنامه فراخوانیشونده با آن منتقل میشود، مشخص میگردد:
sub nomProcédure([Byref/Byval] param1, [Byref/Byval] param2, ...)
function nomFonction([Byref/Byval] param1, [Byref/Byval] param2, ...)
در صورتی که حالت انتقال byRef یا byVal مشخص نشده باشد، از حالت byRef استفاده میشود.
پارامترهای واقعی، پارامترهای اسمی
بیایید تابع VBScript تعریفشده توسط
پارامترهای parmamFormi که در تعریف تابع یا رویه استفاده میشوند، پارامترهای رسمی نامیده میشوند. تابع فوق را میتوان از برنامه اصلی یا ماژول دیگری با استفاده از دستوری مانند زیر فراخوانی کرد:
پارامترهای parmamEffi که در فراخوانی تابع یا رویه استفاده میشوند، پارامترهای حقیقی نامیده میشوند. هنگامی که اجرای تابع nomFonction آغاز میشود، مقادیر پارامترهای شکلی با مقادیر پارامترهای حقیقی متناظر تخصیص مییابد. کلیدواژههای byRef و byVal حالت انتقال مقدار را تعیین میکنند.
حالت انتقال با مقدار (byVal)
وقتی یک پارامتر صوری این روش گذراندن را مشخص میکند، پارامتر صوری و پارامتر حقیقی دو متغیر مجزا هستند. مقدار پارامتر حقیقی قبل از اجرای تابع یا رویه، در پارامتر شکلی کپی میشود. اگر تابع یا رویه در حین اجرا مقدار پارامتر شکلی را تغییر دهد، این امر به هیچ وجه بر مقدار پارامتر حقیقی متناظر تأثیر نمیگذارد. این حالت ارسال برای پارامترهای ورودی یک تابع یا رویه بسیار مناسب است.
![]() |
حالت گذراندن به صورت مرجع (byRef)
این حالت ارسال، حالت پیشفرض است اگر هیچ حالت ارسالی مشخص نشود. هنگامی که یک پارامتر فرمال این حالت ارسال را مشخص میکند، پارامتر فرمال و پارامتر حقیقی متناظر، یک متغیر واحد هستند. بنابراین، اگر تابع، پارامتر فرمال را تغییر دهد، پارامتر حقیقی نیز تغییر میکند. این حالت ارسال برای موارد زیر مناسب است:
- پارامترهای خروجی، زیرا مقادیر آنها باید به برنامه فراخواننده بازگردانده شوند
- پارامترهای ورودی که کپی کردن آنها دشوار است، مانند آرایهها
![]() |
برنامه زیر نمونههایی از ارسال پارامتر را نشان میدهد:
برنامه |
|
نتایج |
توضیحات
- در یک اسکریپت VBScript، جای مشخصی برای توابع و رویهها وجود ندارد. آنها میتوانند در هر نقطهای از کد منبع ظاهر شوند. به طور کلی، آنها یا در ابتدا یا در انتها گروهبندی میشوند و دقت میشود که برنامه اصلی یک بلوک پیوسته را تشکیل دهد.
5.3.3. نحو فراخوانی توابع و رویهها
فرض کنید p یک رویه است که پارامترهای اسمی pf1، pf2، ... را میپذیرد
- روال p به صورت زیر فراخوانی میشود
بدون پرانتز دور پارامترها
- اگر رویه p هیچ پارامتری نداشته باشد، میتوان از فراخوانی p یا p() و اعلامیه sub p یا sub p() استفاده کرد
فرض کنید f تابعی است که پارامترهای رسمی pf1، pf2، ... را میپذیرد.
- فراخوانی تابع f به شکل زیر است
کروشهها دور پارامترها ضروری است. اگر تابع f هیچ پارامتری نداشته باشد، میتوان از فراخوانی f یا f() و اعلامیهی function f یا function f() استفاده کرد.
- نتیجهٔ تابع f ممکن است توسط برنامهٔ فراخواننده نادیده گرفته شود. در این صورت، تابع f بهعنوان یک رویه در نظر گرفته شده و از قواعد فراخوانی رویهها پیروی میکند. در این حالت، برای فراخوانی تابع f، f pe1, pe2, ... (بدون پرانتز) نوشته میشود.
اگر تابع یا رویه یک متد شیء باشد، به نظر میرسد که قوانین تا حدی متفاوت و ناسازگار هستند.
- برای مثال، میتوان نوشت MyFile.WriteLine "This is a test." یا MyFile.WriteLine("This is a test.")
- اما در حالی که میتوانید wscript.echo 4 را بنویسید، نمیتوانید wscript.echo(4) را بنویسید.
ما از قوانین زیر پیروی خواهیم کرد:
- بدون پرانتز دور پارامترهای یک رویه یا تابع که بهعنوان رویه استفاده میشود
- کروشهها دور پارامترهای یک تابع
5.3.4. چند مثال از توابع
در زیر چند مثال از تعریف و کاربرد توابع آورده شده است:
برنامه |
|
نتایج |
نظرات
- تابع rendUnTableau نشان میدهد که یک تابع میتواند به جای یک نتیجه، چندین نتیجه بازگرداند. تنها کاری که باید انجام دهد این است که آنها را در یک واریانت آرایه قرار دهد و آن واریانت را به عنوان نتیجه بازگرداند.
- برعکس، تابع argumentsVariables نشان میدهد که میتوان تابعی نوشت که تعداد متغیری آرگومان را بپذیرد. در اینجا نیز، صرفاً کافی است آنها را در یک واریانت آرایه قرار داده و این واریانت را به عنوان پارامتر تابع در نظر بگیریم.
5.3.5. پارامتر خروجی یا نتیجه تابع
فرض کنید تحلیل یک برنامه کاربردی، نیاز به ماژولی به نام M با پارامترهای ورودی Ei و پارامترهای خروجی Sj را نشان داده است. به یاد داشته باشید که پارامترهای ورودی، اطلاعاتی هستند که برنامه فراخواننده در اختیار برنامه فراخواندهشده قرار میدهد و برعکس، پارامترهای خروجی، اطلاعاتی هستند که برنامه فراخواندهشده در اختیار برنامه فراخواننده قرار میدهد. در VBScript، چندین راهحل برای پارامترهای خروجی وجود دارد:
- اگر تنها یک پارامتر خروجی وجود داشته باشد، میتوان آن را به عنوان نتیجه تابع در نظر گرفت. در این حالت، دیگر از پارامتر خروجی صحبت نمیشود، بلکه صرفاً از نتیجه تابع صحبت میشود.
- اگر n پارامتر خروجی وجود داشته باشد، یکی از آنها میتواند به عنوان نتیجه تابع عمل کند و n-1 پارامتر باقیمانده به عنوان پارامترهای خروجی عمل میکنند. به عنوان جایگزینی دیگر، به جای یک تابع، میتوان از یک رویه با n پارامتر خروجی استفاده کرد. همچنین میتوان از توابعی استفاده کرد که آرایهای حاوی n مقدار را برای بازگشت به برنامه فراخوانیکننده برمیگردانند. شایان ذکر است که برنامه فراخوانیشونده نتایج خود را به برنامه فراخوانیکننده به صورت مقدار بازمیگرداند. این کپیبرداری هنگامی که پارامترهای خروجی به صورت ارجاعی ارسال شوند، اجتناب میشود. بنابراین، این راهحل دوم در زمان صرفهجویی میکند.
5.4. برنامه VBScript برای مرتبسازی مقادیر
ما بحث خود را در مورد برنامهنویسی مدولار با یک مطالعه الگوریتمی بر روی مرتبسازی مقادیر عددی وارد شده از طریق صفحهکلید آغاز کردیم. در اینجا ترجمه VBScript که میتوان تولید کرد، آورده شده است:
توضیحات:
- ماژول échanger که در الگوریتم اولیه شناسایی شده بود، در اینجا به عنوان یک ماژول VBScript پیادهسازی نشد، زیرا بسیار ساده تشخیص داده شد و شایسته یک ماژول جداگانه نبود.
5.5. برنامه IMPOTS به صورت مدولار
ما در حال بازنویسی برنامه محاسبه مالیات هستیم، این بار به صورت مدولار نوشته شده است
نظرات
- تابع getArguments جزئیات مالیاتدهنده (همسر، فرزندان، حقوق) را بازیابی میکند. در اینجا، این موارد به عنوان آرگومان به برنامه VBScript ارسال میشوند. اگر این تغییر کند – برای مثال، اگر این آرگومانها از یک رابط کاربری گرافیکی تأمین شوند – تنها رویه getArguments نیاز به بازنویسی دارد و نه موارد دیگر.
- تابع getArguments میتواند خطاها را در آرگومانها تشخیص دهد. هنگامی که این اتفاق میافتد، ممکن است تصمیم گرفته شده باشد که اجرای برنامه را در داخل تابع getArguments با استفاده از یک دستور wscript.quit متوقف کنند. این کار هرگز نباید در داخل یک تابع یا رویه انجام شود. اگر یک تابع یا رویه خطایی را تشخیص دهد، باید به نحوی آن را به برنامه فراخواننده گزارش دهد. تصمیمگیری برای متوقف کردن اجرای برنامه یا عدم توقف آن بر عهده خودِ برنامه فراخواننده است، نه رویه. در مثال ما، برنامه فراخواننده ممکن است به جای متوقف کردن اجرا، تصمیم بگیرد از کاربر بخواهد که دادههای نادرست را مجدداً از طریق صفحهکلید وارد کند.
- در اینجا، تابع getArguments آرایهای از نوع variant را بازمیگرداند که عنصر اول آن کد خطا (در صورت عدم وجود خطا برابر با 0) و عنصر دوم آن پیام خطا در صورت وقوع خطا است. با بررسی نتیجه بازگرداندهشده، برنامه فراخواننده میتواند تشخیص دهد که آیا خطایی رخ داده است یا خیر.
- روال getData دادههای مورد نیاز برای محاسبه مالیات را بازیابی میکند. در اینجا، این دادهها مستقیماً در داخل رویه getData تعریف شدهاند. اگر این دادهها از منبع دیگری – برای مثال یک فایل یا پایگاه داده – تأمین میشدند، تنها رویه getData نیاز به بازنویسی داشت و نه رویههای دیگر.
- تابع calculerImpot پس از بهدست آمدن تمام دادهها، مالیات را محاسبه میکند، صرفنظر از نحوهٔ بهدست آوردن آنها.
- بنابراین باید توجه داشت که رویکرد مدولار امکان استفاده مجدد از برخی ماژولها در زمینههای مختلف را فراهم میکند. در طول بیست سال گذشته، این مفهوم در برنامهنویسی شیءگرا به طور گستردهای توسعه یافته است.







