زبان برنامه نویسی سی/دستور goto: تفاوت میان نسخه‌ها

محتوای حذف‌شده محتوای افزوده‌شده
بدون خلاصۀ ویرایش
بدون خلاصۀ ویرایش
خط ۳:
==دستور بروبه goto==
 
دستور « برو به ... » که به انگلیسی می‌شود « ... go to » و با کلیدواژه goto نوشته می‌شود روند اجرای برنامه را از جایی که کلیدواژه نوشته شود به بخش دیگری از برنامه که با برچسب « label » مشخص شده است انتقال می‌دهد . هر برچسب دارای یک نام یا شناسه است که همانند نام یا همان شناسه متغیرها می‌باشد و باید اختصاصی و انحصاری باشد . یعنی شما نمی‌توانید دو برچسب را با یک نام بنویسید یا نام برچسب را نام ( یا همان شناسه ) یک متغیر انتخاب کنید . نحوه نوشتن یک برچسب ( label ) بدین شکل است :
 
 
خط ۲۳:
در اینجا result یک برچسب است با شناسه و نام result که اگر بنویسید ;goto result روند اجرای برنامه به برچسب result می‌رود و خط‌به‌خط از آنجا به بعد ادامه یافته و کدها اجرا می‌شوند . برچسب می‌تواند پس از goto یا قبل از goto نوشته شده باشد .
 
کاربردیکی gotoاز عموماًکاربردهای goto برای خروج از حلقهحلقه‌های تو در تو می‌باشد ؛ مثلاً فرض کنید شما یک برنامه‌ای می‌نویسید که مبتنی بر هوش مصنوعی است و در هنگام نوشتن هوش مصنوعی ( مثل پروژه CGI ) مجبورید از حلقه‌های خیلی زیادی که تو در تو نیز هستند استفاده کنید ؛ مثلاً فرض کنید ۸ حلقه تو در جالتو اجرادر دارید که اگر شرط خاصی برقرار بود باید تمام حلقه‌ها بشکنند و از تکرار استآنها کهجلوگیری شود ؛ اگر شرطیبخواهید از روش متداول شکستن حلقه‌ها استفاده کنید باید یک به یک در حلقه‌ها شرط خود را بنویسید که اگر برقرار شدبود با دستور break حلقه ، برنامهشکسته شود ؛ پس شما ۸ بار باید کد تکراری را بزنید در حالی که با نوشتن یک برچسب بیرون از هر ۸ حلقه خارجو شودنوشتن یک goto داخل حلقه مورد نظر و داخلی اجرای تمام حلقه‌ها را متوقف کنید و روند اجرای برنامه به بیرون از حلقهحلقه‌ها و ادامه برنامه برودمی‌رود . از goto برای ایجاد یک حلقه نیز استفاده می‌شود . مثلاً یک برچسب را می‌نویسید و سپس شرطی را می‌نویسید ؛ که متغیر شرط در خط بعدی یا خطوط بعدی تغییر می‌کند و در انتهای آن از دستور goto برای ارجاع به برچسب استفاده می‌کنید که کامپایلر باز می‌گردد به خطوط قبلی و آنها را اجرا می‌کند و سپس دوباره به goto می‌رسد پس دوباره باز می‌گردد به خطوط و کدهای قبلی و آنها را اجرا می‌کند و این در حالیست که در هر بار اجرا متغیر شرط به برقرار نبودن نزدیک می‌شود تا جایی که در نهایت برقرار نیست و بنابراین goto نیز اجرا نمی‌شود و ادامه برنامه دنبال می‌شود . این روش مانند ساخت یک حلقه است '''اما به هیچ وجه توصیه نمی‌شود''' . شما می‌توانید از goto برای ایجاد اتصال میان بخش‌های مختلف کدها نیز استفاده کنید ؛ اما این نیز توصیه نمی‌شود چرا که برنامه شما را ناخوانا و پیچ در پیچ می‌کند ( حتی ممکن است خود شما نیز به اشتباه بیافتید که در نهایت برنامه خروجی ، نتیجه مطلوب را نخواهد داشت ) مثلاً فرض کنید شما چند حلقه و دستورها و عملگرهای مختلفی داخل تابع خود دارید و با کمک دستورهای شرطی و دستور goto ، مرتب برنامه را از این قسمت به آن قسمت و از آن قسمت به این قسمت ، پاس کاری می‌کنید ولی این کار درک برنامه را مشکل می‌کند و تقریباً هیچ برنامه‌نویس حرفه‌ای و استادی چنین کد زدنی را به برنامه‌نویسان توصیه نمی‌کند . احیاناً اگر قصد چنین کاری را نیز دارید باید حتماً سورس کامپایلر خود را ( در صورت متن باز بودن Open Source بودن ) بخوانید تا بدانید کامپایلر به چه شکل کدهای goto را ترجمه می‌کند
 
در مجموع سعی کنید بهتا ندرتزمانی ازکه gotoنیازی استفاده کنید ، آن هم فقط برای خروجنیست از حلقهgoto دراستفاده صورتینکنید که. نمی‌خواهید با break آن را بشکنید .دقت کنید که از goto تنها داخل بدنه تابع می‌توان استفاده نمود و به هر جای تابع که برچسبی داشته باشد ، دسترسی دارد و به آنجا می‌پرد ( jump ) یعنی از یک قسمت از برنامه که دارد اجرا می‌شود به قسمت دیگری از برنامه می‌رود ( که مسلماً به واسطه ;goto label-identifier اتفاق میافتد ) اما '''دقت کنید''' که goto نمی‌تواند از داخل یک تابع به داخل تابع دیگری برود ؛ یعنی هر برچسب ، محلی می‌باشد و داخل تابع خود معنا و امکان حضور می‌یابد
 
مثال برای ایجاد یک حلقه :
خط ۴۱:
i++;
if(i<10)
{
goto label;
}
 
return 0;
سطر ۵۰ ⟵ ۴۸:
{{پایان چپ‌چین}}
 
در مثال بالا بعد از ضمیمه نمودن فایل سرآیند stdio جهت استفاده از تابع کتابخانه‌ای printf ( که داخل آن تعریف شده است ؛ تابع اصلی برنامه را ( یعنی تابع main را ) تعریف نموده‌ایم که متغیری با نام i در آن با مقدار 0 تعریف شده است . سپس یک برچسب با نام label تعریف کرده‌ایم که در خط بعدی مقدار i را به همراه شکستن خط در خروجی خط‌دستوری چاپ می‌کند . سپس i به کمک عملگر افزایش یک واحد افزایش می‌یابد . در خط بعدی اگر i کوچک‌تر از 10 باشد بلوک خود را اجرا می‌کند که یک دستور goto را شاملبه می‌شوداجرا می‌گذارد که ادامه اجرای برنامه را به چند خط ، قبل‌تر ، یعنی برچسب label باز می‌گرداند . پس حالا مقدار i که 2 شده است چاپ می‌شود و سپس یک واحد دیگر افزایش می‌یابد و برنامه مرتب تا زمانی که i کوچک‌تر از 10 باشد همین روال را ادامه می‌دهد ، اما زمانی که i به مقدار 10 می‌رسد ؛ دیگر شرط if ما برقرار نخواهد بود و از این روی دیگر برنامه به چند خط قبل‌تر نمی‌رود و به بیرون از بلوکدستور if که می‌شود ادامه برنامه خواهد رفت و که حکم و دستور دیگری وجود ندارد مگر دستور return که مقدار 0 را باز می‌گرداند و برنامه ما به پایان می‌رسد
 
'''دقت کنید :''' ما با قطعه کد بالا ، یک حلقه ساختیم ، اما این حلقه توسط کامپایلر به یک حلقه که یک instruction پردازشگر ( CPU ) که سرعت بسیار بالایی در تکرار دارد ، ترجمه نمی‌شود . بنابراین برنامه ، درست مثل این اجرا می‌شود که شما ۱۰ بار حکم چاپ اعداد و شکستن خط را نوشته و در نهایت اجرا کنید . سرعت این شبه‌حلفه بسیار کم‌تر از حلقه‌ای است که توسط دستورهایی مثل for یا while می‌نویسید و توسط کامپایلر به کدهای سیستم‌عامل و یا ماشین ترجمه می‌شوند ( مخصوصاً اگر قصد ایجاد حلقه‌های تو در تویی داشته باشید که مخاسبات سنگینی را انجام دهند و داده‌های حلقه‌ها - معمولاً شرط‌ها - را ارزیابی نمایند )
 
'''استفاده دیگر عمومی goto'''
 
دستور goto در زبان C و خانواده آن و تمام زبان‌هایی که از زبان C الگو گرفته‌اند وجود دارد . اما بسیاری از زبان‌های خیلی سطح بالا امکاناتی دارند که نیاز به استفاده از goto را از میان بر می‌دارند . ولی استفاده goto فقط محدود به خارج شدن از حلقه‌های تو در تو نیست ؛ بلکه جلوی کد نویسی اضافه و اشغال حجم زیاد فایل برنامه را به نحو دیگری همانند خروج از حلقه‌ها می‌گیرد . برای یک مثال ملموس مجبوریم کمی به مباحث نرم‌افزاری بپردازیم . در دنیای نرم‌افزار فرمت‌ها ( Format ) ی مختلفی برای تصاویر رستر ( Raster ) که بر اساس پیکسل تعریف می‌شوند و یا تصاویر وکتور ( Vector ) که با خطوط و اشکال تعریف می‌شوند ، فرمت‌های مالتی مدیا ( چند رسانه‌ای ) مثل فرمت‌های صوتی MP2 یا MP3 یا FLAC یا AIFF یا AC3 یا AAC و یا فرمت‌های ویدئویی MPEG4 و یا ماتروسکا که پسوند mkv ذخیره می‌شود وجود دارند که شما در نوشتن برنامه‌های خود به خواندن و نوشتن آنها احتیاج دارید . اصلاً گاهی ممکن است خودتان بخواهید یک فرمت مخصوص به خود را تعریف کنید ( برای برنامه‌های تجاری ، حسابداری و ... ) این فایل‌ها که هر کدام فرمت خاص خود را دارند یک هدر دارند که به عنوان شناسه آن فرمت مطرح می‌شوند . مثلاً فایل‌های بیت‌مپ ( Bitmap ) که با پسوند bmp در ویندوز وجود دارند توسط مایکروسافت ابداع شده است و هدر ( Header ) آن BM می‌باشد . یعنی بایت اول آن ، کاراکتر B و بایت دوم آن کاراکتر M است . حال فرض کنید شما می‌خواهید یک برنامه Raster Image Editor مثل فتوشاپ ( Adobe Photoshop ) یا پینت‌شاپ پرو ( Corel PaintShop Pro ) یا گیمپ GIMP بنویسید . نه وظیفه شما است و نه در حوصله شما که اگر فایلی که کاربر می‌خواهد باز کند ناخوانا باشد را تعمیر و یا احیا کند ( Repair و یا Recovery ) به این گونه فایل‌ها که به هر دلیلی آسیب دیده‌اند و خوانا نیستند فایل‌های خراب ( فاسد یا Corrupted ) گفته می‌شود . بنابراین شما در برنامه خود تعریف می‌کنید تا اگر کاربر فایل مورد حمایت شما را باز کرد اما خوانا نبود پیغام بدهد Your File Is Corrupted یعنی فایل شما خراب ( فاسد ) است . به انواع و اقسام ممکن است فایل ایراد داشته باشد و شما در کدنویسی اگر بخواهید از اتلاف وقت وقت و کد زدن جلوگیری کنید در تابع خود در پایان آن یک برچسب می‌سازید و می‌نویسید Your File Is Corrupted و پس از شروع به خواندن فایل با شروط مختلف هر جا چیزی جز استاندارد وجود داشت با دستور goto ادامه برنامه را به یک برچسب ارجاع می‌دهید که پیغام خطا می‌دهد که فایل شما فاسد است . و دیگر نیازی ندارید مرتب کد بزنید که پیغام خطا چاپ شود که فایل شما فاسد است . یک بار آن را در یک برچسب می‌نویسید و با شروط ، در کتابخانه و یا Codec خود که فرمت یا فرمت‌های مورد نظر شما را می‌خواند و می‌نویسد کد می‌زنید تا فایل را بخواند و مثلاً نمایش دهد یا در صورت ناخوانا بودن با هر دلیل فقط یک پیغام چاپ کند که فایل شما فاسد است
 
[[رده:زبان برنامه نویسی سی]]