آموزش گام‌به‌گام #C (جلسه اول: آغاز کار با #C)
1397/12/21 12:48 , میلاد صاحب نظر

آموزش گام‌به‌گام #C (جلسه اول: آغاز کار با #C)

سایت MUG با دوره کاملی از آموزش مقدماتی تا پیشرفته #C در خدمت شما است. مفاهیم و موضوعات مختلف دوره #C در جلسات مختلف همراه با حل تمرین آموزش داده خواهند شد. با ما همراه باشید.

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چند ریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

در این جلسه با معرفی چند برنامه ساده، کار با #C را آغاز می‌کنیم. در زیر اهداف این جلسه را مشاهده می‌کنید:

  • درک ساختار ساده و کلی یک برنامه #C
  • آشنایی اولیه با مفهوم “Namespace”
  • درک ساده از مفهوم کلاس
  • یادگیری عملکرد متد Main
  • یادگیری چگونگی کد زدن در خط فرمان
  • یادگیری کنسول ورودی / خروجی(I/O)

یک برنامه #C ساده

عناصر ساده‌ای وجود دارند که همه برنامه‌های قابل اجرا با #C آن‌ها را دارند و این عناصر، نکاتی هستند که در جلسه اول تمرکز ما کاملا بر روی آن‌ها است. کارمان را با یک برنامه #C ساده آغاز می‌کنیم.

بعد از بررسی کد در لیست ۱-۱، مفاهیم ساده‌ای که در همه برنامه‌های #C وجود دارند را بیان خواهم کرد. لطفا لیست ۱-۱ را بررسی کنید تا اولین برنامه خود در #C را ببینید.

هشدار: زبان برنامه‌نویسی #C یک زبان case-sensitive است، یعنی به حروف بزرگ و کوچک کدها حساس است.

لیست ۱-۱: یک برنامه خوش‌آمد گویی ساده: Welcome.cs

// Namespace تعریف
using System;

// کلاس آغاز برنامه
class WelcomeCSS
{
    //اجرای برنامه را آغاز می‌کند Main تابع.
    static void Main()
    {
        // نوشتن در کنسول
        Console.WriteLine("Welcome to the C# Station Tutorial!"); 
    }
}

برنامه موجود در لیست ۱-۱ دارای ۴ عنصر و بخش اصلی است، یک بخش برای تعریف Namespace، یک کلاس، متد Main و عبارت برنامه. می‌توان این برنامه را با خط فرمان زیر کامپایل کرد:

 csc.exe Welcome.cs

این کد، فایلی با نام Welcome.exe ایجاد می‌کنید، که وقتی روی آن کلیک کنید، برنامه شما اجرا خواهد شد. برنامه‌های دیگر نیز با جایگزینی نام فایلشان به جای Welcome.cs می‌توانند به همین صورت فایل اجرایی داشته باشند.

برای به دست آوردن اطلاعات و کمک بیشتر در مورد قسمت خط فرمان، عبارت “csc –help” را در خط فرمان تایپ کنید. نام فایل و نام کلاس می‌توانند کاملا متفاوت باشند.

نکته برای کاربران Visual Studio.NET: وقتی این برنامه را از Visual Studio.NET اجرا می‌کنید، صفحه سریع اجرا و بسته می‌شود. برای جلوگیری از این حالت، کد زیر را در آخرین خط کد در متد Main اضافه کنید:

// برای جلوگیری از بسته شدن سریع صفحه
// اجرا می‌شود VS.NET وقتی برنامه با 
Console.ReadLine();

نکته: خط فرمان پنجره‌ای است که به شما اجازه می‌دهد دستورات و برنامه‌ها را با تایپ کردن دستی متن اجرا کنید. گاهی به آن DOS prumpt هم می‌گویند، که همان‌طور که اطلاع دارید DOS سیستم عاملی است که سال‌ها پیش، قبل از منتشر شدن ویندوز مورد استفاده قرار می‌گرفت.

NET Framework SDK. که رایگان هم هست، بیشتر از ابزارهای خط فرمان استفاده می‌کند. از این رو، من این تمرین را به این شکل نوشتم تا همه استفاده از خط فرمان را یاد بگیرند. از طریق مرورگر خود عبارت “csc.exe” را جستجو کنید. “csc.exe کامپایلر #C است.

وقتی توانستید مکان این فایل را مشخص کنید، آن را به مسیر ویندوزتان اضافه کنید. سپس با رفتن به منوی استارت ویندوز> انتخاب run و تایپ cmd.exe، پنجره فرمان را باز کنید.

اولین نکته‌ای که باید از آن آگاه باشید این است که #C یک زبان case – sensitive است. کلمه “Main” اصلا کاربرد مشابهی با کلمه “main” ندارد. این دو، شناساگرهای متفاوتی هستند. اگر قبلا با زبانی آشنا شده‌اید که حساس به بزرگی و کوچکی حروف نیست، زمان می‌برد تا بتوانید به این ویژگی #C عادت کنید.

عبارت معرفی کننده namespace، عبارت using System است. این عبارت بیان می‌کند که شما از کتابخانه System namespace استفاده می‌کنید. Namespace حاوی مجموعه کدهایی است که می‌توان آن‌ها را در برنامه‌های #C فراخوانی کرد.

با نوشتن عبارت using System، شما به برنامه می‌گویید که بدون اینکه لازم باشد قبل از هر قطعه کد واژه System تایپ شود، می‌تواند از کدهای موجود در Systemnamespace استفاده کند. در جلسه ششم که کاملا در ارتباط با انواع Namespaceها هست، بیشتر در این مورد صحبت خواهم کرد.

عبارت تعریف کلاس، یعنی class WelcomeCSS، حاوی داده‌ها و تعاریف متدهایی است که برنامه شما برای اجرا از آن‌ها استفاده خواهد کرد. کلاس یکی از معدود انواع عناصری است که برنامه شما می‌تواند برای تعریف اشیاء(مانند ساختارها، واسط‌ها، اختصاص‌ها و enumها) از آن استفاده کند.

موضوعات ساختارها، واسط‌ها، اختصاص‌ها و enumها به ترتیب در جلسات ۱۲ و ۱۳ و ۱۴ و ۱۷با جزئیات کامل توضیح داده خواهند شد. در این برنامه، این کلاس به خصوص، هیچ  داده‌ای ندارد، اما دارای یک متد است. این متد، رفتار این کلاس را تعریف می‌کند(یا به عبارت دیگر بیان می‌کند که این کلاس چه کاری انجام می‌دهد). 

در جلسه ۷ بیشتر در مورد کلاس‌ها صحبت خواهم کرد. در جلسه ۷ اطلاعات زیادی در مورد کلاس‌ها ارائه خواهم داد.

متد موجود در داخل کلاس WelcomeCSS بیان می‌کند که وقتی برنامه اجرا شود، این کلاس چه کاری انجام خواهد داد.

نام متد، یعنی Main، به عنوان نقطه آغاز برنامه در نظر گرفته شده است. گاهی Main را با عنوان "نقطه ورود" نیز شناخته می‌شود و اگر زمانی یک پیغام ارور کامپایلری دریافت کردید که بیان می‌کرد: نمی‌تواند entry point(نقطه ورود) را پیدا کند، یعنی اینکه شما سعی در اجرای برنامه‌ای دارید که متد Main ندارد.

واژه static که قبل از Main آمده است، به این معنا است که این متد فقط در این کلاس به خصوص عمل می‌کند، نه در کل کلاس‌ها. این کار ضروری است، چون وقتی یک برنامه آغاز می‌شود، هیچ نمونه شیئی وجود ندارد.

همه متدها باید یک نوع بازگشتی داشته باشند. در این مورد، نوع بازگشتی ما void است، که بیان می‌کند Main هیچ مقداری را باز نمی‌گرداند. همچنین همه متدها دارای یک لیست از پارامترها هستند که بعد از نام متد بین پرانتزها نوشته شده و تعداد آن‌ها می‌تواند صفر یا هر رقم دیگری باشد.

برای ساده بودن کار، ما هیچ پارامتری به Main اضافه نکردیم. در ادامه این جلسه، خواهید فهمید که متد Main چه پارامترهایی می‌تواند بگیرد. در مورد متدها در جلسه پنجم بیشتر توضیح خواهم داد.

متد Main، رفتارش را با عبارت (...)Console.WriteLine مشخص می‌کند. Console یک کلاس در System namespace است. (...)WriteLine یک متد در کلاس Console است. از “.” یعنی عملگر نقطه برای جدا کردن عناصر مختلف برنامه استفاده می‌کنیم.

توجه کنید که این عبارت را می‌توانستیم به شکل (...)System.Console.WriteLineهم بنویسیم. این نوع کد نویسی از الگوی “namespace.class.method” به عنوان یک عبارت کاملا صحیح و معتبر پیروی می‌کند. اگر عبارت تعریف using System را در بالای برنامه نمی‌نوشتیم، مجبور می‌شدیم که برای اجرای برنامه،

حتما کدها را با الگوی (...)System.Console.WriteLine بنویسیم. این عبارت، عاملی است که باعث می‌شود رشته "!Welcome to MUG C# Tutorialُ” در صفحه کنسول نمایش داده شود.

قطعه کدهایی که با علامت “//” به رنگ سبز درآمده‌اند را مشاهده کنید. این‌ها نظرها یا کامنت‌های تک خطی هستند. به این معنا که واژه‌های بعد از // فقط تا انتهای خط به عنوان نظر یا کامنت معتبر هستند. اگر می‌خواهید چندین خط کامنت بنویسید، باید ابتدای خط را با “/*” آغاز کنید و انتهای خط را نیز با “*/” ببندید.

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

همه کدها با یک “;” یا سمی‌کالن پایان می‌یابند. کلاس‌ها و متدها با آکولاد باز “}“ شروع و با آکولاد بسته "{" پایان می‌یابند. هر کدی که داخل و بین آکولادها قرار گیرد، یک بلوک را تعریف می‌کند. بلوک‌ها، گستره(یا طول عمر و مدت زمان دیده شدن)عناصر برنامه را تعریف می‌کنند.

پذیرش ورودی خط فرمان

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

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

برای مثال، اگر تایپ کنید Notepad.exeMyFile.txt(با فرض اینکه فایل MyFile وجود داشته باشد)، آنگاه برنامه نوت پد فایل MyFile.txt شما را باز می‌کند تا بتوانید شروع به ویرایش آن کنید.

شما هم می‌توانید برنامه خود را به گونه‌ای بنویسید که ورودی خط فرمان را بپذیرد. در لیست ۲-۱، برنامه‌ای را مشاهده می‌کنید که از خط فرمان یک نام را گرفته و آن را در کنسول می‌نویسد.

خطر! قبل و بعد از نوشتن کدهای درون لیست ۲-۱، باید آرگومان‌های مناسب برای استفاده از خط فرمان را درج کنید. در غیر این صورت هنگام اجرای برنامه با ارور و باگ‌های فراوانی رو به رو خواهید شد!!! پس لطفا ابتدا دستورالعمل‌های درج آرگومان خط فرمان را مطالعه کنید.

نکته: وقتی برنامه NamedWelcom.exe حاصل از کدهای لیست ۲-۱ را اجرا می‌کنید، باید ابتدا آرگومان‌های خط فرمان را بنویسید. برای مثال، نام برنامه را تایپ کنید و در ادامه نام خودتان را بنویسید: NamedWelcomeYourName. اصلا هدف لیست ۲-۱ همین است – که به شما نشان دهد چگونه باید ورودی خط فرمان را کنترل کنید.

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

اگر با استفاده از Visual Studio کد می‌زنید، در قسمت Solution Explorer روی project کلیک راست کنید، Propeties را انتخاب کنید، روی تب Debug کلیک کنید، Start Options را پیدا کنید و درون آرگومان‌های خط فرمان عبارت YourName(یعنی نام خودتان مثلا Ali) را تایپ کنید.

اگر فراموش کنید YourName را روی خط فرمان وارد کنید یا آن را درون project properties وارد کنید، یک Exception دریافت خواهید کرد که می‌گوید “Index was outside the bounds of array.”(شاخص خارج از محدوده آرایه قرار دارد).  

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

لیست ۲-۱: دریافت ورودی خط فرمان: NamedWelcome.cs

// Namespace نعریف
using System;

// کلاس آغاز برنامه
class NamedWelcome
{
    //اجرای برنامه را آغاز می‌کند Main تابع
    static void Main(string[] args)
    {
        // نوشتن در کنسول
        Console.WriteLine("Hello, {0}!", args[0]);
        Console.WriteLine("Welcome to the C# Station Tutorial!"); 
    }
}

نکته: حتما حواستان باشد که نام خودتان را به خط فرمان اضافه کنید مثلا “NamedWelcome Ali”. اگر این کار را نکنید، برنامه شما کرش خواهد شد. در جلسه ۱۵ به شما نشان خواهم داد که چگونه می‌توانید این نوع ارورها را شناسایی و از بروز آن‌ها جلوگیری کنید.

اگر از یک IDE مثل ویژوال استودیو استفاده می‌کنید، فایل کمک IDE خود را مطالعه کنید تا بفهمید که چگونه می‌توانید آپشن خط فرمان را از طریق project properties تنظیم کنید.

در لیست ۲-۱، متوجه یک ورودی در لیست پارامتر متد Main می‌شوید، نام پارامتر args می‌باشد، که بعدا از آن برای اشاره به پارامتر استفاده خواهید کرد. عبارت []string نوع پارامتر args را تعریف می‌کند. نوع String یا رشته، کاراکترها یا حروف را می‌پذیرد. این حروف می‌توانند یک کلمه یا چندین کلمه را تشکیل دهند.

کروشه‌ها(“[]”) مشخص کننده آرایه هستند. آرایه چیزی شبیه به یک لیست است. در نتیجه، نوع پارامتر args، لیستی از کلمات است که از طریق خط فرمان وارد می‌شوند.

هر موقع عبارت string[]args را به لیست پارامتر متد Main اضافه کنید، کامپایلر #C کدی که آرگومان‌های خط فرمان را parse می‌کند را استخراج کرده و آرگومان‌های خط فرمان را به داخل args منتقل می‌کند. با خواندن args، شما به همه آرگومان‌ها(به جز نام برنامه که در خط فرمان تایپ می‌شود)دسترسی خواهید داشت.

همچنین یک عبارت (…)Console.WriteLineاضافی نیز در داخل متد Main مشاهده می‌کنید. لیست آرگومان‌ها در این عبارت با برنامه قبلی فرق می‌کند. این کد دارای یک فرمت رشته با یک پارامتر “{0}” قرار داده شده درون رشته، می‌باشد.

اولین پارامتر با فرمت رشته از شماره ۰ شروع می‌شود، دومین با شماره ۱ و الی آخر. پارامتر “{0}” یعنی اینکه آرگومان بعدی در انتهای عبارت وارد شده قرار می‌گیرد.

آرگومان [args[0 به اولین رشته در آرایه args اشاره می‌کند. اولین عنصر از یک آرایه عدد صفر، دومین عنصر عدد ۱ و الی آخر است. برای مثال، اگر من در خط فرمان تایپ کنم NamedWelcome Ali، مقدار [args[0، علی("ALI") خواهد بود.

این قسمت کمی گیج کننده است، چون شما می‌دانید که NamedWelcome.exe را در خط فرمان تایپ کرده‌اید، اما #C نام برنامه قابل اجرا را در لیست Args قرار نمی‌دهد – فقط اولین پارامتر پس از نام برنامه قابل اجرا در این لیست قرار می‌گیرد.

حالا برگردیم به سراغ پارامتر “{0}” درج شده با فرمت رشته: چون [args[0 اولین آرگومان پس از فرمت رشته در عبارت ()Console.WriteLine است، پس مقدار آن درون اولین پارامتر درج شده با فرمت رشته قرار خواهد گرفت.

وقتی این دستور اجرا می‌شود، مقدار [args[0 که “ALI” است، جایگزین “{0}” با فرمت رشته خواهد شد. با اجرا شدن خط فرمان با عبارت “NamedWelcomeAli”، خروجی به شکل زیر خواهد بود:

Hello, ALI!
Welcome to the MUG C# Tutorial!

تعامل از طریق خط فرمان

در کنار ورودی خط فرمان، روش دیگری هم به منظور فراهم کردن ورودی برای یک برنامه از طریق کنسول وجود دارد. معمولا، عملکرد این روش به این صورت است: از کاربر می‌خواهید مقداری را وارد کند، کاربر چیزی را تایپ می‌کند و کلید Enter را می‌فشارد و شما ورودی او را خوانده و کاری روی آن انجام می‌دهید.

لیست ۱-۳ نشان می‌دهد که چگونه می‌توانید برای وارد کردن ورودی با کاربر تعامل داشته باشید.

لیست ۳-۱: به دست آوردن ورودی تعاملی: InteractiveWelcome.cs

// Namespace تعریف
using System;

// کلاس آغاز برنامه
class InteractiveWelcome
{
    //اجرای برنامه را آغاز می‌کند Main تابع
    public static void Main()
    {
        // نوشتن در کنسول / گرفتن ورودی
        Console.Write("What is your name?: ");
        Console.Write("Hello, {0}! ", Console.ReadLine());
        Console.WriteLine("Welcome to the C# Station Tutorial!"); 
    }
}

در لیست ۳-۱، متد Main هیچ پارامتری ندارد – بیشتر به این دلیل که این دفعه وجود پارامتر ضرورت ندارد. همچنین توجه کنید که من عبارت Mainmethod را با کلیدواژه پیشوند public نوشته‌ام. کلیدواژه public یعنی اینکه هر کلاسی خارج از این کلاس، می‌تواند به آن بخش دسترسی داشته باشد.

برای Main، این ویژگی هیچ اهمیتی ندارد چون کد شما هیچوقت Main را فراخوانی نمی‌کند، اما اگر این آموزش را دنبال کنید، متوجه خواهید شد که چگونه می‌توانید کلاس‌هایی دارای بخش‌های خاصی ایجاد کنید که برای قابل استفاده بودن، باید public باشند.

دسترسی پیش‌فرض private است، که یعنی فقط بخش‌های درون همان کلاس، می‌توانند به آن بخش دسترسی داشته باشند. کلیدواژه‌هایی مثل public و private به عنوان تعیین کننده دسترسی شناخته می‌شوند. در جلسه ۱۹ام درمورد تعیین کننده‌های دسترسی بیشتر صحبت خواهیم کرد.

سه عبارت درون Main قرار دارند و دوتای اولی با سومی فرق دارند. آن‌ها به جای اینکه به صورت (…)Console.WriteLine نوشته شوند، به صورت (…)Console.Write نوشته شده‌اند.

تفاوت این است که عبارت (…)Console.Write کنسول را می‌نویسد و در همین خط متوقف می‌شود، اما عبارت (…)Console.WriteLine بعد از نوشتن کنسول به خط بعدی می‌رود.

اولین عبارت در کنسول فقط می‌نویسد :”:?What is your name”.

دومین عبارت تا وقتی که آرگومان‌هایش کاملا ارزیابی نشوند، هیچ چیز نمی‌نویسد. اولین آرگومان پس از فرمت رشته، (…)Console.ReadLine است. این کد باعث می‌شود برنامه در کنسول منتظر ورودی کاربر بماند.

بعد از اینکه کاربر ورودی خود را تایپ کرد، که در این مورد ورودی نام کاربر است، آن‌ها باید کلید Enter را بزنند.

حالا مقدار بازگشتی از این متد جایگزین پارامتر “{0}” با فرمت رشته شده و درون کنسول نوشته می‌شود. این خط را می‌توان به شکل زیر نیز نوشت:

string name = Console.ReadLine(); 
Console.Write("Hello, {0}! ", name);

آخرین عبارت، همان‌طور که قبلا توضیح داده شد خروجی را در کنسول می‌نویسد. با اجرای خط فرمان همراه با عبارت “InteractiveWelcome”، خروجی به شکل زیر خواهد بود:

[What is your Name?  <type your name here> [Enter Key>

!Hello, <your name here>!  Welcome to the MUG C# Tutorial>

خلاصه

حالا با ساختار ابتدایی یک برنامه #C آشنا هستید. عباراتی که using دارند به شما اجازه می‌دهند به namespace اشاره کنید و باعث می‌شوند بتوانید کدها را خیلی کوتاه‌تر و خواناتر بنویسید. متد Main نقطه آغازین یا ورودی برای شروع یک برنامه #C است.

وقتی برنامه با خواندن آیتم‌ها از یک پارامتر []string(آرایه رشته) درون متد Main اجرا می‌شود، می‌توانید ورودی خط فرمان را بگیرید. I/O تعاملی با متدهای ReadLine، Write و WriteLine از کلاس Console اجرا می‌شود.

 منبع:C# - STATION

جلسه بعد 

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

 

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

دیدگاه خود را درباره این پست بنویسید

فرم ارسال نظرات