0

تونلی به دنیای قدیم

 
samsam
samsam
کاربر طلایی1
تاریخ عضویت : بهمن 1387 
تعداد پست ها : 50672
محل سکونت : یزد

تونلی به دنیای قدیم

دریافت دستورات در برنامه های مختلف، به شیوه های مختلف انجام می پذیرد. ممکن است از طریق صفحه نمایش چند لمسی دستورات به برنامه وارد شود، ممکن است از طریق ماوس، و یا حتی ممکن است با تایپ دستورات، بخواهیم برنامه را کنترل کنیم. کنترل برنامه ها با تایپ دستورات، زمانی به کار می آید که دسترسی مستقیم یا دسترسی گرافیکی به برنامه نداریم و یا باید از طریق کنسول با برنامه خود ارتباط برقرار کنیم و پاسخ را دریافت کنیم. در این حالت، قابلیت اجرا از طریق خط فرمان یک مزیت برای برنامه مان به حساب خواهد آمد. در این مقاله قصد نداریم به سراغ دستورات پیچیده برویم و تلاش بر این است که با مفاهیم شی گرای فعلی، یک پارسر برای خط فرمان بنویسیم. با بسط و گسترش همین کدها می توان هر برنامه ای را به موتور تشخیص دستور از راه خط فرمان مجهز کرد. نخست آن که وجه شباهت تمامی دستورات با همدیگر، این است که همه شان دارای پارامترهای ورودی هستند و همه آنها باید به شیوه ای صحیح اجرا شوند. به عبارت دیگر وقتی دستوری وارد می شود، باید تشخیص داده شده، اجرا شده، و در صورت عدم شناسایی دستور، پیغام خطا ارسال کند. قدم نخست برای راه اندازی یک خط فرمان، تولید کلاسی پایه به صورت زیر است: class basecommand { public : basecommand(int argc,char** argv); basecommand(); virtual void execute(); virtual bool contain(const char* arg); virtual void printhelp(); private : int argc; char** argv; { این کلاس چیست و چه کاری قرار است انجام دهد؟ این کلاس تمامی متدها و فیلدهای مورد نیاز برای اجرا و نگهداری هر دستور را در خود دارد، و به عبارت بهتر یک شی از یک دستور است. بقیه دستورات از این کلاس ارث بری می کنند و مستلزم بازنویسی متدهایی هستند که به صورت مجازی (virtual) تعریف شده اند. این کلاس دو فیلد با دسترسی خصوصی (private) دارد. دلیل این امر این است که اشیا دیگر نیازی به دانستن مقدار آنها و دیدن آنها از یک شی دیگر ندارند و در واقع این در این فیلدها مشخص می شود که چه دستوری چگونه باید اجرا بشود. فیلد اول argc تعداد آرگومان های ورودی هر دستور را مشخص می کند و فیلد argv یک آرایه دو بعدی از کاراکترها (آرایه ای از رشته ها) است، که شامل دستور و پارامترهای ورودی آن دستور است. این کلاس دو سازنده دارد که یکی از آنها مقدارهای argc و argv را از ورودی می گیرد و دیگری هیچ آرگومانی را نمی پذیرد و از آن به سازنده پیش فرض (default constructor) یاد می شود. متد execute دستور را اجرا می کند و وظیفه آن مدیریت اجرای صحیح دستور است. و متد دیگر printhelp است، این متد زمانی اجرا می شود که دستور با پارامتر /? اجرا شود و هدف آن نشان دادن اطلاعاتی در مورد دستور است. متد دیگر contain است این متد بررسی می کند آیا پارامتر خاصی در argv موجود است یا خیر. بسیار خب، حالا به یک فرمت کلی دست پیدا کردیم و می دانیم برای پیاده سازی هر دستور به چه چیزهایی نیاز است و هر دستور باید از چه الگویی باید پیروی کند. حالا می توان به شیوه ای دیگری به هر دستور نگاه کرد تا پیاده سازی راحت تری داشته باشد. هر دستور یکسری پارامتر را به عنوان ورودی دریافت می کند. خوب هر پارامتر برای انجام عمل خاصی است، پس در کلاس های مربوط به هر دستور علاوه بر دستورات فوق باید متدهایی برای انجام هر عمل نوشته شود. به طور مثال دستور copy، این دستور باید دو پارامتر را به صورت پیش فرض دریافت کند. اولین پارامتر فایل منبع و دومی فایل مقصد را مشخص می کند حال اگر دستور copy با فرمان /x اجرا شود باید فایل منبع به مقصد منتقل شود و کپی گرفته نشود. بنابراین، دو متد به نام های copyfile و movefile را باید در کلاس مربوط به دستور copy بنویسیم که عملیات مربوطه را انجام دهند. مشکلی که در این میان ممکن است رخ بدهد، این است که متدهای movefile و copyfile را باید به چه صورتی تبدیل کنیم که امنیت کافی داشته باشد؟ آیا این متدها private باشند یا public؟ از آنجا که این متدها برای کلاس مربوط به دستور copy هستند پس باید به صورت private تعریف شوند. اما اگر طور دیگری به این دو متد نگاه کنیم، و اگر دستور دیگری داشتیم که نیاز به کپی و کات کردن فایل ها داشت نتیجه چه می شد؟ باید این متدها هر بار نوشته شوند؟ یا اینکه آنها را بصورت عمومی تعریف کنیم؟ اگر به صورت عمومی تعریف کنیم، طراحی ما غلط است چون دیگر کلاس ها نباید متدهایی که برای اجرای پارامترهای ورودی هر دستور هستند را ببینند، راه حل چیست؟می توانیم با نوشتن یک کلاس جداگانه برای کارکردن با فایل ها، این مشکل را حل کنیم. این کار دو مزیت دارد: 1- متدهای copyfile و movefile از سطح کلاس دستورها جدا خوهد شد و بطور مستقل کار می کنند. این کار debug (اشکال زدایی) برنامه را راحت تر و نگهداری کد را ساده تر می کند. در ضمن طراحی یکپارچه ای خواهیم داشت، بدین ترتیب کلاس file را برای کار با فایل ها را به صورت زیر می نویسیم: class file{ const static int buf_size = 4096; public: static void copy(char* source,char* destination); static void move(char* source,char* destination); static void delete(char* filename); static void rename(char* oldname,char* newname); static bool exist(char* filename); static void create(char* filename,bool overwrite); }; نیازی به توضیح در مورد متدهای کلاس نیست، بسیار خوب پس پیاده سازی متد execute از کلاس مربوط به دستور copy به صورت زیر خواهد شد: void execute(){ if(this-»contain("/x") || this-»contain("/x")){ file::move(this-»argv[1],this-»argv[2]); } else file::copy(this-»argv[1],this-»argv[2]); } حالا که موفق شدیم کلاس مربوط به copy را پیاده کنیم، به بررسی کلاس دیگری می پردازیم. این کلاس برای ایجاد رابطه با کاربر مورد استفاده قرار می گیرد، نام این کلاس را helper می گذاریم، این کلاس قرار است دستوراتی را که کاربر وارد می کند، اعتبارسنجی کند و با توجه به دستورات وارد شده، عملیات مناسب را اجرا کند. این کلاس بصورت زیر تعریف شده است : class utility{ public : utility(char* command); utility(); void run(); private : char* command; char** argv; int argc; basecommand* internalecommand; void parse(); void createcommand(); {; این کلاس شامل 3 فیلد است یکی argv ودیگری argc که قبلا درمورد آنها و کاربردشان صحبت کرده ایم. دیگری یک شی از basecommand. همانطور که گفتیم کلاس basecommand کلاس پدر همه کلاس های مربوط به دستورات است و مقدار آن می تواند تمامی دستورات را قبول کند، متد run این کلاس در واقع دستوری که کاربر وارد کرده است، را تجزیه و تحلیل می کند و فرمان مربوطه را اجرا می کند. در این متد ابتدا عبارت وارد شده توسط متد parse تجزیه و تحلیل می شود و فیلدهای argv و argc مقدار دهی می شوند، و سپس متد createcommand اجرا می شود و بر اساس مقدار argv فیلد internalcommand مقدار دهی می شود و سپس متدexecute از کلاس basecomman اجرا می شود. با این کار دستور مورد نظر انجام شده و خروجی ها چاپ می شود، تا اینجا ما موفق شدیم دستوری را وارد و آن را اجرا کنیم. حال بگذارید شرایطی را بررسی کنیم که ما بخواهیم دستورات را پست سر هم وارد کنیم و اینکار تا آنجا ادامه پیدا کند که کاربر دستور exit را وارد کند و از برنامه خارج شود (یعنی یک محیط خط فرمان برای کاربر ایجاد کنیم)، وظیفه این کار بر عهده متد main یا متد اجرایی برنامه است که به این صورت پیاده سازی شده است:با این پیاده سازی، یک محیط خوب برای برنامه خود دارید که می توانید در آن دستورات مختلف را پیاده کنید. در این مقاله، دستورات اجرایی، همان دستورات سیستم عامل ویندوز بود. آیا می توانید توابع و کلاس های داخلی سیستم خود را با استفاده از این روش، راه اندازی و اجرا کنید. موفق باشید. 

چهار راه برای رسیدن به آرامش:
1.نگاه کردن به عقب و تشکر از خدا  2.نگاه کردن به جلو و اعتماد به خدا  3.نگاه کردن به اطراف و خدمت به خدا  4.نگاه کردن به درون و پیدا کردن خدا

پل ارتباطی : samsamdragon@gmail.com

تالارهای تحت مدیریت :

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

 

چهارشنبه 13 آبان 1388  3:51 PM
تشکرات از این پست
دسترسی سریع به انجمن ها