এটি কি সি-তে গোটো ব্যবহারের উপযুক্ত?


59

আমি এটি জিজ্ঞাসা করতে সত্যই দ্বিধা বোধ করছি, কারণ আমি "বিতর্ক, যুক্তি, পোলিং বা প্রসারিত আলোচনার জন্য চাই" না তবে আমি সি তে নতুন এবং ভাষায় ব্যবহৃত সাধারণ নিদর্শনগুলির সম্পর্কে আরও অন্তর্দৃষ্টি পেতে চাই।

gotoকমান্ডটির জন্য আমি সম্প্রতি কিছুটা বিরক্তি শুনেছি , তবে আমি সম্প্রতি এটির জন্য একটি শালীন ব্যবহারের সন্ধানও পেয়েছি।

এর মতো কোড:

error = function_that_could_fail_1();
if (!error) {
    error = function_that_could_fail_2();
    if (!error) {
        error = function_that_could_fail_3();
        ...to the n-th tab level!
    } else {
        // deal with error, clean up, and return error code
    }
} else {
    // deal with error, clean up, and return error code
}

ক্লিন-আপ অংশটি যদি খুব মিলে যায় তবে এইভাবে কিছুটা সুন্দরভাবে লেখা যেতে পারে (আমার অভিমত?):

error = function_that_could_fail_1();
if(error) {
    goto cleanup;
}
error = function_that_could_fail_2();
if(error) {
    goto cleanup;
}
error = function_that_could_fail_3();
if(error) {
    goto cleanup;
}
...
cleanup:
// deal with error if it exists, clean up
// return error code

এটি কি gotoসি -এর সাধারণ বা গ্রহণযোগ্য ব্যবহারের ক্ষেত্রে ? এটি করার কোনও আলাদা / আরও ভাল উপায় আছে কি?



2
চিনির প্রলেপের তুলনায় সংকলকটি ক্লিনআপ এবং ত্রুটি যাচাইয়ের গ্যারান্টি দেয়, তবে সিতে আপনাকে অবশ্যই এটি করতে হবে ডিআরওয়াই লঙ্ঘন করে এবং গ্যারান্টি দিয়েছিল যে কোনও কোনও জায়গায় আপনি ত্রুটি কোডটি পরীক্ষা করতে খুব অলস ছিলেন বা ভুল লেবেল বা এর মতো কিছুতে গিয়েছিলেন।
ডেডএমজি

3
@ ইজকাটা: না, পয়েন্টটি হ'ল ফাংশনগুলি (ধ্বংসকারীদের মতো) যা কোনও সংযোজন নিক্ষেপ করার পরে সংকলক দ্বারা সুস্পষ্টভাবে ডাকা হয়।
ডেডএমজি

6
@ ডেডএমজি: অন্য ভাষা ব্যবহার করা সর্বদা বিকল্প নয়।
বেনিয়ামিন ক্লোস্টার

13
আমি উপযুক্ত ট্যাগ নামকরণ সঙ্গে মনে হয়, উদাহরণস্বরূপ বেশ শালীন চেহারা হতে পারে:goto hell;
মশা

উত্তর:


48

gotoবিবৃতি (এবং তার সংশ্লিষ্ট লেবেল) একটি প্রবাহ নিয়ন্ত্রণ হয় আদিম (ক বিবৃতির শর্তসাপেক্ষ মৃত্যুদন্ড সহ)। তার দ্বারা, আমি বলতে চাইছি যে তারা আপনাকে প্রোগ্রাম প্রবাহ নিয়ন্ত্রণ নেটওয়ার্ক তৈরি করার অনুমতি দেওয়ার জন্য রয়েছে। আপনি এগুলি ফ্লোচার্টের নোডের মধ্যে তীরগুলি মডেলিং হিসাবে ভাবতে পারেন।

এর কয়েকটি অবিলম্বে অপ্টিমাইজ করা যায়, যেখানে সরাসরি লিনিয়ার প্রবাহ থাকে (আপনি কেবলমাত্র মৌলিক বক্তব্যের ক্রম ব্যবহার করেন)। অন্যান্য নিদর্শনগুলি স্ট্রাকচার্ড প্রোগ্রামিং কনস্ট্রাক্টগুলির সাথে সেরা প্রতিস্থাপন করা হয় যেখানে এগুলি উপলব্ধ; যদি এটি একটি মত দেখায় whileলুপ, একটি ব্যবহার whileলুপ , ঠিক আছে? স্ট্রাকচার্ড প্রোগ্রামিং প্যাটার্নগুলি অবশ্যই বিবৃতিতে জগাখিচির চেয়ে কমপক্ষে সম্ভাব্য উদ্দেশ্য সম্পর্কে পরিষ্কারভাবে রয়েছে goto

তবুও সি সমস্ত সম্ভাব্য স্ট্রাকচার্ড প্রোগ্রামিং কনস্ট্রাক্টস অন্তর্ভুক্ত করে না। (এটি আমার কাছে স্পষ্ট নয় যে সমস্ত প্রাসঙ্গিক এখনও আবিষ্কার হয়েছে; আবিষ্কারের হার এখন ধীর, তবে আমি এই বলে যে সমস্ত কিছু পাওয়া গেছে তা দ্বিধা করতে দ্বিধা করতে দ্বিধা করব)) আমরা যাদের সম্পর্কে জানি, তার মধ্যে অবশ্যই সি এর অভাব রয়েছে try/ catch/ finallyকাঠামো (এবং ব্যতিক্রমগুলিও)। breakএটিতে বহু-স্তরের -থেকে-লুপেরও অভাব রয়েছে । এগুলি এমন ধরণের জিনিস যা একটি gotoপ্রয়োগ করতে ব্যবহার করা যেতে পারে। এটি করার জন্য অন্যান্য স্কিমগুলি ব্যবহার করাও সম্ভব - আমরা জানি যে সি এর যথেষ্ট পরিমাণে অ-gotoআদিম - তবে এগুলিতে প্রায়শই পতাকা চলক এবং আরও অনেক জটিল লুপ বা প্রহরী শর্ত তৈরি করা জড়িত; ডেটা বিশ্লেষণের সাথে নিয়ন্ত্রণ বিশ্লেষণের জড়িয়ে পড়া প্রোগ্রামটিকে সামগ্রিকভাবে বোঝা আরও শক্ত করে তোলে। এটি সংকলকটির জন্য অনুকূলকরণ করা এবং সিপিইউর দ্রুত সম্পাদন করা আরও জটিল করে তোলে (বেশিরভাগ প্রবাহ নিয়ন্ত্রণের নির্মাণ - এবং অবশ্যই goto - খুব সস্তা)।

সুতরাং, যখন gotoনা আপনার প্রয়োজন ব্যতীত ব্যবহার করা উচিত নয় , আপনার সচেতন হওয়া উচিত যে এটি বিদ্যমান এবং এটি প্রয়োজন হতে পারে, এবং আপনার যদি এটি প্রয়োজন হয় তবে আপনার খুব খারাপ লাগবে না। যে ক্ষেত্রে এটির প্রয়োজন হয় তার উদাহরণ হ'ল সংস্থান ফাংশন যখন কোনও কল করা ফাংশন ত্রুটির শর্ত দেয়। (এটি, try/ finally।) এটি ছাড়া এটি লেখা সম্ভব যে এটি gotoনা করেই এর নিজস্ব ডাউনসাইড থাকতে পারে যেমন এটি বজায় রাখার সমস্যা। মামলার উদাহরণ:

int frobnicateTheThings() {
    char *workingBuffer = malloc(...);
    int i;

    for (i=0 ; i<numberOfThings ; i++) {
        if (giveMeThing(i, workingBuffer) != OK)
            goto error;
        if (processThing(workingBuffer) != OK)
            goto error;
        if (dispatchThing(i, workingBuffer) != OK)
            goto error;
    }

    free(workingBuffer);
    return OK;

  error:
    free(workingBuffer);
    return OOPS;
}

কোডটি আরও ছোট হতে পারে তবে পয়েন্টটি প্রদর্শন করার জন্য এটি যথেষ্ট।


4
+1: সি তে প্রযুক্তিগতভাবে কখনই "প্রয়োজন হয় না" - এটি করার সবসময় একটি উপায় থাকে, এটি অগোছালো হয়ে যায় .....
মিজরা

1
আপনি কি স্পেসেটি কোডটি ব্যবহার করছেন এমন রূপের অনুরূপ, আরও বেশি বিস্তৃত (যেমন এটি একাধিক ফাংশন / মডিউল জুড়ে ছড়িয়ে যেতে try/catch/finallyপারে goto) সত্ত্বেও পছন্দ করতে চান try/catch/finally?
অটিস্টিক

65

হ্যাঁ.

এটি ব্যবহৃত হয়, উদাহরণস্বরূপ, লিনাক্স কার্নেল। এখানে প্রায় এক দশক আগে একটি থ্রেডের শেষে থেকে একটি ইমেল এসেছে , আমার গা bold় করে:

থেকে: রবার্ট প্রেমের
বিষয়: পুন: 2.6.0-পরীক্ষা * এর কোনও সুযোগ আছে?
তারিখ: 12 জানু 2003 17:58:06 -0500 রোববার

, 2003-01-12 17:22 এ রব উইলকেন্স লিখেছেন:

আমি বলি "দয়া করে গোটো ব্যবহার করবেন না" এবং পরিবর্তে একটি "ক্লিনআপ_লক" ফাংশন করুন এবং সমস্ত রিটার্নের বিবৃতি দেওয়ার আগে এটি যুক্ত করুন .. এটি বোঝা হওয়া উচিত নয়। হ্যাঁ, এটি বিকাশকারীকে একটু বেশি কঠোর পরিশ্রম করতে বলছে, তবে শেষ ফলাফলটি আরও ভাল কোড।

না, এটি স্থূল এবং এটি কার্নেলটি ফুটিয়ে তোলে । এটি এন ত্রুটিযুক্ত পথগুলির জন্য একগুচ্ছ জাঙ্ক ইনলাইন করে, শেষদিকে একবার প্রস্থান কোড রাখার বিপরীতে। ক্যাশে পায়ের ছাপ কী এবং আপনি এটি খুন করেছেন।

না পড়া সহজ।

চূড়ান্ত যুক্তি হিসাবে এটি আমাদের স্বাভাবিক স্ট্যাক-এষ্কো বাতাস পরিষ্কার করতে দেয় না এবং আনইন্ডাইন্ড , অর্থাৎ ie

        do A
        if (error)
            goto out_a;
        do B
        if (error)
            goto out_b;
        do C
        if (error)
            goto out_c;
        goto out;
        out_c:
        undo C
        out_b:
        undo B:
        out_a:
        undo A
        out:
        return ret;

এখন এই বন্ধ করুন।

রবার্ট লাভ

এটি বলেছে, একবার গোটো ব্যবহারে অভ্যস্ত হয়ে ওঠার পরে নিজেকে স্প্যাগেটি কোড তৈরি করা থেকে বিরত রাখার জন্য অনেক শৃঙ্খলার প্রয়োজন, সুতরাং আপনি যদি এমন কিছু লেখেন না যেখানে গতি এবং একটি কম মেমরির পদচিহ্নের প্রয়োজন হয় (কার্নেল বা এমবেডেড সিস্টেমের মতো) আপনার সত্যই উচিত আপনি প্রথম গোটো লেখার আগে এটি সম্পর্কে চিন্তা করুন ।


21
নোট করুন যে কার্নেলটি কাঁচা গতি বনাম পঠনযোগ্যতার উপর অগ্রাধিকার সম্পর্কিত নন-কার্নেল প্রোগ্রাম থেকে আলাদা। অন্য কথায়, তারা ইতিমধ্যে প্রোফাইল করেছে এবং তারা খুঁজে পেয়েছে যে গোটো সহ গতির জন্য তাদের কোডটি অপ্টিমাইজ করতে হবে।

11
স্ট্যাক আন-উইন্ড ব্যবহার করে স্ট্যাকের দিকে ধাক্কা না দিয়েই ত্রুটিটি সাফ করতে হ্যান্ডেল করতে! এটি গোটোর দুর্দান্ত ব্যবহার।
মাইকে 30

1
@ ব্যবহারকারী 1249, আবর্জনা, আপনি every লাইব্রেরি, কার্নেল} কোডের একটি অংশ ব্যবহার করে এমন প্রতিটি অতীত, বিদ্যমান, ভবিষ্যত} অ্যাপ্লিকেশনটিকে প্রোফাইল করতে পারবেন না। আপনার কেবল দ্রুত হওয়া দরকার।
পেসারিয়ার

1
আনলেটেড: আমি আশ্চর্য হয়েছি যে কীভাবে লোকেরা মেলিং তালিকাগুলি কোনও কাজ করতে ব্যবহার করতে পারে, এত বড় প্রকল্পগুলি ছেড়ে দেওয়া হোক। এটা ঠিক তাই ... আদিম। লোকেরা কীভাবে বার্তাগুলির ফায়ার হাউস নিয়ে আসে ?!
আলেকজান্ডার

2
আমি সংযম নিয়ে তেমন উদ্বিগ্ন নই। কেউ যদি ইন্টারনেটে কোনও গাধা দ্বারা সরিয়ে ফেলার মতো যথেষ্ট নরম হয় তবে আপনার প্রকল্পটি তাদের ছাড়া সম্ভবত ভাল better আগত বার্তাগুলির ব্যারেজটি ধরে রাখার অযৌক্তিকতা সম্পর্কে আমি আরও উদ্বিগ্ন এবং উদাহরণস্বরূপ, কীভাবে আপনি সম্ভবত প্রাকৃতিক পিছনে-আলোচনার সাথে এতটা ছোট সরঞ্জামের সাহায্যে আলোচনা করতে পারেন quot
আলেকজান্ডার

14

আমার মতে, আপনার পোস্ট করা কোডটি বৈধ ব্যবহারের উদাহরণ goto, কারণ আপনি কেবল নীচের দিকে ঝাঁপিয়ে পড়ে থাকেন এবং কেবল এটিকে আদিম ব্যতিক্রম হ্যান্ডলারের মতো ব্যবহার করেন।

তবে , পুরানো গোষ্ঠী বিতর্কের কারণে প্রোগ্রামাররা gotoপ্রায় 40 বছর ধরে এড়ানো চলেছে এবং তাই সেগুলি গোটো সহ কোড পড়তে ব্যবহার করা হয় না। গোটো এড়ানোর জন্য এটি একটি বৈধ কারণ: এটি কেবল আদর্শ নয়।

আমি সি প্রোগ্রামারদের দ্বারা আরও সহজে কিছু পড়ার মতো কোডটি আবার লিখে ফেলতাম:

Error some_func (void)
{
  Error error;
  type_t* resource = malloc(...);

  error = some_other_func (resource);

  free (resource);

  /* error handling can be placed here, or it can be returned to the caller */

  return error;
}


Error some_other_func (type_t* resource)  // inline if needed
{
  error = function_that_could_fail_1();
  if(error)
  {
    return error;
  }

  /* ... */

  error = function_that_could_fail_2();
  if(error)
  {
    return error;
  }

  /* ... */

  return ok;
}

এই নকশার সুবিধা:

  • প্রকৃত কাজটি করে ফাংশনটি সেই বিষয়গুলির সাথে নিজেকে উদ্বিগ্ন করার প্রয়োজন হয় না যা এর অ্যালগরিদমের সাথে সম্পর্কিত নয় যেমন ডেটা বন্টন করে।
  • কোডটি সি প্রোগ্রামারদের কাছে কম ভিনগ্রহী দেখায়, যেহেতু তারা গোটো এবং লেবেলগুলির ভয় পায়।
  • অ্যালগরিদম করে ফাংশনের বাইরে আপনি একই স্থানে ত্রুটি পরিচালনা ও বিলোপকে কেন্দ্রিয় করতে পারেন। কোনও ফাংশনের নিজস্ব ফলাফলগুলি পরিচালনা করার জন্য এটি বোধগম্য নয়।

11

এর বৈধ ব্যবহারের ক্ষেত্রে বর্ণিত একটি বিখ্যাত কাগজ ছিল ডোনাল্ড ই নুথ (স্ট্যানফোর্ড বিশ্ববিদ্যালয়) দ্বারা GOTO বিবৃতি সহ স্ট্রাকচার্ড প্রোগ্রামিং । কাগজগুলি সেই দিনগুলিতে প্রকাশিত হয়েছিল যেখানে GOTO ব্যবহার করা কারও কারও দ্বারা পাপ হিসাবে বিবেচিত হত এবং যখন স্ট্রাকচার্ড প্রোগ্রামিংয়ের আন্দোলন চূড়ান্ত ছিল। আপনি GoTo বিবেচিত ক্ষতিকারক দিকে একবার নজর রাখতে পারেন


9

জাভাতে আপনি এটি এটি করতে চাই:

makeCalls:  {
    error = function_that_could_fail_1();
    if (error) {
        break makeCalls;
    }
    error = function_that_could_fail_2();
    if (error) {
        break makeCalls;
    }
    error = function_that_could_fail_3();
    if (error) {
        break makeCalls;
    }
    ...
    return 0;  // No error code.
}
// deal with error if it exists, clean up
// return error code

আমি এই অনেক ব্যবহার। আমি যতটা অপছন্দ করি goto, বেশিরভাগ সি-স্টাইলের ভাষায় আমি আপনার কোড ব্যবহার করি; এটি করার অন্য কোনও ভাল উপায় নেই। (নেস্টেড লুপগুলির বাইরে ঝাঁপ দেওয়া একই রকম ঘটনা; জাভাতে আমি লেবেলযুক্ত breakএবং অন্য কোথাও আমি ব্যবহার করি goto))


3
ওহ এটি একটি ঝরঝরে নিয়ন্ত্রণ কাঠামো।
ব্রায়ান বোয়েচার 16

4
এটি সত্যিই আকর্ষণীয়। আমি সাধারণত জাভাতে এর জন্য চেষ্টা / ধরা / শেষ অবধি কাঠামোটি ব্যবহার করার কথা ভাবি (ভাঙার পরিবর্তে ব্যতিক্রম ছোঁড়া)।
রবজ

5
এটি সত্যিই অপঠনযোগ্য (কমপক্ষে আমার জন্য)। যদি উপস্থিত থাকে তবে ব্যতিক্রমগুলি আরও ভাল।
m3th0dman

1
@ m3th0dman এই বিশেষ উদাহরণে (ত্রুটি পরিচালনা করা) আমি আপনার সাথে একমত। তবে অন্যান্য (ব্যতিক্রমী) ক্ষেত্রেও এই আইডিয়াটি কার্যকর হতে পারে।
কনরাড রুডলফ

1
ব্যতিক্রম ব্যয়বহুল, তাদের একটি ত্রুটি, স্ট্যাকট্রেস এবং আরও অনেক জাঙ্ক জেনারেট করা দরকার। এই লেবেল বিরতি একটি চেকিং লুপ থেকে একটি পরিষ্কার প্রস্থান দেয়। যদি না কেউ স্মৃতি এবং গতির বিষয়ে চিন্তা না করে তবে সবার জন্য আমি ব্যতিক্রম ব্যবহার করি।
স্যাচল্লাকা

8

আমার মনে হয় এটা হল একটি শালীন ব্যবহারের ক্ষেত্রে কিন্তু পাছে "ত্রুটি" একটি বুলিয়ান মান ছাড়া আর কিছুই না থাকে, তখন অন্যভাবে উদ্যাপন করা কি আপনি চান হল:

error = function_that_could_fail_1();
error = error || function_that_could_fail_2();
error = error || function_that_could_fail_3();
if(error)
{
     // do cleanup
}

এটি বুলিয়ান অপারেটরগুলির শর্ট সার্কিট মূল্যায়নের ব্যবহার করে। যদি এটি "আরও ভাল" হয় তবে এটি আপনার ব্যক্তিগত স্বাদ এবং আপনি কীভাবে সেই প্রতিমাটির অভ্যস্ত হন to


1
errorএটির সাথে সমস্যাটি হ'ল এর মান সমস্ত ওআর'এর সাথে অর্থহীন হয়ে উঠতে পারে।
জেমস

@ জেমস: আপনার মন্তব্যের কারণে আমার উত্তর সম্পাদনা করেছেন
ডক ব্রাউন

1
এটি যথেষ্ট নয়। প্রথম ফাংশনের সময় যদি ত্রুটি ঘটে থাকে তবে আমি দ্বিতীয় বা তৃতীয় ফাংশনটি সম্পাদন করতে চাই না।
রবজ

2
শর্ট হ্যান্ড মূল্যায়নের সাথে যদি আপনি শর্ট সার্কিট মূল্যায়ন বোঝায় , লজিক্যাল ওআর পরিবর্তে বিটওয়াইজ বা এর ব্যবহারের কারণে এখানে এটি ঘটেছিল ঠিক এটি নয়।
ক্রিস

1
@ ক্রিশ্চিয়ানআউ: ধন্যবাদ, সেই অনুসারে আমার উত্তরটি সম্পাদনা করেছেন
ডক ব্রাউন

6

লিনাক্স শৈলী গাইড আপনার ব্যবহারের নির্দিষ্ট কারণগুলি দেয় gotoযা আপনার উদাহরণের সাথে সঙ্গতিপূর্ণ:

https://www.kernel.org/doc/Documentation/process/coding-style.rst

গোটোস ব্যবহারের যুক্তিটি হ'ল:

  • নিঃশর্ত বিবৃতি বোঝা এবং অনুসরণ করা সহজ
  • বাসা কমেছে
  • পরিবর্তনগুলি রোধ করার সময় পৃথক প্রস্থান পয়েন্টগুলি আপডেট না করে ত্রুটিগুলি প্রতিরোধ করা হয়
  • অপ্রয়োজনীয় কোড দূরে অপ্টিমাইজ করতে কম্পাইলার কাজটি সংরক্ষণ করে;)

দাবি অস্বীকার আমি আমার কাজ ভাগ করে নেওয়ার কথা না। এখানে উদাহরণগুলি কিছুটা স্বীকৃত তাই ভালুক দয়া করে আমাকে সহ্য করুন।

এটি মেমরি পরিচালনার জন্য ভাল। আমি সম্প্রতি এমন কোডে কাজ করেছি যা গতিশীলভাবে মেমরি বরাদ্দ করেছিল (উদাহরণস্বরূপ char *কোনও ফাংশন দ্বারা ফেরত)। একটি ফাংশন যা কোনও পাথ দেখে এবং পথের টোকেনগুলি বিশ্লেষণ করে পথটি বৈধ কিনা তা নির্ধারণ করে:

tmp_string = strdup(string);
token = strtok(tmp_string,delim);
while( token != NULL ){
    ...
    some statements, some involving dynamically allocated memory
    ...
    if ( check_this() ){
        free(var1);
        free(var2);
        ...
        free(varN);
        return 1;
    }
    ...
    some more stuff
    ...
    if(something()){
        if ( check_that() ){
            free(var1);
            free(var2);
            ...
            free(varN);
            return 1;
        } else {
            free(var1);
            free(var2);
            ...
            free(varN);
            return 0;
        }
    }
    token = strtok(NULL,delim);
}

free(var1);
free(var2);
...
free(varN);
return 1;

এখন আমার কাছে, নীচের কোডটি যদি আপনি একটি যুক্ত করতে চান তবে বজায় রাখা আরও সুন্দর এবং সহজ varNplus1:

int retval = 1;
tmp_string = strdup(string);
token = strtok(tmp_string,delim);
while( token != NULL ){
    ...
    some statements, some involving dynamically allocated memory
    ...
    if ( check_this() ){
        retval = 1;
        goto out_free;
    }
    ...
    some more stuff
    ...
    if(something()){
        if ( check_that() ){
            retval = 1;
            goto out_free;
        } else {
            retval = 0;
            goto out_free;
        }
    }
    token = strtok(NULL,delim);
}

out_free:
free(var1);
free(var2);
...
free(varN);
return retval;

কোডটিতে এটির সাথে অন্যান্য সকল ধরণের সমস্যা ছিল, যথা এন যে কোথাও 10 এর উপরে ছিল এবং ফাংশনটি 450 লাইনের ওপরে ছিল, কিছু জায়গায় 10 টি নেস্টনেস ছিল।

তবে আমি আমার সুপারভাইজারকে এটি রিফ্যাক্টারের জন্য প্রস্তাব দিয়েছিলাম, যা আমি করেছি এবং এখন এটি সমস্ত সংক্ষিপ্ত ফাংশনগুলির একটি গুচ্ছ, এবং তাদের সকলের লিনাক্স স্টাইল রয়েছে

int function(const char * param)
{
    int retval = 1;
    char * var1 = fcn_that_returns_dynamically_allocated_string(param);
    if( var1 == NULL ){
        retval = 0;
        goto out;
    }

    if( isValid(var1) ){
         retval = some_function(var1);
         goto out_free;
    }

    if( isGood(var1) ){
         retval = 0;
         goto out_free;
    }

out_free:
    free(var1);
out:
    return retval;
}

আমরা যদি gotoএস ছাড়াই সমতুল্য বিবেচনা করি :

int function(const char * param)
{
    int retval = 1;
    char * var1 = fcn_that_returns_dynamically_allocated_string(param);
    if( var1 != NULL ){

       if( isValid(var1) ){
            retval = some_function(var1);
       } else {
          if( isGood(var1) ){
               retval = 0;
          }
       }
       free(var1);

    } else {
       retval = 0;
    }

    return retval;
}

আমার কাছে, প্রথম ক্ষেত্রে, এটি আমার কাছে স্পষ্ট যে প্রথম ফাংশনটি যদি ফিরে আসে তবে NULLআমরা এখানে চলে যাব এবং আমরা ফিরে আসছি 0। দ্বিতীয় ক্ষেত্রে, আমাকে পুরো স্ক্রিনটি রয়েছে কিনা তা দেখতে নীচে স্ক্রোল করতে হবে। মঞ্জুরিপ্রাপ্ত প্রথমটি এটি আমার কাছে স্টাইলিস্টিকভাবে (নাম " out") ইঙ্গিত করে এবং দ্বিতীয়টি সিনট্যাকটিকভাবে এটি করে। প্রথমটি এখনও আরও স্পষ্ট।

এছাড়াও, আমি free()একটি ফাংশন শেষে বিবৃতি দেওয়া খুব পছন্দ করি । এটি আংশিক কারণ কারণ, আমার অভিজ্ঞতায় free()ফাংশনগুলির মাঝামাঝি বিবৃতিগুলি খারাপ গন্ধ পায় এবং আমাকে বোঝায় যে আমার সাব্রোটিন তৈরি করা উচিত। এই ক্ষেত্রে, আমি var1আমার ফাংশনটিতে তৈরি করেছি এবং free()এটি একটি সাবরুটিনে পারিনি , তবে সে কারণেই goto out_free, গোটো আউট স্টাইলটি এত ব্যবহারিক।

আমি মনে করি প্রোগ্রামারদের এটিকে বিশ্বাস করা উচিত যে gotoএটি খারাপ। তারপরে, যখন তারা যথেষ্ট পরিপক্ক হবে, তাদের লিনাক্স উত্স কোডটি ব্রাউজ করা উচিত এবং লিনাক্স স্টাইল গাইডটি পড়া উচিত।

আমার যুক্ত করা উচিত যে আমি এই স্টাইলটি খুব ধারাবাহিকভাবে ব্যবহার করি, প্রতিটি ফাংশনের একটি ইনট retval, একটি out_freeলেবেল এবং আউট লেবেল রয়েছে। স্টাইলিস্টিক ধারাবাহিকতার কারণে, পাঠযোগ্যতা উন্নত হয়।

বোনাস: বিরতি এবং এখনও অবিরত

বলুন আপনার কিছুক্ষণ লুপ আছে

char *var1, *var2;
char line[MAX_LINE_LENGTH];
while( sscanf(line,... ){
    var1 = functionA(line,count);
    var2 = functionB(line,count);

    if( functionC(var1, var2){
         count++
         continue;
    }

    ...
    a bunch of statements
    ...

    count++;
    free(var1);
    free(var2);
}

এই কোডটিতে অন্য কিছু জিনিস ভুল রয়েছে, তবে একটি বিষয় হল চালিয়ে যাওয়া বিবৃতি। আমি পুরো জিনিসটি আবার লিখতে চাই, তবে এটি একটি ছোট উপায়ে পরিবর্তন করার দায়িত্ব আমার দেওয়া হয়েছিল। এটি আমাকে সন্তুষ্ট করে এমনভাবে রিফ্যাক্টর করতে কয়েক দিন সময় নিতে পারে তবে আসল পরিবর্তনটি ছিল প্রায় দেড় দিনের কাজ। সমস্যাটি হ'ল আমাদের ' continue' 'তবুও আমাদের মুক্ত করতে হবে var1এবং var2। আমাকে একটি যুক্ত var3করতে হয়েছিল, এবং এটি আমাকে ফ্রি () বিবৃতিটি আয়না করতে বাধ্য করে তোলে।

আমি তখন তুলনামূলকভাবে নতুন ইন্টার্ন ছিলাম, তবে আমি কিছুক্ষণ আগে মজা করার জন্য লিনাক্স সোর্স কোডটি দেখছিলাম, তাই আমি আমার সুপারভাইজারকে জিজ্ঞাসা করলাম আমি কোনও গোটো স্টেটমেন্ট ব্যবহার করতে পারি কিনা। তিনি হ্যাঁ বলেছিলেন, এবং আমি এটি করেছি:

char *var1, *var2;
char line[MAX_LINE_LENGTH];
while( sscanf(line,... ){
    var1 = functionA(line,count);
    var2 = functionB(line,count);
    var3 = newFunction(line,count);

    if( functionC(var1, var2){
         goto next;
    }

    ...
    a bunch of statements
    ...
next:
    count++;
    free(var1);
    free(var2);
}

আমি মনে করি চালিয়ে যাওয়া সর্বোত্তমভাবে ঠিক আছে তবে আমার কাছে তারা অদৃশ্য লেবেলযুক্ত গোটোর মতো। একই বিরতি জন্য যায়। আমি এখনও চালিয়ে যাওয়া বা বিরতিতে পছন্দ করব যদি না এখানে না হয়, এটি আপনাকে একাধিক জায়গায় পরিবর্তনগুলি আয়না করতে বাধ্য করে।

এবং আমার আরও যোগ করা উচিত যে এই ব্যবহার goto next;এবং next:লেবেলটি আমার কাছে অসন্তুষ্টিজনক। তারা free()'র এবং count++বিবৃতি আয়না চেয়ে নিছক ভাল ।

gotoএর প্রায় সর্বদা ভুল, তবে কখন ব্যবহার করা ভাল সেগুলি অবশ্যই জেনে রাখা উচিত।

একটি বিষয় যা আমি নিয়ে আলোচনা করি নি তা হ'ল ত্রুটি পরিচালনা করা যা অন্যান্য উত্তর দ্বারা আবৃত হয়েছে।

কর্মক্ষমতা

স্ট্র্যাটকের () http://opensource.apple.com//source/Libc/Libc-167/string.subproj/strtok.c এর বাস্তবায়নটি দেখতে পারেন

#include <stddef.h>
#include <string.h>

char *
strtok(s, delim)
    register char *s;
    register const char *delim;
{
    register char *spanp;
    register int c, sc;
    char *tok;
    static char *last;


    if (s == NULL && (s = last) == NULL)
        return (NULL);

    /*
     * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
     */
cont:
    c = *s++;
    for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
        if (c == sc)
            goto cont;
    }

    if (c == 0) {       /* no non-delimiter characters */
        last = NULL;
        return (NULL);
    }
    tok = s - 1;

    /*
     * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
     * Note that delim must have one NUL; we stop if we see that, too.
     */
    for (;;) {
        c = *s++;
        spanp = (char *)delim;
        do {
            if ((sc = *spanp++) == c) {
                if (c == 0)
                    s = NULL;
                else
                    s[-1] = 0;
                last = s;
                return (tok);
            }
        } while (sc != 0);
    }
    /* NOTREACHED */
}

আমি ভুল হলে দয়া করে আমাকে সংশোধন করুন, তবে আমি বিশ্বাস করি যে cont:লেবেল এবং goto cont;বিবৃতিটি কার্য সম্পাদনের জন্য রয়েছে (তারা অবশ্যই কোডটি আরও পঠনযোগ্য করে তোলে না)। এগুলি করে পাঠযোগ্য কোড দিয়ে প্রতিস্থাপন করা যেতে পারে

while( isDelim(*s++,delim));

সীমানা ছাড়তে। তবে যত তাড়াতাড়ি সম্ভব দ্রুত হওয়া এবং অপ্রয়োজনীয় ফাংশন কলগুলি এড়াতে, তারা এটি এভাবে করে।

আমি ডিজকস্ট্রার কাগজটি পড়েছি এবং এটি বেশ নিখুঁত বলে মনে করি।

গুগল "ডিজজস্ট্র গোটো বিবৃতি ক্ষতিকারক হিসাবে বিবেচিত" কারণ আমার 2 টির বেশি লিঙ্ক পোস্ট করার মতো খ্যাতি নেই।

আমি এটিকে গোটো ব্যবহার না করার কারণ হিসাবে উদ্ধৃত করেছি এবং এটি পড়ে আমার গোটো ব্যবহারগুলি যেভাবে গ্রহণ করা যায় তেমন কোনও পরিবর্তন হয়নি।

সংযোজন :

এই সমস্ত অবিরত এবং বিরতি সম্পর্কে চিন্তা করতে গিয়ে আমি একটি ঝরঝরে নিয়ম নিয়ে এসেছি।

  • যদি কিছুক্ষণের মধ্যে লুপ হয় তবে আপনার একটি চালিয়ে যায়, তবে সেই সময়ের লুপটির মূল অংশটি একটি ফাংশন হওয়া উচিত এবং চালিয়ে যাওয়াটি একটি রিটার্ন স্টেটমেন্ট হওয়া উচিত।
  • কিছুক্ষণের মধ্যে যদি আপনার একটি ব্রেক স্টেটমেন্ট থাকে, তবে লুপটি নিজেই একটি ফাংশন হওয়া উচিত এবং বিরতিটি একটি রিটার্ন স্টেটমেন্ট হয়ে যায়।
  • আপনার যদি উভয় থাকে তবে কিছু ভুল হতে পারে।

স্কোপ সমস্যাগুলির কারণে এটি সর্বদা সম্ভব হয় না তবে আমি খুঁজে পেয়েছি যে এটি করা আমার কোড সম্পর্কে যুক্তিযুক্ত হওয়া আরও সহজ করে তোলে। আমি লক্ষ্য করেছি যে যখনই লুপের বিরতি বা চালিয়ে যাওয়া তখন আমার খারাপ অনুভূতি জোগায়।


2
+1 তবে আমি কি একটি বিষয়ে একমত হতে পারি না? "আমি মনে করি প্রোগ্রামারদের এ কথা বিশ্বাস করে সামনে আনতে হবে যে গোটো খারাপ evil" সম্ভবত তাই, তবে আমি প্রথমে ১৯IC৫ সালে পাঠ্য সম্পাদক ছাড়া লাইন নম্বর এবং জিওটিও সহ বেসিকে প্রোগ্রামিং শিখি ten আমি দশ বছর পরে কাঠামোগত প্রোগ্রামিংয়ের মুখোমুখি হয়েছি, তারপরে আমার নিজের থেকে জিওটিও ব্যবহার বন্ধ করতে এক মাস সময় লেগেছে without কোন চাপ থামাতে। আজ, আমি বিভিন্ন কারণে বছরে কয়েকবার GOTO ব্যবহার করি, তবে এটি খুব বেশি আসে না। গোটো দুষ্ট যে বিশ্বাস করি না তা বিশ্বাস করে না এসে আমার কোনও ক্ষতি করেনি যা আমি জানি, এবং এটি কিছু ভাল কাজও করতে পারে। ঐটা শুধুই আমি.
thb

1
আমি মনে করি আপনি সে সম্পর্কে ঠিক বলেছেন। আমি এই ধারণাটি নিয়ে এসেছি যে GOTOs ব্যবহার করা উচিত নয় এবং শুদ্ধ ঘটনা দ্বারা, আমি লিনাক্স উত্স কোডটি এমন এক সময়ে ব্রাউজ করছিলাম যখন আমি এমন কোডে কাজ করছিলাম যেখানে মেমরি মুক্ত করার জন্য একাধিক প্রস্থান পয়েন্ট সহ এই ফাংশনগুলি ছিল। অন্যথায়, আমি এই কৌশলগুলি সম্পর্কে জানতাম না।
ফিলিপ কার্ফিন

1
@thb এছাড়াও, মজার গল্প, আমি আমার তত্ত্বাবধায়ককে সে সময় গোটোর ব্যবহারের অনুমতিের জন্য জিজ্ঞাসা করেছিলাম এবং আমি নিশ্চিত করেছিলাম যে আমি তাকে ব্যাখ্যা করেছিলাম যে আমি সেগুলিকে যেভাবে ব্যবহার করেছি সেভাবে একটি নির্দিষ্ট উপায়ে ব্যবহার করতে যাচ্ছি লিনাক্স কার্নেল এবং তিনি বলেছিলেন "ঠিক আছে, এটি বোধগম্য হয় এবং এটিও, আমি জানতাম না যে আপনি সিটিতে জিওটিও ব্যবহার করতে পারবেন"।
ফিলিপ কার্ফিন

1
@thb আমি জানি না তা লুপ মধ্যে এতে যান ভালো মত (লুপ ভঙ্গ পরিবর্তে) এই এক ? ঠিক আছে, এটি একটি খারাপ উদাহরণ, তবে আমি দেখতে পেয়েছি যে নুথের স্ট্রাকচার্ড প্রোগ্রামিংয়ের সাথে গোটো স্টেটমেন্ট (উদাহরণ 7 এ) সহ কুইকোর্টটি খুব বোধগম্য নয় State
ইয়েফফাহ

@ ইয়ে0 ফাহ আমি আমার বক্তব্য ব্যাখ্যা করব তবে আমার ব্যাখ্যাটি আপনার সূক্ষ্ম উদাহরণকে হ্রাস করে না! এ! আমি উদাহরণ অনুমোদিত। তবুও মনিব সোফমোরেস গোটো সম্পর্কে লোকদের বক্তৃতা দিতে পছন্দ করে। 1985 সাল থেকে গোটোর ব্যবহারিক ব্যবহার খুঁজে পাওয়া শক্ত কারণ এটি উল্লেখযোগ্য সমস্যার সৃষ্টি করে, অন্যদিকে প্রোগ্রামারটির কাজকে স্বাচ্ছন্দ্যহীন গোটোস খুঁজে পেতে পারে। যাইহোক, আধুনিক প্রোগ্রামিংয়ে খুব কমই উদ্ভূত হয়, যাইহোক, যখন এটি উত্থাপিত হয়, আমার পরামর্শ হ'ল আপনি যদি এটি ব্যবহার করতে চান তবে আপনার সম্ভবত এটি ব্যবহার করা উচিত। গোটো ঠিক আছে। গোটোর মূল সমস্যাটি হ'ল কিছু লোক বিশ্বাস করেন যে গোটোকে অবহেলা করা তাদের স্মার্ট দেখায়।
14

5

ব্যক্তিগতভাবে আমি এটিকে আরও রিফ্যাক্টর করতাম:

int DoLotsOfStuffThatCouldFail (paramstruct *params)
{
    int errcode = EC_NOERROR;

    if ((errcode = FunctionThatCouldFail1 (params)) != EC_NOERROR) return errcode;
    if ((errcode = FunctionThatCouldFail2 (params)) != EC_NOERROR) return errcode;
    if ((errcode = FunctionThatCouldFail3 (params)) != EC_NOERROR) return errcode;
    if ((errcode = FunctionThatCouldFail4 (params)) != EC_NOERROR) return errcode;

    return EC_NOERROR;
}

void DoStuff (paramstruct *params)
{
    int errcode = EC_NOERROR;

    InitStuffThatMayNeedToBeCleaned (params);

    if ((errcode = DoLotsOfStuffThatCouldFail (params)) != EC_NOERROR)
    {
         CleanupAfterError (params, errcode);
    }
}

এটি গোটোকে এড়িয়ে যাওয়ার চেয়ে গভীর বাসা বেঁধে বেশি উত্সাহিত হবে (আইএমও প্রথম কোডের নমুনার সাথে আরও খারাপ সমস্যা) এবং অবশ্যই ক্লিনআপএফটারেরর এর বাইরে সম্ভাবনার বাইরে থাকার উপর নির্ভরশীল (এই ক্ষেত্রে "প্যারামগুলি" পারে এমন কিছু কাঠামো হ'ল কিছু বরাদ্দ মেমরি যা আপনাকে মুক্ত করতে হবে, একটি ফাইল * যা আপনাকে বন্ধ করতে হবে বা যাই হোক না কেন)।

এই পদ্ধতির সাথে আমি যে বড় সুবিধাটি দেখি তা হ'ল এফটিসিএফ 2 এবং এফটিসিএফ 3 (বা একটি বিদ্যমান বর্তমান পদক্ষেপ মুছে ফেলা) এর মধ্যে অনুমানমূলক ভবিষ্যতের অতিরিক্ত পদক্ষেপ স্লট করা সহজ এবং পরিষ্কার উভয়, সুতরাং এটি রক্ষণাবেক্ষণের জন্য নিজেকে আরও ভাল ধার দেয় (এবং যে ব্যক্তি আমার কোড লিচিং না করার জন্য আমার কোডকে উত্তরাধিকার সূত্রে প্রাপ্ত!) - তবে একদিকে, নেস্টেড সংস্করণটির অভাব রয়েছে।


1
আমি আমার প্রশ্নে এটি বর্ণনা করি নি, তবে এটি সম্ভব যে এফটিসিএফগুলির একই পরামিতি না থাকায় এই প্যাটার্নটি আরও জটিল করে তোলে। ধন্যবাদ যদিও.
রবজ

3

মিশ্রা (মোটর শিল্প সফটওয়্যার রিলিবিবিলিটি অ্যাসোসিয়েশন) সি কোডিং গাইডলাইনগুলি দেখুন যা কঠোর মানদণ্ডের আওতায় যাওয়ার অনুমতি দেয় (যা আপনার উদাহরণটি পূরণ করে)

যেখানে আমি কাজ করি একই কোডটি লেখা হবে - কোনও দরকার নেই - এগুলি সম্পর্কে অযথা ধর্মীয় বিতর্ক এড়ানো যে কোনও সফ্টওয়্যার হাউসে একটি বড় প্লাস।

error = function_that_could_fail_1();
if(!error) {
  error = function_that_could_fail_2();
}
if(!error) {
  error = function_that_could_fail_3();
} 
if(!error) {
...
if (error) {
  cleanup:
} 

বা "টেনে নিয়ে যাওয়ার জন্য" - গোটোয়ের চেয়ে আরও খারাপ কিছু, তবে "নো গোতো এভার !!!" এর আশেপাশে যায় শিবির) "অবশ্যই এটি অবশ্যই ঠিক আছে, গোটো ব্যবহার করে না" ....

do {
  if (error = function_that_could_fail_1() ){
    break 
  }
  if (error = function_that_could_fail_2() ){
    break 
  }
  ....... 
} while (0) 
cleanup();
.... 

যদি ফাংশনগুলির একই পরামিতি প্রকার থাকে তবে এগুলি একটি টেবিলের মধ্যে রাখুন এবং একটি লুপ ব্যবহার করুন -


2
বর্তমান মিশ্র-সি: ২০০৪ এর দিকনির্দেশগুলি কোনও রূপে গোটো করার অনুমতি দেয় না (নিয়ম 14.4 দেখুন)। দ্রষ্টব্য যে মিস্রা কমিটি সর্বদা এ সম্পর্কে বিভ্রান্ত হয়ে পড়েছে, কোন পায়ে দাঁড়াতে হবে তা তারা জানে না। প্রথমত, তারা নিঃশর্তভাবে গোটো ব্যবহার নিষিদ্ধ করেছে, চালিয়ে যাওয়া ইত্যাদি। তবে আসন্ন মিস্রা ২০১১-এর খসড়ায় তারা আবার তাদের অনুমতি দিতে চায়। একটি সাইডনোট হিসাবে, দয়া করে নোট করুন যে মিজরা যদি বিবৃতিগুলির ভিতরে অ্যাসাইনমেন্ট নিষিদ্ধ করে থাকে তবে খুব ভাল কারণেই এটি গোটো ব্যবহারের চেয়ে অনেক বেশি বিপজ্জনক।

1
বিশ্লেষণাত্মক দৃষ্টিকোণ থেকে, একটি প্রোগ্রামে পতাকা যুক্ত করা সমস্ত পতাকা কোডের যেখানে পতাকাটির সুযোগ রয়েছে সেখানে নকল করার সমতুল্য, if(flag)একটি অনুলিপিটিতে প্রত্যেকটি "যদি" শাখা গ্রহণ করে এবং অন্য অনুলিপিতে প্রতিটি সম্পর্কিত বিবৃতি গ্রহণ করে " অন্য "। পতাকা নির্ধারণ এবং পরিষ্কার করার জন্য ক্রিয়াগুলি আসলে "গোটোস" যা কোডের এই দুটি সংস্করণের মধ্যে লাফিয়ে যায়। এমন সময়গুলি রয়েছে যখন পতাকাগুলির ব্যবহার যে কোনও বিকল্পের চেয়ে পরিষ্কার, তবে একটি gotoলক্ষ্য বাঁচাতে পতাকা যুক্ত করা ভাল বাণিজ্য বন্ধ নয়।
সুপারকেট

1

gotoবিকল্প do/while/continue/breakহ্যাকারি কম পঠনযোগ্য হলে আমিও ব্যবহার করি ।

gotoএর সুবিধা রয়েছে যে তাদের টার্গেটগুলির একটি নাম রয়েছে এবং তারা পড়তে পারে goto something;। এর চেয়ে পাঠযোগ্য হতে পারে breakবা continueযদি আপনি আসলে বাঁধন বা কিছু অব্যাহত করছি না।


4
কোনও do ... while(0)বা অন্য নির্মাণের ভিতরে যে কোনও জায়গায় যা আসল লুপ নয় তবে এটির ব্যবহার রোধ করার জন্য একটি কৃপণ চেষ্টা goto
আইবি

1
আহ, ধন্যবাদ, আমি এই বিশেষ ব্র্যান্ডটি জানতাম না "কেন কেউ এমন করবে ?!" এখনও নির্মাণ।
বেনিয়ামিন ক্লোস্টার

2
সাধারণত, যখন / চালিয়ে / বিরতি / হ্যাকারি বিরতি কেবল তখনই অপঠনযোগ্য হয়ে যায় যখন এতে থাকা মডিউলটি প্রথম স্থানে দীর্ঘ ফিক্স করে।
জন আর স্ট্রোহম

2
গোটো ব্যবহারের ন্যায়সঙ্গত হিসাবে আমি এর মধ্যে কিছুই খুঁজে পাচ্ছি না। বিরতি এবং অবিরত একটি সুস্পষ্ট পরিণতি আছে। এতে যান ... কোথায়? লেবেল কোথায়? বিরতি ফেলুন এবং পরের ধাপটি ঠিক কোথায় এবং এর কাছাকাছি রয়েছে তা আপনাকে বলুন।
রিগ

1
লেবেলটি অবশ্যই লুপের মধ্যে থেকে দৃশ্যমান হওয়া উচিত। আমি @ জন আর। স্ট্রোহমের মন্তব্যের সুস্পষ্ট দৈর্ঘ্যের অংশের সাথে একমত। এবং আপনার বক্তব্য, লুপ হ্যাকেরিতে অনুবাদ করা, "কীসের বিরতি? এটি লুপ নয়!" হয়ে যায়। যাই হোক না কেন, এটি ওপি যা হতে পারে তার আশঙ্কা করছে, তাই আমি আলোচনাটি এড়িয়ে চলেছি।
এআইব

-1
for (int y=0; y<height; ++y) {
    for (int x=0; x<width; ++x) {
        if (find(x, y)) goto found;
    }
}
found:

যদি কেবল একটি লুপ থাকে তবে breakঠিক যেমন কাজ করে goto, যদিও কোনও কলঙ্ক না রাখে।
9000

6
-1: প্রথম, x এবং y খুঁজে পাওয়া যায় না: সুতরাং এটি আপনাকে কোনও সাহায্য করবে না। দ্বিতীয়ত, কোডটি লিখিত হিসাবে কোডটি সহ, আপনি যে পৌঁছেছেন তার সত্যতা: এর অর্থ এই নয় যে আপনি যা খুঁজছিলেন তা পেয়েছেন।
জন আর স্ট্রোহম

এর কারণ এটি একাধিক সংখ্যক লুপ ভেঙে ফেলার ক্ষেত্রে আমি সবচেয়ে ছোট উদাহরণটি ভাবতে পারি। আরও ভাল লেবেল বা সম্পন্ন চেকের জন্য এটি সম্পাদনা করতে নির্দ্বিধায় দয়া করে
এআইব

1
তবে এগুলিও মনে রাখবেন যে সি ফাংশনগুলি অগত্যা পার্শ্ব-প্রভাব-মুক্ত নয়।
এআইব

1
@ জনআর.স্ট্রোহম এটি প্রচুর পরিমাণে বোঝায় না ... 'পাওয়া' লেবেলটি ভেরিয়েবলগুলি পরীক্ষা করতে নয়, লুপ ভাঙতে ব্যবহৃত হয়। আমি যদি ভেরিয়েবলগুলি পরীক্ষা করতে চাইতাম তবে আমি এরকম কিছু করতে পারতাম: (int y = 0; y <উচ্চতা; ++ y) {এর জন্য (int x = 0; x <প্রস্থ; ++ x) {যদি (সন্ধান করুন ( x, y)) S doSomeThingWith (x, y); পাওয়া গেল; }}} পাওয়া গেছে:
YoYoYonnY

-1

সর্বদা শিবিরগুলি থাকবে যেগুলি বলে যে একটি উপায় গ্রহণযোগ্য এবং অন্যটি যা তা নয়। আমি যে সংস্থাগুলির জন্য কাজ করেছি সেগুলি গোটো ব্যবহারকে ভীষণভাবে নিরুৎসাহিত করেছে। ব্যক্তিগতভাবে, আমি যে কোনও সময় ব্যবহার করেছি তা আমি ভাবতে পারি না, তবে এর অর্থ এই নয় যে তারা খারাপ , কাজ করার আরও একটি উপায়।

সি তে, আমি সাধারণত নিম্নলিখিতগুলি করি:

  • এমন শর্তগুলির জন্য পরীক্ষা করুন যা প্রক্রিয়াকরণ (খারাপ ইনপুটস ইত্যাদি) এবং "ফেরত" রোধ করতে পারে
  • সমস্ত পদক্ষেপগুলি করুন যা সংস্থার বরাদ্দ প্রয়োজন (যেমন mallocs)
  • প্রক্রিয়া সম্পাদন করুন, যেখানে একাধিক পদক্ষেপ সাফল্যের জন্য পরীক্ষা করে
  • সফলভাবে বরাদ্দ থাকলে যে কোনও সংস্থান মুক্তি করুন
  • কোনও ফলাফল ফেরত দিন

প্রক্রিয়াকরণের জন্য, আপনার গোটো উদাহরণটি ব্যবহার করে, আমি এটি করব:

ত্রুটি = ফাংশন_এই_কিল্ড_ফেইল_ (); যদি (! ত্রুটি) {ত্রুটি = ফাংশন_এই_কিল্ড_ফেইল_2 (); } যদি (! ত্রুটি) {ত্রুটি = ফাংশন_ট_কিল্ড_ফয়েল_3 (); }

কোনও নেস্টিং নেই, এবং আইফোন ক্লজগুলির মধ্যে, যদি পদক্ষেপটি ত্রুটি তৈরি করে তবে আপনি কোনও ত্রুটি প্রতিবেদন করতে পারেন। সুতরাং, এটি গোটোস ব্যবহারের পদ্ধতির চেয়ে "খারাপ" হতে হবে না।

আমি এখনও এমন একটি মামলা চালিয়ে যেতে পেরেছি যেখানে কারও কাছে গোটস রয়েছে যা অন্য কোনও পদ্ধতিতে করা যায় না এবং এটি কেবল পঠনযোগ্য / বোধগম্য এবং এটিই মূল, আইএমএইচও।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.