
مقدمه
این دومین مقاله از سری مقالات “زبان MQL4 برای تازهکارها” است. در اولین مقاله، “MQL4 Language for Newbies. Introduction”، توضیح دادیم که با MQL4 چه کارهایی میشود انجام داد، یاد گرفتیم اسکریپتهای ساده بنویسیم، و فهمیدیم متغیر چیست، و کار با آنها را فرا گرفتیم، همچنین توابع آنالیزشده، آرایهها، آرایهها و متغیرهای توکار، سیکلهای “for” و شرطهای ساده و پیچیده را با هم دیدیم.
اکنون به بررسی ساختار پیچیده و پیشرفتهتر این زبان می پردازیم، گزینههای جدید را یاد میگیریم و میبینیم که چگونه میتوان از آنها در مسائل مربوطه استفاده کرد. با سیکل جدید “while” آشنا میشوید، نوع جدید شرط، یعنی “switch” را میبینید، عملگرهای “break” و “continue” را هم خواهید شناخت. علاوه بر اینها، یاد میگیرید توابع خودتان را بنویسید و با آرایههای چند بُعدی نیز کار کنید. و بهعنوان دسر کار، توضیحی دربارهی یک پیشپردازنده، آماده کردهام.
نصیحت
اگر مقالهی قبلی را کامل مسلط نیستید، خواندن این مقاله را آغاز نکنید. چراکه اشتباهات زیادی خواهید داشت و باز هم چیزی متوجه نخواهید شد. این مقاله بر اساس اصول [نسبتاً] قدیمی نوشته شده، پس عجله نکنید! البته بگذارید خیالتان را کمی راحت کنم-چیزهای سخت جدیدی که هنگام یادگیری با آنها مواجه میشوید، فریبآمیز هستند! زمانی میرسد که دیگر نگران این نیستید که سیکلها چگونه نوشته میشوند، و چه شرطهایی باید گذاشت – بلکه همهچیز ماشینی انجام خواهد شد. هرچه بیشتر با این زبان کار کنید، استفاده از آن برایتان راحتتر میشود.
نوع جدیدی از سیکلها – while
میخواهم به این موضوع اشاره کنم که سیکل ‘for’ که در مقالهی قبلی توضیح داده شد، یک سیکل جهانی است و میتواند جایگزینی برای هر نوع سیکل دیگری باشد که اکنون یاد میگیریم. اما همیشه راحت و مفید هم نیست! بعضیوقتها، بهتر این است که از while استفاده کنیم. خیلی زود متوجه خواهید شد استفاده از کدام سیکل منطقیتر است. بیایید یک کار را به دو روش انجام دهیم: با استفاده از هر دو سیکل میخواهیم حجم کلی تمام کندلها را پیدا کنیم و تفاوتها را ببینیم:
// using the cycle for double sum = 0.0; for(int a = 0; a < Bars; a++) sum += Volume[a]; // now using while, the result is the same double sum = 0.0; int a = 0; while(a < Bars) { sum += Volume[a]; a++; }
اکنون میبینید که، شمارنده اعلام شدهاست و بهشکل جداگانه از آن استفاده میشود. while در اینجا نشان میدهد وقتی شرط true باشد، سیکل ادامه خواهد یافت. در اینجا شکل کلی [این مسئله] را میبینیم:
while(condition of cycle fulfillment) { code; }
در اینجا مثالی سادهتر داریم:
while(I havent eaten up the apple) // condition { // what to do, if the condition is not fulfilled bite more; }
در واقع، سیکل while تفاوتش با سیکل for در نبود شمارنده[۱] است. اگر به شمارنده نیازی ندارید، از while استفاده کنید، هرچند، ضرورتی هم ندارد! برای مثال، من خودم اغلب از while همراه با شمارنده استفاده میکنم، و در واقع، بحث سلیقه است. مثلاً در خصوص for، اگر بدنهی سیکل[۲] شامل فقط یک دستور[۳] باشد، میتوانید آکولادها[۴] را حذف کنید. همچنین، برای توسعهی خودتان، معنایکلمهی iteration (تکرار) را همیشه بهیاد داشته باشید؛ که یکی از چندین عملگری (تکرارهایی) است که سیکل [انجام] آن را برعهده دارد. بهعبارت دیگر، یک بار اجرای بدنهی سیکل یعنی، یک تکرار (iteration) انجام شدهاست.
نوع جدید شرطها – switch
درست همانند موضوع سیکلها، باید به این نکته اشاره کنیم که switch میتواند جایگزین ترکیبی آشنا برای شما، یعنی شرطهای if و else، بشود. از ساختار switch وقتی استفاده میکنیم که نیاز داشته باشیم کارهایی را بسته به مقدار یک متغیر، انجام دهیم. دقیقاً مثل حالت عادی سوئیچ کردن در یک مایکروویو است. برای مثال تصور کنید که اکسپرتی را دارید مینویسید، و این اکسپرت عملکرد خود را بسته به شرایط بازار تغییر میدهد. بیایید متغییر int marketState را مسئول این کار قرار دهیم. ممکن است معانی زیر را در بر گیرد:
- ۱- رو به بالا
- ۲- رو به پایین
- ۳- صاف
مهم نیست که این پوزیشن چگونه تعریف شدهاست. وظیفهی ما این است که یک نوع مکانیزم را در اینجا تحقق ببخشیم، تا بسته به شرایط بازار اکسپرت کارهای مرتبط را انجام دهد. بسیار خب، میدانید این کار را چگونه انجام دهید. واضحترین حالت این است:
if(marketState == 1) { // trading strategy for an uptrend } else if(marketState == 2) { // strategy for a downtrend } else if(marketState == 3) { // strategy for a flat } else { // error: this state is not supported! }
در اینجا، برخی از خصوصیات را داریم:
- تمام شرطها با یک متغیر، و با همین متغیر، انجام شدهاند؛
- تمام شرطها با یکی از معانیایی که متغیر میتواند آن را بپذیرد، آن را (متغیر را) مقایسه میکنند.
بنابراین، تمام اینها به ساختار switch نیز برمیگردد. در اینجا کد را داریم که با استفاده از switch، نتیجه همان است:
switch(marketState) { case 1: // trading strategy for an uptrend break; case 2: // strategy for a downtrend break; case 3: // strategy for a flat break; default: // error: this state is not supported! break; }
بهیاد داشته باشید که اول تعریف میکنیم که کدام متغیر مقایسه خواهد شد:
// switch - key word, marketState - // a variable for comparison switch(marketState)
و سپس مشخص میکنیم که در موارد خاص چه کاری باید انجام شود:
case 1: // case - key word; // trading strategy // if marketState is equal to 1, then // for an uptrend // perform this code break; // key word that indicates // the end of actions in this case case 2: // if marketState is equal to 2, then // startegy for // perform this // a downtrend break; // end case 3: // identical // strategy for flat break; default: // otherwise, perform this // error: this // state is not // supported! break;
در یک دید کلی، switch چنین فرمی دارد:
switch(a variable for comparison) { case [a variable value]: // a code for this case break; case [another value of the variable] // a code for this case break; default: // a code for all other cases break; }
وقتی میخواهید یک متغیر را با چند مقدار و یک بلوک خاص از کد که مرتبط با یک مقدار است، مقایسه کنید، از switch استفاده کنید. در موارد دیگر، از همان ترکیب معروف شرطهای if و else استفاده کنید. بعضیوقت نیاز دارید یک کد را در چندین مقدار یک متغیر اجرا کنید. برای مثال، اگر marketState == 1 or 2، آنگاه یک کد خاص اجرا شود. این کار را با استفاده از swtich اینگونه میتوان انجام داد:
switch(marketState) { case 1: // if marketState is equal to 1 case 2: // or if marketState is equal to 2, then // perform this break; default: // in any other case perform // this code break; }
عملگرها: continue و break
تا الان فقط عملگر break را دیدهایم. از این عملگر برای فرار از بدنهی switch استفاده میشود. علاوه بر این، میتوانید از این عملگر برای فرار از یک سیکل هم استفاده کنید. برای مثال، اگر نیاز ندارید که یک سیکل، در برخی شرطها اجرا شود. فرض کنید نیاز داریم حجم اولین کندلهایی را پیدا کنیم که ۱۰۰۰ پوینت را در بر بگیرند. باید چنین کدی بنویسیم:
int a = 0; double volume = 0.0; while(volume < 1000.0) { volume += Volume[a]; // equivalent to volume = volume + Volume[a]; a++; } // now variable "a" includes the amount of bars, the volume of their sums // is no less than 1000 points
حالا بیایید کدی مشابه کد قبلی بنویسیم و از عملگر break استفاده کنیم:
int a = 0; double volume = 0.0; while(a < Bars) { // if the volume is exceeds 1000 points, then if(volume > 1000.0) // exit the cycle break; volume += Volume[a]; a++; }
همانطور که میبینید، استفاده از عملگر break آسان است و به شما اجازه میدهد از تکرارهای ناخواستهی سیکل دور باشید. عملگر مفید دیگری بهنام continue داریم که برای “حذف” تکرارهای ناخواسته میتوان از آن استفاده کرد. فرض کنید میخواهیم یک حجم کلی را محاسبه کنیم، اما نباید حجم کندلهایی که در لحظهی انتشار اخبار مهم ایجاد شدهاند را، در محاسبات خود بیاوریم.
همانطور که میدانید، اخبار مهم، حجم زیادی را با خود دارند و به کندلها منتقل میکنند. بیایید بگوییم بچهی کَفِ والاستریت هستیم و فرض را بر این بگذاریم که حجم کندل اگر بیشتر از ۵۰ پوینت باشد، آنگاه آن کندل، خبر است. برای حل این موضوع، از عملگر continue استفاده میکنیم:
int a = -1; double volume = 0.0; while(a < Bars) { a++; // if the volume exceeds 50 points, then it must // be news, omit it if(Volume[a] > 50.0) continue; volume += Volume[a]; }
میبینید که استفاده از عملگر continue، شاید خیلی چیز خاصی نباشد، اما بعضیوقتها کمکتان میکند، و البته واضح است که این اسکریپت برای تایمفریمهای کوچک نوشته شدهاست.
نوشتن توابع خودمان
اما چرا به آنها نیاز داریم؟ واقعیت این است که اغلب میتوانید کپی کد خودتان را پیدا کنید. بهعبارت دیگر، از یک سری از دستورات در موارد مختلف استفاده خواهید کرد. برای اینکه زمان و انرژی خود را حفظ کنید، میتوانید این کد کپیشده را در یک تابع مجزا بنویسید. و هر وقت به آن نیاز داشتید، بهراحتی نام تابع را نوشته و بقیه چیزها انجام خواهند شد. بیایید ببینیم این موضوع چگونه است…
فرض کنید میخواهید رنگ یک کندل را پیدا کنید. و میدانیم که کندل سفید، آن کندلی است که بالاتر از بازشدن، بسته شدهاست، و برای کندل سیاه، برعکس این قضیه صادق است. بیایید کد تعیین رنگ یک کندل را بنویسیم:
bool color; // as there are only 2 variants // (white or black candlestick), // then suppose that the velue // false corresponds to a black // candlestick, and true - white if(Close[0] > Open[0]) color = true; // white candlestick if(Open[0] > Close[0]) color = false; // black candlestick
همهی کار همین بود، اکنون متغیر رنگ، رنگِ آخرین کندل را در خود دارد . برای تعیین رنگ کندل دیگر، برای مثال، کندل یکی مانده به آخر، میبایستی شاخص ۰ را به ۱ تغییر دهیم. اما آیا هر بار که میخواهید رنگ یک کندل را پیدا کنید، میخواهید این کد را وارد کنید؟ و اگر دهها مورد اینطوری باشد، چه میکنید؟ به همین دلیل است که به توابع نیاز داریم. بیایید فکر کنیم چگونه باید عمل کرد…
چنین تابعی باید یک استدلال[۵] را بپذیرد – شاخص یک کندل، که میخواهید رنگ آن را تعیین کنید، و رنگ را بهشکل یک متغیر از نوع منطقی برگرداند. تصور میکنیم این تابع نوشته شده، و آن را فعال کردهایم:
bool color; // here will be the color of a wanted candlestick color = GetColor(0);
همانطور که شاید حدس زده باشید، نام تابع ما GetColor است. در فراخوانی این تابع، میخواهیم رنگ آخرین کندل را پیدا کنیم. به همین دلیل است که تنها استدلال ما برابر با صفر است. تابع، رنگ یک کندل را برمیگرداند، و ما بهیکباره یک واگذاری را ایجاد کردهایم. لحظهی بسیار مهمی است! یک متغیر درون تابع ایجاد شدهاست، سپس مقدار آن، فراخوانی تابع را جایگزین خواهد کرد.
در نهایت اینکه، فراخوانی تابع و کد تعیین تابع، که در بالا توضیح داده شدند، همان نتیجه را به ما خواهند داد – متغیر رنگ، رنگِ آخرین کندل را در خود دارد، اما استفاده از تابع انرژی کمتری از ما میگیرد.
اکنون بهشکل غیرمنتظرهای برمیگردیم به کد یک اسکریپت خالی. در واقع، این اسکریپت خالی، هماکنون توضیح کاملی از تابع start() را در خود دارد. جالب این است که تمام این مدت مشغول نوشتن اسکریپتها در این تابع بودهاید! وقتی اسکریپت خود را اجرا میکنید، نرمافزار تابع start() را فعال میکند. بیایید کد یک اسکریپتخالی را بررسی کنیم:
int start()
این خط بسیار مهم است! و نام تابع در آن است. بهعبارت دیگر، یک کلمهی کلیدی، که آن را برای فعالسازی این تابع مینویسید. در اینجا، آن کلمه، “start” است. همینطور نوع مقدار بازگشتی نیز در آن است- یعنی int. و این یعنی اینکه بعد از اجرای این تابع، مقدارهایی از نوع int به ما برمیگردد. کروشهها شامل لیستی از استدلالها هستند، اما در اینجا تابع هیچ نوع پارامتری را نمیپذیرد.
سپس در آکولادها، توضیحات تابع را میبینید، بهعبارت دیگر، کدی را میبینید که در فراخوانی تابع اجرا خواهد شد:
{ //---- // a code that will be performed // at the function call. //---- return(0); }
واضح است که کد را در بدنهی تابع start() نوشتهایم. در انتهای تابع عملگر return را میبینیم که مقدار تابع را برمیگرداند. در اینجا، صفر را برمیگرداند.
اکنون به فرم کلی نوشتن یک تابع نگاهی بیندازیم:
[type of return value] [function name] ([list of arguments]) { // function code return([a value, which the function returns]); }
اکنون به کندلهای خودمان و تابع GetColor برمیگردیم. به کد این تابع نگاهی بیندازید:
bool GetColor(int index) { bool color; if(Close[index] > Open[index]) color = true; // white candlestick if(Open[index] > Close[index]) color = false; // black candlestick return(color); }
بیایید خط اول را بررسی کنیم:
bool GetColor(int index)
در اینجا داریم: bool – نوع مقدار بازگشتی؛ GetColor – نام تابع؛ int – نوع استدلال؛ index – نام استدلال. بهیاد داشته باشید، index را درون بدنهی تابع استفاده میکنیم، اما در فراخوانی تابع، به این نام هرگز اشارهای نمیشود. برای مثال:
bool lastColor = GetColor(0);
سپس:
{ bool color; if(Close[index]>Open[index]) color=true; // white candlestick if(Open[index]>Close[index]) color=false; // black candlestick
بدنهی این تابع، یک کد عمومی است، که در هر بار فراخوانی تابع اجرا میشود. پس از آن:
return(color); }
عملگر return مشخص میکند که تابع چه چیزی را باید برگرداند. مقدار بازگشتی، باید مرتبط با نوع باشد، که در همان ابتدا آن را تعیین کردیم. در صورت نیاز، از چند عملگرد return در یک تابع استفاده کنید. برای مثال:
bool GetColor(int index) { if(Close[index] > Open[index]) return(true); // white candlestick if(Open[index] > Close[index]) return(false); // black candlestick }
مشخص است که استفاده از چند عملگر return به ما اجازه داده از متغیر color اجتناب کنیم. علاوه بر این، در عملگرد return میتوانید حتی از بیان منطقی نیز استفاده کنید:
return(Close[index] > Open[index]);
این کار ممکن است، زیرا عملگرهای مقایسهای، متغیرهایی از نوع منطقی (true or false) را نیز برمیگردانند، درست مانند دیگر توابع رایج. بهنظر سخت میآید اما بهزودی به آن عادت میکنید.
اکنون برمیگردیم به لیست استدلالها. فقط از استدلال int index در تابعمان استفاده کردهایم. اگر میخواهید از چند استدلال استفاده کنید، یک به یک آنها را نام برده و با کاما جدا کنید:
bool SomeСomplicatedFunction(int fistArgument, int secondArgument, sting stringArgument)
برای اینکه به استدلالها ارجاع دهیم، از نام آنها، همانند تابع قبلی استفاده کنید. وقتی تابعی را با چندین استدلال فرا میخوانید، به ترتیبِ آوردهشدنِ استدلالها دقت کنید: هیچ چیزی را با دیگری ترکیب نکنید! اگر تابع نباید هیچ مقداری را برگرداند، از کلیدواژه void استفاده کنید. دقت کنید که در اینجا از عملگر return استفاده نشدهاست:
void function() { // code }
یک مورد دیگر: ممکن است مقادیر را برای استدلالهای تابع، روی پیشفرض تعیین کنید. این چیست؟ فرض کنید تابع پیچیدهای نوشتهاید که شامل ۵ استدلال است، که روی عملکرد تابع تاثیر میگذارند. اما از چند استدلال آخر، تقریباً همیشه با مقادیر یکسان استفاده میکنید. فقط برای ۲۴ فراخوان تابع نیاز به استفاده از مقادیر متفاوت دارید. برای اینکه هر بار مقادیر استدلالهای آخر را مشخص نکنیم، که تقریباً همیشه مشابه هستند، مقادیر پیشفرض استدلالها استفاده میشوند.
در چنین شرایطی، خیلی ساده، استدلالهای آخر را حذف میکنید، طوریکه انگار وجود نداشتهاند، هرچند در حقیقت از آنها استفاده شده، اما مقادیر آنها، پیشفرض تعیین شدهاست. وقتی با چنین شرایط خاصی مواجه میشوید، تمام استدلالها را مشخص کنید. بیایید ببینیم چگونه میتوانیم تابعی را با استدلاهای پیشفرض، اعلام کنیم:
void someFunction(int argument1, int argument2, int specialArgument = 1) { // code }
همانطور که میبینید، همهچیز ساده است: مقدار مورد نیاز را به استدلال مورد نیاز اختصاص داده و اکنون میتوانیم آن را در فراخوانی تابع حذف کنیم:
someFunction(10,20); // we omitted the last argument, but // actually it is assigned a value by default someFunction(10,20,1); // this activation is fully identical to the previous one someFunction(10,20,2); // here we indicate another value, // it is a rare case
میتوانید تا حد دلخواه، مقادیر پیشفرض استدلالها را مشخص کنید. اما یک قانون مهم را بهیاد داشته باشید. باید همهی آنها را در انتها قرار دهید. برای مثال:
void someFunction(int argument1, int argument2, int specialArgument = 1) // all right void someFunction(int argument1, int argument2 = 10, int specialArgument=1) // all right void someFunction(int argument1, int argument2 = 10, int specialArgument) // wrong! default // values must stay // at the end of the // list of arguments void someFunction(int argument1 = 0, int argument2 = 10, int specialArgument = 1) // you can assign // default values // to all arguments
آرایههای چندبُعدی
حین برنامهنویسی اغلب از آرایهها استفاده میکنید و در موارد اصلی، آرایههای تکبُعدی کافی هستند. اما در برخی موارد، به دوبُعدیها یا سهبعدیها نیاز دارید. اکنون یاد میگیریم چگونه از آنها استفاده کنیم.
برای شروع بیایید یک آرایهی تکبعدی، تجدید نظر در اعلام (revise declaration)، مقداردهی اولیه، شاخصها و مقدار را، بهصورت بصری ببینیم:
هر آرایهی تکبعدی را میتوان بهشکل یک ردیف از مقادیر همنوع، نمایش داد. نگاه کنید، چگونه منابع مختلف برای یک آرایه یکبعدی پردازش میشوند:
آرایههای دوبعدی مانند جداول معمولی هستند. نگاه کنید:
همانطور که در تصویر میبینید، آرایههای دوبعدی در حال حاضر، دو شاخص (two indexes) برای بازگشت به مقدار[۶]، دارند: اولین شاخص ردیف را مشخص میکند، و دومی ستون را. همانند آرایههای یکبعدی، از لیستی از مقادیر برای مقداردهی اولیه، استفاده شدهاست. اینگونه به مقادیر سلولهای جدول ارجاع داده میشود:
همانطور که دیدید، همهچیز واضح است. بیایید بررسی کنیم، چگونه میشود تمام مقادیر یک آرایهی دوبعدی را بررسی کرد. از دو سیکل باید استفاده کنیم:
int array2D[3][3]={10,20,30, ۴۰,۵۰,۶۰, ۷۰,۸۰,۹۰}; for(int y=0;y<3;y++) for(int x=0;x<3;x++) MessageBox("array2D["+y+"]["+x+"]="+array2D[y][x]);
در این مثال، ارجاع (referencing)، به سمت پایین از چپ به راست میرود. صرفِ تمرین، بیایید سعی کنیم جهت را عوض کنیم، برای مثال، به سمت بالا.
در آرایههای سهبعدی فقط حضور یک شاخص بیشتر برای ارجاع به مقادیر سلولها را داریم. یک آرایهی سهبعدی میتواند بهسادگی بهشکل چندین جدول (آرایههای دوبعدی) نمایش داده شود. بدین صورت میتوانیم تمام اِلمانهای یک آرایهی سهبعدی را بررسی کنیم:
int array3D[3][3][3] = {11, 12, 13, ۱۴, ۱۵, ۱۶, ۱۷, ۱۸, ۱۹, ۲۱, ۲۲, ۲۳, ۲۴, ۲۵, ۲۶, ۲۷, ۲۸, ۲۹, ۳۱, ۳۲, ۳۳, ۳۴, ۳۵, ۳۶, ۳۷, ۳۸, ۳۹}; for(int z = 0; z < 3; z++) for(int y = 0; y < 3; y++) for(int x = 0; x < 3; x++) MessageBox("array3D["+z+"]["+y+"]["+x+"]=" + array3D[z][y][x]);
بهطور کامل آرایههای دوبعدی و سهبعدی را مطالعه کنید، زیرا مبحث بسیار مهمی است. یک بار دیگر خیلی دقیق و موشکافانه، به تصاویر و توضیحات آنها توجه کنید. بسیاری از مسائل را با استفاده از آرایهها حل کردیم، بنابراین جا دارد وقت کافی برای آنها بگذارید چراکه در آینده نیز به کمک شما خواهند آمد. اگر اصول کار با آرایهها را یاد گرفته باشید، دیگر مشکلی حتی برای کار کردن با آرایههای n بعدی هم نخواهید داشت.
برخی از توابع برای کار کردن با آرایهها
بیایید با توابع ساده شروع کنیم.
int ArraySize(object array[]);
این تابع حجم (amount) اِلمانهایی که در آرایه هستند را، برمیگرداند، و با همه نوع آرایه کار میکند. برای مثال،
// create two different arrays int arrayInt[] = {1, 2, 3, 4}; double arrayDouble[] = {5.9, 2.1, 4.7}; // here store the amount of elements int amount; amount = ArraySize(arrayInt); // note: // to define a specific // array, you need to indicate // only its name. // Now amount is equal to 4 amount = ArraySize(arrayDouble); // amount is equal to 3
تابع بعدی:
int ArrayInitialize(object array[],double value);
ArrayInitialize
یک مقدار را به تمام اِلمانهای آرایه اختصاص میدهد، و حجم اِلمانها را، به اِلمانهایی برمیگرداند که یک مقدار برایشان اختصاص یافته است. از این تابع همراه با آرایههایی از نوع int و double استفاده کنید.
بعدی:
int ArrayMaximum(double array[], int count = WHOLE_ARRAY, int start = 0); int ArrayMinimum(double array[], int count = WHOLE_ARRAY, int start = 0);
این دو تابع شاخص حداکثری و حداقلی مقدار سلول را برمیگردانند. برای استفاده از آنها، خیلی ساده مشخص کنید در کدام آرایه باید در جستجوی آنها باشیم:
int array[] = {10, 100, 190, 3, 1}; // will be returned 1, because array[1] - maximal value ArrayMaximum(array); // will be returned 4, because array[4] - minimal value ArrayMinimum(array);
بعدی:
int ArrayDimension(object array[]);
با استفاده از این توابع، میتوانید ابعاد یک آرایه را تعیین کنید، بهعبارت دیگر، میتوانید تعیین کنید، یکبعدی است، دوبعدی است یا n بعدی. برای مثال:
int array1D[15]; int array4D[3][3][3]; ArrayDimension(array1D); // get 1 ArrayDimension(array3D); // 3
در اینجا توابع پیچیدهتر و پرکاربردتری را داریم:
int ArraySort(double&array[], int count = WHOLE_ARRAY, int start = 0, int sort_dir = MODE_ASCEND);
این تابع، اِلمانها را مرتب میکند. اگر شما مستقیماً استدلالها را روی پیشفرض مشخص نکنید، برای مثال اینگونه:
int array[5] = {1, 10, 5, 7, 8}; ArraySort(array);
اِلمانها بهصورت صعودی (ascending) مرتب خواهند شد. میتوانید از پارامترهای اضافی برای مشخص کردن عملکرد تابع استفاده کنید:
- int count – تعداد اِلمانهایی که باید مرتب شوند
- int start – شاخص یک اِلمان که از آن مرتبسازی باید آغاز شود
- int sort_dir – جهتِ مرتبسازی (صعودی – MODE_ASCEND یا نزولی – MODE_DESCEND)
اینجا باید تعجب کنید: MODE_ASCEND و MODE_DESCEND دیگر چیست؟ int احتمال قوی integer است! با توجه به این، اصلاً نگران نباشید، همهچیز در بخش بعدی، “پیشپردازنده”، شفاف خواهد شد. برای مثال، اگر میخواهید ۵ اِلمان را، از دومی، بهصورت نزولی مرتب کنید، چیزی مثل این را نیاز دارید:
ArraySort(array, 5, 1, MODE_DESCEND);
و آخرین تابع برای امروز:
int ArrayCopy(object&dest[], object source[], int start_dest = 0, int start_source=0, int count=WHOLE_ARRAY);
از این تابع برای کپی کردن یک آرایه به آرایه دیگر استفاده میشود. بیایید پارامترهای واجب را با هم ببینیم:
- dest[] – که در آن آرایه کپی خواهد شد
- source[] – که از آن آرایه کپی خواهد شد
پارامترهای اختیاری:
- start_dest – شاخص یک اِلمانِ آرایه، که درون آن کپی انجام میشود
- start_source – شاخص یک اِلمانِ آرایه، که از آن کپی انجام میشود
- int count – تعداد اِلمانها برای کپی
این تابع تعداد اِلمانهای کپیشده را برمیگرداند. از ArrayCopy بسیار با دقت استفاد کنید: مطمئن شوید که آرایهها، وقتی دارید درون آنها کپی انجام میدهید، بهاندازهی کافی ظرفیت دارند!
پیشپردازنده
این دیگر چیست؟! پیشپردازنده یک مکانیزم خاص است که برای پردازش سورس کد درنظر گرفته شدهاست. بهعبارت دیگر، ابتدا پیشپردازنده یک کد را آماده میکند و سپس آن را برای کامپایلشدن منتقل میکند. امروز، یک گزینهی کاربردی دیگر یاد خواهیم گرفت – constants.
فایدهی این کار چیست؟ برای فهمیدن این موضوع، بیایید مثالی از بخش switch را بهیاد بیاوریم:
switch(marketState) { case 1: // trading strategy for an uptrend break; case 2: // strategy for a downtrend break; case 3: // strategy for a flat break; default: // error: this state is not supported! break; }
در اینجا مکانیزمی را فعال کردیم که به طُرق مختلف بسته به وضعیت بازار، عمل میکند. یادتان آمد؟ بنابراین، سادهتر و توصیفیتر این است که بهجای ۱، ۲ و ۳، چیزی مانند TREND_UP، TREND_DOWN، FLAT، را بنویسیم:
switch(marketState) { case TREND_UP: // trading strategy for an uptrend break; case TREND_DOWN: // strategy for a downtrend break; case FLAT: // strategy for a flat break; default: // error: this state is not supported! break; }
در این شرایط، فهمیدن سورس کد بسیار سادهتر و شفافتر است، مگه نه؟ پس، constants اجازه میدهد که قبل از کامپایل کردن، TREND_UP، TREND_DOWN، FLAT، را با مقادیر مرتبط، یعنی ۱، ۲ و ۳، جایگزین کنیم. تمام کاری که باید انجام دهید این است که مشخص کنید پیشپردازنده چه چیزی را باید تغییر دهد. این کار بهوسیلهی دستورات پیشپردازنده[۷] انجام خواهد شد، که از یک نماد خاص یعنی “#” آغاز میشود. دستورات پیشپردازنده باید در ابتدای سورس فایل، همراه با دیگر دستورات، قرار بگیرند. بیایید به مثالی کامل از استفاده از constants نگاهی بیندازیم:
//+------------------------------------------------------------------+ //| preprocessor.mq4 | //| Copyright © ۲۰۰۷, Antonio Banderass. All rights reserved | //| banderassa@ukr.net | //+------------------------------------------------------------------+ #property copyright "Copyright © ۲۰۰۷, Antonio Banderass. All rights reserved" #property link "banderassa@ukr.net" #define TREND_UP 1 #define TREND_DOWN 2 #define FLAT 3 //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + TREND_DOWN + " FLAT=" + FLAT); return(0); }
لطفاً بهیاد داشته باشید که اعلام constants را در ابتدای فایل، زیر دیگر دستورات پیشپردازنده، قرار دادیم. بیایید اعلام را از نزدیک بررسی کنیم:
#define TREND_UP 1
ابتدا کلیدواژهی #define را مینویسیم. این کار به پیشپردازنده نشان میدهد که بعد از آن، اعلام constant را داریم. سپس، نام constant را مینویسیم – معینکنندهی هویت آن را – بهعبارت دیگر، یک کلمه که با آن به مقدار constant، رجوع میکنیم. در اینجا TREND_UP است. مقدارِ ۱ بعد از آن میآید. اکنون، وقتیکه پیشپردازنده TREND_UP را در سورس کد میبیند، آن را با ۱ جایگزین میکند، و همین رویه برای تمام دیگر constantها هم به همین شکل است. در اینجا سورس کد مثالمان را قبل از پردازش توسط یک پیشپردازنده، میبینید:
int start() { MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + TREND_DOWN + " FLAT=" + FLAT); return(0); }
و سپس:
int start() { MessageBox("TREND_UP=" + 1 + " TREND_DOWN=" + 2 + " FLAT=" + 3); return(0); }
اکنون باید فهمیده باشید که MODE_ASCEND و MODE_DESCEND از بخش قبلی چه معنایی میدهند. اینها constantهایی هستند با مقادیر مرتبط.
نتیجهگیری
چیزهایی زیادی از این مقاله یاد گرفتید: مدل جدید سیکل – while؛ مدل جدید شرط – switch؛ عملگرهای break و continue. یاد گرفتید که توابع خودتان را بنویسید و با آرایههای چند بعدی کار کنید. یاد گرفتید از constantها چگونه استفاده کنید. تمام اینها ابزارهای اصلی شما برای نوشتن چیزهای پیشرفتهتر هستند، مثل اندیکاتور و اکسپرت. به همین دلیل باید مطمئن شوید تمام مطالب را کاملاً یاد گرفتهاید زیرا علاوه بر اهمیت مطالب، از آنها دائماً در آینده استفاده خواهید کرد.
این مقاله دارای فایل پیوست است.
[۱]) Counter
[۲]) Cycle body
[۳]) Instruction
[۴]) Bracers
[۵]) Argument
[۶]) Reference to the value
[۷]) Preprocessor directives
۲۶ مورد نظر
homeopathic remedies for ed
cialis manufacturer coupon lilly cialis 20 mg best price cialis windsor canada pharmacy
cialis sample pack purchasing cialis in the usa genic cialis
buy prednisone online without a script order prednisone over the counter prednisone cheap
prednisone 5084 buy prednisone online order prednisone
erection pills that work ed in young men hims ed pills
cheap tablet cialis cialis 20 mg best price cialis one a day with dapoxetine canada
prednisone 10mg prices cheap prednisone prednisone 30
cheap ed drugs erectile dysfunction drug online ed pills
stromectol tea tree oil how to treat heartworms with ivermectin ivermectin sheep drench
ivermectin for humans walgreens how to take ivermectin for scabies durvet ivermectin for dogs
is ivermectin safe for dogs ivermectin lotion (sklice) ivermectin dosage for guinea pigs
ivermectin for dogs side effects buy ivermectin pill ivermectin after vaccine
ed pill ed pills online male erection pills
erectile dysfunction pills erection pills online best ed pills
reputable online pharmacies in india india pharmacies online reputable online pharmacies in india
generic drugs without doctor’s prescription reputable canadian mail order pharmacies aarp approved canadian online pharmacies
best pills for ed treatment of ed ed drugs compared
generic drugs india order online buy prescriptions from india pharmacy buy prescription online from india
stromectol for sale stromectol for sale stromectol for humans for sale
stromectol for humans for sale ivermectin without a doctor prescription stromectol for sale
sildenafil citrate 100mg for sale viagra tablets for men sildenafil 100 mg
prescribing stromectol prescribing stromectol stromectol pills for humans
prescribing stromectol stromectol for sale stromectol for sale
where to buy cheap clomid online clomid for sale canada clomid tablets for sale
ivermectin 9 mg tablet ivermectin for goats lice stromectol 12 mg tablets