নেস্টেড লুপ থেকে ব্রেকিং


216

যদি আমার কাছে লুপের জন্য থাকে যা অন্যের মধ্যে বাসা বেঁধে থাকে তবে আমি কীভাবে দক্ষতার সাথে দ্রুততম উপায়ে উভয় লুপ থেকে (অভ্যন্তরীণ এবং বাহ্যিক) বাইরে আসতে পারি?

আমি বুলিয়ান ব্যবহার করতে চাই না এবং তারপরে অন্য পদ্ধতিতে যেতে বলি না, কেবল কেবল বাহ্যিক লুপের পরে কোডের প্রথম লাইনটি কার্যকর করতে হয়।

এটি সম্পর্কে একটি দ্রুত এবং সুন্দর উপায় কি?

আমি ভাবছিলাম যে ব্যতিক্রমগুলি সস্তা নয় / কেবল সত্যিকারের ব্যতিক্রমী অবস্থাতেই ফেলে দেওয়া উচিত Hence সুতরাং আমি মনে করি না যে সমাধানটি পারফরম্যান্সের দৃষ্টিকোণ থেকে ভাল হবে।

.NET (আনোন পদ্ধতি) এর নতুন বৈশিষ্ট্যগুলির সদ্ব্যবহার করা সঠিক বলে মনে করি না এটি বেশ মৌলিক।


আমি কেবল এটি নিশ্চিত করতে চেয়েছিলাম: আপনি এটি করতে চান কেন?
জন লিমাজাপ

3
আপনি বুলিয়ান ব্যবহার করতে চান না কেন? এটা করতে দোষ কী?
অ্যান্টনি

VB.net এ আপনি একটি চেষ্টা / শেষ অবধি বিবরণটি (কোনও ধরতে পারবেন না) একটি স্বেচ্ছাসেবী সংখ্যার লুপের চারপাশে আবদ্ধ করতে পারেন, তারপরে "প্রস্থান চেষ্টা করুন" যে কোনও বিন্দুতে সেগুলি থেকে প্রস্থান করবে।
Brain2000

উত্তর:


206

ঠিক আছে, gotoতবে এটি কুরুচিপূর্ণ এবং সর্বদা সম্ভব নয়। আপনি কোনও পদ্ধতিতে (বা আনন-পদ্ধতি) এও লুপগুলি রাখতে পারেন এবং returnমূল কোডটিতে ফিরে যেতে ব্যবহার করতে পারেন ।

    // goto
    for (int i = 0; i < 100; i++)
    {
        for (int j = 0; j < 100; j++)
        {
            goto Foo; // yeuck!
        }
    }
Foo:
    Console.WriteLine("Hi");

বনাম:

// anon-method
Action work = delegate
{
    for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            return; // exits anon-method
        }
    }
};
work(); // execute anon-method
Console.WriteLine("Hi");

নোট করুন যে সি # 7 এ আমাদের "স্থানীয় ফাংশনগুলি" পাওয়া উচিত, যার (সিনট্যাক্স টিবিডি ইত্যাদি) এর অর্থ এটির মতো কিছু কাজ করা উচিত:

// local function (declared **inside** another method)
void Work()
{
    for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            return; // exits local function
        }
    }
};
Work(); // execute local function
Console.WriteLine("Hi");

49
এই ধরণের পরিস্থিতিতে আমি মনে করি না যে গোটো ব্যবহার বিরতির মতো কোনও কিছুর সাধারণ ব্যবহারের চেয়ে খারাপ (সর্বোপরি তারা উভয়ই একটি লেবেলে নিঃশর্ত শর্তযুক্ত, এটি কেবল ব্রেকের সাথে লেবেল অন্তর্নিহিত)।
গ্রেগ বিচ 0

37
কখনও কখনও বিকল্পগুলির তুলনায়
গোটো

7
@ বিউওউলোফএফ - বিরতি কেবল অভ্যন্তরীণ লুপ থেকে বিভক্ত হবে, অভ্যন্তরীণ এবং বাইরের লুপগুলি নয়।
গ্রেগ বিচ

36
গোটো নিজেই কুৎসিত নয়। কুৎসিত কি গোটোকে গালি দিচ্ছে যার ফলস্বরূপ স্প্যাগেটি কোড। নেস্টেড লুপটি ভেঙে ফেলার জন্য গোটো ব্যবহার করা নিখুঁতভাবে ঠিক। এছাড়াও, লক্ষ করুন যে স্ট্রাকচারাল প্রোগ্রামিং দৃষ্টিকোণ থেকে সমস্ত বিরতি, চালিয়ে যাওয়া এবং ফিরে আসা, গোটোর চেয়ে খুব ভাল - মূলত তারা ঠিক একই জিনিস, কেবল প্যাকেজিংয়ে। এজন্য খাঁটি কাঠামোগত ভাষার (যেমন আসল পাস্কাল) তিনটির তিনটিরই অভাব রয়েছে।
el.pescado

11
@ el.pescado সম্পূর্ণভাবে সঠিক: অনেক পরিকল্পনাটি বিশ্বাস করতে ভুল পথে চালিত হয়েছে gotoক্ষতিকর প্রতি SE , যখন এটি সহজভাবে হয় সঠিক কিছু কিছু করার যন্ত্র, এবং অনেক যন্ত্র মত অপব্যবহার হতে পারে। এই ধর্মীয় বিদ্বেষ স্পষ্টভাবেgoto নির্বোধ এবং অবশ্যই অবৈজ্ঞানিক।
o0 '

96

সি # এর পদ্ধতির রূপান্তরটি প্রায়শই সি-এ ব্যবহৃত হয় - লুপের অবস্থার বাইরে বাইরের লুপের ভেরিয়েবলের সেট মান (যেমন ইন্ট ভেরিয়েবল ব্যবহার করে লুপের INT_MAX -1জন্য প্রায়শই ভাল পছন্দ):

for (int i = 0; i < 100; i++)
{
    for (int j = 0; j < 100; j++)
    {
        if (exit_condition)
        {
            // cause the outer loop to break:
            // use i = INT_MAX - 1; otherwise i++ == INT_MIN < 100 and loop will continue 
            i = int.MaxValue - 1;
            Console.WriteLine("Hi");
            // break the inner loop
            break;
        }
    }
    // if you have code in outer loop it will execute after break from inner loop    
}

কোডে নোট হিসাবে breakযাদু হিসাবে বাহ্যিক লুপের পরবর্তী পুনরাবৃত্তিতে ঝাঁপ দেবে না - সুতরাং আপনার যদি অভ্যন্তরীণ লুপের বাইরের কোড থাকে তবে এই পদ্ধতির আরও চেক প্রয়োজন। এই ক্ষেত্রে অন্যান্য সমাধান বিবেচনা করুন।

এই পদ্ধতির সাথে কাজ করে forএবং whileলুপগুলি কার্যকর হয় না foreach। যদি foreachআপনার কাছে লুকানো IEnumeratorগণকের কোড অ্যাক্সেস না থাকে তবে আপনি এটি পরিবর্তন করতে পারবেন না (এবং আপনার যদি কিছু "মুভটোএন্ড" পদ্ধতি নাও থাকতে পারে )।

অন্তর্ভুক্ত মন্তব্যগুলির লেখকদের কাছে স্বীকৃতি: মেটা
i = INT_MAX - 1 দ্বারা পরামর্শ / ygoe দ্বারা মন্তব্য । যথাযথ দ্বারা jmbpiano দ্বারা ভেতরের লুপ পর কোড সম্পর্কে মন্তব্য blizpasta
forforeach
IntMax


@ ডিআরজি: সি # তে কাজ করবেন না কারণ "ব্রেক স্টেটমেন্টটি নিকটে থাকা ঘেরের লুপ বা সুইচ বিবৃতিতে এটি প্রদর্শিত হবে বলে সমাপ্ত করে।" (এমএসডিএন)
blizpasta

1
@ ব্লিজপাস্টা তাই? যদি তিনি বাইরের লুপের শর্তটি মিথ্যা করেন (যেমন তিনি করেছিলেন) তবে এটি উভয়ই প্রস্থান করবে।
প্যাট্রিক

51
আপনার i = INT_MAX - 1 ব্যবহার করা উচিত; অন্যথায় আমি ++ == INT_MIN <100 এবং লুপটি অবিরত থাকবে
মেটা

6
ভবিষ্যদ্বাণী সম্পর্কে কোন ধারণা?
ktutnik

4
@ktutnik এটি foreach নিয়ে কাজ করবে না কারণ আপনার কাছে লুকানো এনুমিরেটরের কোড অ্যাক্সেস নেই। এছাড়াও আইনিমরেটরটির কিছু "মুভটোএন্ড" পদ্ধতি নেই।
ygoe

39

এই সমাধানটি সি # তে প্রযোজ্য নয়

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

outer: while(fn1())
{
   while(fn2())
   {
     if(fn3()) continue outer;
     if(fn4()) break outer;
   }
}

40
এটি দুঃখজনক যে এটি সি # দিয়ে করা যায় না, এটি অনেক সময় ক্লিনার কোড তৈরি করে।
রিকার্ড 11'12

17
আমি বুঝতে পারছি না যতক্ষণ না আমি বুঝতে পেরেছিলাম যে এটি সি # এর জন্য নয়। :(
আরভো বোভেন

1
এই ধারণাটি পাওয়ারশেলের জন্যও যদি কেউ কেউ সমস্যাটি দেখা দেয় তবে। (তারা কেবলমাত্র কোলনটিকে লেবেলের নামের সামনে রাখে)) এখন আমি জানি এটি পাওয়ারশেল-নির্দিষ্ট নয় ... এই বাক্য গঠনটি সি # তে উপলব্ধ গোটো লেবেলের সাথে বেমানান হবে। পিএইচপি অন্য কিছু ব্যবহার করে: বিরতি 3; ব্রেক স্টেটমেন্টের পরে স্তরের সংখ্যা রাখুন।
ygoe

1
এটি জাভা নয় সি #
লুকা জিগলার

যারা এই বৈশিষ্ট্যটি সি # তে দেখতে চান, আপনার কুডোগুলি
m93a

28

বাইরের লুপে উপযুক্ত গার্ড ব্যবহার করুন। বিরতি দেওয়ার আগে অভ্যন্তরীণ লুপে প্রহরী সেট করুন।

bool exitedInner = false;

for (int i = 0; i < N && !exitedInner; ++i) {

    .... some outer loop stuff

    for (int j = 0; j < M; ++j) {

        if (sometest) {
            exitedInner = true;
            break;
        }
    }
    if (!exitedInner) {
       ... more outer loop stuff
    }
}

বা আরও ভাল, কোনও পদ্ধতিতে অভ্যন্তরীণ লুপটি বিমূর্ত করুন এবং যখন এটি মিথ্যা দেখায় তখন বাইরের লুপটি প্রস্থান করুন।

for (int i = 0; i < N; ++i) {

    .... some outer loop stuff

    if (!doInner(i, N, M)) {
       break;
    }

    ... more outer loop stuff
}

4
ওপিকে বাদ দিয়ে "আমি কোনও বুলিয়ান ব্যবহার করতে চাই না" বলেছিল।
চিতাবাঘ স্কিনপিলবক্সহ্যাট

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

21

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

যাও:

for ( int i = 0; i < 10; ++i ) {
   for ( int j = 0; j < 10; ++j ) {
      // code
      if ( break_condition ) goto End;
      // more code
   }
}
End: ;

কন্ডিশন:

bool exit = false;
for ( int i = 0; i < 10 && !exit; ++i ) {
   for ( int j = 0; j < 10 && !exit; ++j ) {
      // code
      if ( break_condition ) {
         exit = true;
         break; // or continue
      }
      // more code
   }
}

ব্যতিক্রম:

try {
    for ( int i = 0; i < 10 && !exit; ++i ) {
       for ( int j = 0; j < 10 && !exit; ++j ) {
          // code
          if ( break_condition ) {
             throw new Exception()
          }
          // more code
       }
    }
catch ( Exception e ) {}

2
এগুলি সমস্ত হ্যাকি ওয়ার্কআরউন্ডস যেখানে এটি কোনও পদ্ধতিতে কেবল ফ্যাক্টর এবং তাড়াতাড়ি রিটার্ন ব্যবহার করতে সুপার ক্লিন হবে
ডাস্টিন গেটেজ

3
:) ঠিক আছে, এটি একটি সহজ সমাধান, তবে আপনাকে প্রয়োজনীয় সমস্ত স্থানীয় ডেটাটি পদ্ধতিতে আর্গুমেন্ট হিসাবে প্রেরণ করতে হবে ... এটি এমন কয়েকটি জায়গার মধ্যে একটি যেখানে উপযুক্ত সমাধান হতে পারে
ডেভিড রদ্রিগেজ - ড্রিবিস

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

আমি লেবেলের পরে সেই সেমিকোলনটি হাইলাইট করব। এই লেবেলটি কোনও ব্লকের শেষেও হতে পারে। +1
তামাস হেজেডাস

@ উইন্ডোস্প্রাগ্রামার ওপি জিজ্ঞাসা করেছিল, "এটির দ্রুত এবং সুন্দর উপায় কী?" গোটো হ'ল পছন্দসই সমাধান: একটি পৃথক পদ্ধতি জড়িত না করে পরিষ্কার এবং সংক্ষিপ্ততর।
সানকাট 2000

16

একটি ব্যক্তিগত পদ্ধতিতে লুপের জন্য নেস্টেড রিফ্যাক্টর করা কি সম্ভব? লুপ থেকে প্রস্থান করার জন্য আপনি পদ্ধতিটি থেকে কেবল 'ফিরে' যেতে পারেন।


আপনার আসল পদ্ধতিটি আরও খাটো করার পার্শ্ব সুবিধার সাথে :-)
মার্টিন ক্যাপোডিসি

সি ++ 11 ল্যাম্বডাস কিছু ক্ষেত্রে এটি সহজ করে তোলে:[&] { ... return; ... }();
বিসিএস

14

এটি আমার কাছে মনে হয় যেন লোকেরা কোনও gotoবক্তব্যকে অনেক অপছন্দ করে , তাই আমি এটি কিছুটা সোজা করার প্রয়োজন অনুভব করেছি।

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

যেমনটি আমরা সবাই জানি, সি # আইএল-তে সংকলিত হয়, যা এসএসএ সংকলক ব্যবহার করে এসেম্বলারের জন্য সংকলিত হয়। আমি কীভাবে এটি সমস্ত কাজ করে সে সম্পর্কে কিছুটা অন্তর্দৃষ্টি দেব এবং তারপরে প্রশ্নের উত্তরটি নিজেই দেওয়ার চেষ্টা করব।

সি # থেকে আইএল পর্যন্ত

প্রথমে আমাদের সি # কোডের একটি টুকরা দরকার। সহজ শুরু করা যাক:

foreach (var item in array)
{
    // ... 
    break;
    // ...
}

হুডের নীচে কী ঘটে তা আপনাকে একটি ভাল ধারণা দেওয়ার জন্য আমি এই পদক্ষেপটি করব do

প্রথম অনুবাদ: foreachসমতুল্য forলুপ থেকে (দ্রষ্টব্য: আমি এখানে একটি অ্যারে ব্যবহার করছি, কারণ আমি আইডিস্পোসেবলের বিশদ পেতে চাই না - এই ক্ষেত্রে আমাকে একটি আইনুমেবলও ব্যবহার করতে হবে):

for (int i=0; i<array.Length; ++i)
{
    var item = array[i];
    // ...
    break;
    // ...
}

দ্বিতীয় অনুবাদ: একটি forএবং breakসহজ সমতুল্যে অনুবাদ করা হয়েছে:

int i=0;
while (i < array.Length)
{
    var item = array[i];
    // ...
    break;
    // ...
    ++i;
}

তৃতীয়ত অনুবাদ (এই আইএল কোডের সমতূল্য): আমরা পরিবর্তন breakএবং whileএকটি শাখা মধ্যে:

    int i=0; // for initialization

startLoop:
    if (i >= array.Length) // for condition
    {
        goto exitLoop;
    }
    var item = array[i];
    // ...
    goto exitLoop; // break
    // ...
    ++i;           // for post-expression
    goto startLoop; 

সংকলক একক পদক্ষেপে এই জিনিসগুলি করার সময় এটি আপনাকে প্রক্রিয়াটির অন্তর্দৃষ্টি দেয়। সি # প্রোগ্রাম থেকে যে আইএল কোডটি বিকশিত হয়েছিল তা হ'ল শেষ সি # কোডের আক্ষরিক অনুবাদ । আপনি নিজের জন্য এখানে দেখতে পারেন: https://dotnetfiddle.net/QaiLRz ('আইএল দেখুন' ক্লিক করুন)

এখন, আপনি এখানে একটি জিনিস লক্ষ্য করেছেন যে প্রক্রিয়া চলাকালীন, কোডটি আরও জটিল হয়ে ওঠে। এটি পর্যবেক্ষণ করার সবচেয়ে সহজ উপায়টি হ'ল একই জিনিসটি আকাকম্পল করতে আমাদের আরও বেশি সংখ্যক কোডের প্রয়োজন। এছাড়াও, আপনি এখানে তর্ক হতে পারে foreach, for, whileএবং breakজন্য আসলে স্বল্প হাত goto, যা আংশিকভাবে সত্য।

আইএল থেকে এসেমব্লার পর্যন্ত

.NET JIT সংকলক একটি এসএসএ সংকলক। আমি এখানে এসএসএ ফর্মের সমস্ত বিশদ এবং কীভাবে একটি অপ্টিমাইজিং সংকলক তৈরি করব তা যাব না, এটি কেবলমাত্র অনেক বেশি, তবে কী হবে তা সম্পর্কে প্রাথমিক ধারণা দিতে পারি। আরও গভীর বোঝার জন্য, সংকলকগুলি অনুকূলকরণের উপর পড়া শুরু করা ভাল (একটি সংক্ষিপ্ত পরিচিতির জন্য আমি এই বইটি পছন্দ করি: http://ssabook.gforge.inria.fr/latest/book.pdf সংযোজকগুলি অনুকূলকরণের পরিচিতির ) এবং এলএলভিএম (llvm.org) ।

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

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

    int i=0; // for initialization

    if (i >= array.Length) // for condition
    {
        goto endOfLoop;
    }

startLoop:
    var item = array[i];
    // ...
    goto endOfLoop; // break
    // ...
    ++i;           // for post-expression

    if (i >= array.Length) // for condition
    {
        goto startLoop;
    }

endOfLoop:
    // ...

আপনি দেখতে পাচ্ছেন, আমাদের এখন একটি পশ্চাদপদ শাখা রয়েছে যা আমাদের ছোট লুপ। এখানে এখনও কদর্য একমাত্র জিনিসটি সেই শাখা যা আমরা আমাদের breakবক্তব্যের কারণে শেষ করেছিলাম । কিছু ক্ষেত্রে, আমরা এটিকে একই পথে স্থানান্তর করতে পারি, তবে অন্যদের মধ্যে এটি থাকার জন্য রয়েছে।

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

যাইহোক, শাখাগুলি সেই দুর্দান্ত অনুমানযোগ্য নিদর্শনগুলিকে ভাঙতে ঝোঁক করে, এটি অপ্টিমাইজারের কিছু তাই অত্যাধিক-অপছন্দ। ভাঙ্গা, চালিয়ে যাও, যাও - তারা সকলেই এই ভবিষ্যদ্বাণীমূলক নিদর্শনগুলি ভাঙ্গার ইচ্ছাকৃত- এবং তাই সত্যই 'সুন্দর' নয়।

আপনার এই মুহুর্তে উপলব্ধি করা উচিত যে একটি সরল foreachআরও অনুমানযোগ্য তবে gotoবিবৃতিগুলির একটি গোছা যা পুরো জায়গা জুড়ে। অপ্টিমাইজারের দৃষ্টিকোণ থেকে (1) পঠনযোগ্যতা এবং (2) এর পরিপ্রেক্ষিতে এটি উভয়ই ভাল সমাধান।

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

সহায়তা, খুব জটিলতা ... আমার কি করা উচিত?

তল লাইনটি হ'ল আপনার নিজের ভাষাতে আপনার নির্মিত ভাষা নির্মাণগুলি সর্বদা ব্যবহার করা উচিত, যা সাধারণত (ছদ্মবেশী) আপনার সংকলকটির জন্য অনুমানযোগ্য নিদর্শন তৈরি করে। (: বিশেষভাবে সম্ভব হলে অদ্ভুত শাখা এড়ানোর চেষ্টা break, continue, gotoবা returnকিছুই মাঝখানে)।

এখানে সুসংবাদটি হ'ল এই অনুমানযোগ্য নিদর্শনগুলি উভয়ই পড়া সহজ (মানুষের জন্য) এবং স্পট করা সহজ (সংকলকগুলির জন্য) উভয়ই।

এই নিদর্শনগুলির মধ্যে একটিকে এসইএসই বলা হয়, যা সিঙ্গল এন্ট্রি সিঙ্গেল এক্সিটের জন্য দাঁড়ায়।

এবং এখন আমরা আসল প্রশ্ন পেতে।

কল্পনা করুন যে আপনার কাছে এরকম কিছু রয়েছে:

// a is a variable.

for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j)
  {
     // ...

     if (i*j > a) 
     {
        // break everything
     }
  }
}

এটি অনুমানযোগ্য প্যাটার্ন করার সহজতম উপায় হ'ল ifসম্পূর্ণরূপে মুছে ফেলা :

int i, j;
for (i=0; i<100 && i*j <= a; ++i) 
{
  for (j=0; j<100 && i*j <= a; ++j)
  {
     // ...
  }
}

অন্যান্য ক্ষেত্রে আপনি পদ্ধতিটি 2 টি পদ্ধতিতেও বিভক্ত করতে পারেন:

// Outer loop in method 1:

for (i=0; i<100 && processInner(i); ++i) 
{
}

private bool processInner(int i)
{
  int j;
  for (j=0; j<100 && i*j <= a; ++j)
  {
     // ...
  }
  return i*j<=a;
}

অস্থায়ী পরিবর্তনশীল? ভাল, খারাপ না কদর্য?

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

কিছু লোক মনে করেন এটি অস্থায়ী পরিবর্তনশীল ব্যবহার করা পরিষ্কার, এবং এর মতো সমাধানের প্রস্তাব দিন:

bool more = true;
for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j) 
  {
     // ...
     if (i*j > a) { more = false; break; } // yuck.
     // ...
  }
  if (!more) { break; } // yuck.
  // ...
}
// ...

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

ঠিক আছে, আমাকে এটি বানান। কি ঘটবে তা হ'ল:

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

সুতরাং, সংক্ষেপে বলি: আপনার সংকলকটির অপ্টিমাইজারটি moreকেবল নিয়ন্ত্রণ প্রবাহের জন্য ব্যবহৃত হয় তা নির্ধারণ করার জন্য অনেক ঝামেলার জাহান্নামে চলে যাবে , এবং সর্বোত্তম ক্ষেত্রে এটির জন্য বাইরের বাইরের একটি শাখায় অনুবাদ করবে লুপ.

অন্য কথায়, সর্বোত্তম মামলার দৃশ্যপট হ'ল এটি এর সমতুল্য সমাপ্ত হবে:

for (int i=0; i<100; ++i) 
{
  for (int j=0; j<100; ++j)
  {
     // ...
     if (i*j > a) { goto exitLoop; } // perhaps add a comment
     // ...
  }
  // ...
}
exitLoop:

// ...

এ সম্পর্কে আমার ব্যক্তিগত মতামতটি বেশ সহজ: আমরা যদি এই বিষয়টিকেই পাশাপাশি রেখেছিলাম তবে আসুন আমরা সংকলক এবং পঠনযোগ্যতা উভয়ের জন্যই বিশ্বকে সহজ করে তুলি এবং এখনই এটি লিখি।

TL; ড:

শেষের সারি:

  • লুপের জন্য যদি সম্ভব হয় তবে একটি সাধারণ শর্ত ব্যবহার করুন। যথাসম্ভব আপনার হাতে থাকা উচ্চ-স্তরের ভাষা নির্মাণকে আঁকুন।
  • যদি সবকিছু ব্যর্থ হয় এবং আপনি উভয়ের সাথে ছেড়ে যান gotoবা bool more, পূর্বেরটিকে পছন্দ করুন।

ওটোঃ আমার খুব কমই বাইরের লুপগুলি ভেঙে ফেলার ইচ্ছা বা গোটো-সমতুল্য (এবং প্রচুর কোড যা যুক্তিযুক্তভাবে আরও পরিষ্কারভাবে লেখা যেতে পারে) এর ইচ্ছা পোষণ করতে পারে, যদিও অন্য ডোমেনগুলিতে এগুলি বেশি সাধারণ হতে পারে .. আজ এমন একটি ঘটনা ছিল, কিন্তু যে মূলত হবার কথা ছিলো yield return। এটি হ'ল সহজেই কিছু কার্যকর কেস দেখাতে পারা যায়, বেশিরভাগ "অ্যাপ্লিকেশন-স্তরের" কোডের জন্য এটি সম্ভবত সি # এর সাথে হতাশার খুব কম ঘটনা, কেবলমাত্র "সি / সি ++ ;-) থেকে আসা" ব্যতীত "আমিও মাঝে মাঝে মিস করি miss উপলক্ষে রুবির "নিক্ষেপ" (অ-ব্যতিক্রমী উইন্ডোজিং) যেমন এটি এই ডোমেনেও ফিট করে।
ব্যবহারকারী 2864740

1
@ সানকাট ২000 কেবল এটিকে এড়াতে ভেরিয়েবল এবং শর্তসাপেক্ষ শাখার মতো আরও কোড প্রবর্তন করা gotoআপনার কোডটি আরও পঠনযোগ্য করে তুলবে না - আমার যুক্তিটি কী যুক্তি দেয় তার ঠিক বিপরীত: আসলে আপনার নিয়ন্ত্রণ প্রবাহে আরও নোড থাকবে - যা অনেক বেশি জটিলতার সংজ্ঞা। স্ব-শৃঙ্খলা রক্ষার জন্য এটি এড়ানো কেবল পঠনযোগ্যতার ক্ষেত্রে উত্পাদনশীল শোনায়।
এটলস্টে

@ অ্যাটলস্ট: দুঃখিত, আমার মন্তব্যটি আরও স্পষ্টভাবে আমাকে জানাতে দিন। আমার যা বলা উচিত ছিল তা হ'ল: সুন্দর ব্যাখ্যা। কিন্তু গোটো এড়ানো লোকেরা পারফরম্যান্সের বিষয়ে নয়; এটি অপব্যবহার এড়ানো সম্পর্কে যা পাঠযোগ্যতার অভাবের কারণ হয়। আমরা ধরে নিতে পারি যে যারা এড়িয়ে চলেন তাদের gotoকেবল এটির অপব্যবহার না করার শৃঙ্খলা নেই।
সানকাট 2000

@ অ্যাটলাস্ট, "অ্যাকম্পম্প্লিশ" কোন ভাষা?
পেসারিয়ার

11

কোনও ফাংশন / পদ্ধতিতে ফ্যাক্টর করুন এবং তাড়াতাড়ি রিটার্ন ব্যবহার করুন বা আপনার লুপগুলিকে কিছুক্ষণের মধ্যে পুনর্বিন্যাস করুন। গোটো / ব্যতিক্রম / যা অবশ্যই এখানে উপযুক্ত নয়।

def do_until_equal():
  foreach a:
    foreach b:
      if a==b: return

10

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

গোটো ব্যবহার করা সবচেয়ে দ্রুত এবং স্বল্পতম উপায়।


সম্পূর্ণ একমত. একটি মাত্র গোটো থেকে মুক্তি পেতে একটি নতুন পদ্ধতি প্রবর্তন করা নিরীহ। সংকলক যদি কোনও কারণে সেই পদ্ধতির কলটিকে ইনলাইন করতে না পারে - আমরা অতিরিক্ত পদ্ধতি কলের সম্পূর্ণ অপ্রয়োজনীয় ওভারহেড দিয়ে শেষ করব। কেবল লুপটি ভাঙতে ব্যতিক্রম ছুঁড়ে ফেলা এবং ধরা দুটোই ভার্জিক এবং হাস্যকরভাবে আরও ব্যয়বহুল।
জার শারদান

@ উইন্ডোস্প্রাগ্রাম: ওপি "গোটো ব্যবহার না করার জন্য" জিজ্ঞাসা করেনি। তিনি "অন্য পদ্ধতিতে যেতে" চান না। প্রশ্নটি সম্ভাব্য সমস্ত উপায়ে রায় দেওয়া থেকে দূরে ছিল , তবে আপনি এখানেই সেরা সেরাটি বোঝান ঠিক বলেছেন।
সানকাট 2000

5

কখনও কখনও কোডটিকে তার নিজস্ব ফাংশনে বিমূর্ত করা ভাল লাগে এবং তাড়াতাড়ি রিটার্ন ব্যবহার না করে - প্রারম্ভিক আয়গুলি খারাপ হয় যদিও:)

public void GetIndexOf(Transform transform, out int outX, out int outY)
{
    outX = -1;
    outY = -1;

    for (int x = 0; x < Columns.Length; x++)
    {
        var column = Columns[x];

        for (int y = 0; y < column.Transforms.Length; y++)
        {
            if(column.Transforms[y] == transform)
            {
                outX = x;
                outY = y;

                return;
            }
        }
    }
}

1
তবে তারপরে এটি ওপি
সূর্য প্রতাপ

2

আমি অনেকগুলি উদাহরণ দেখেছি যা "ব্রেক" ব্যবহার করে তবে "চালিয়ে যান" ব্যবহার করে না।

এটি এখনও অভ্যন্তরীণ লুপে কোনও ধরণের পতাকা প্রয়োজন:

while( some_condition )
{
    // outer loop stuff
    ...

    bool get_out = false;
    for(...)
    {
        // inner loop stuff
        ...

        get_out = true;
        break;
    }

    if( get_out )
    {
        some_condition=false;
        continue;
    }

    // more out loop stuff
    ...

}

1

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

break; // our trusty friend, breaks out of current looping construct.
break 2; // breaks out of the current and it's parent looping construct.
break 3; // breaks out of 3 looping constructs.
break all; // totally decimates any looping constructs in force.

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

অপেক্ষা করুন, কে আর রক্ষণাবেক্ষণ প্রোগ্রামিং করে? :)
জেসি সি স্লিকার

2
জাভাস্ক্রিপ্ট এমনকি ব্লক / ব্রেক স্টেটমেন্ট লেবেলযুক্ত। devguru.com
ডেভিড গ্রান্ট

@ ক্রিস বার্তো: দুর্দান্ত! আমার ক্রিসমাস বানিয়েছে :) @ ডেভিড গ্রান্ট: সুতরাং মনে হচ্ছে জেএস ব্রেক == সি এর গোটো?
জেসি সি স্লিকার

ডি বিরতি / অবিরত হিসাবে লেবেলযুক্ত করেছেন
বিসিএস 21

0

আমার ছাত্র দিবস থেকেই মনে আছে যে এটি গাণিতিকভাবে প্রমাণযোগ্য যে আপনি গোটো ব্যতীত কোডে কিছু করতে পারবেন (অর্থাত্ গোটোর একমাত্র উত্তর হ'ল এমন পরিস্থিতি নেই)। সুতরাং, আমি কখনই গোটো ব্যবহার করি না (কেবলমাত্র আমার ব্যক্তিগত পছন্দ, আমি ঠিক বা ভুলটি বোঝায় না)

যাইহোক, নেস্টেড লুপগুলি ভেঙে ফেলার জন্য আমি এই জাতীয় কিছু করি:

var isDone = false;
for (var x in collectionX) {
    for (var y in collectionY) {
        for (var z in collectionZ) {
            if (conditionMet) {
                // some code
                isDone = true;
            }
            if (isDone)
                break;
        }
        if (isDone) 
            break;
    }
    if (isDone)
        break;
}

... আমি আশা করি যাঁরা আমার পছন্দ করেন তাদের পক্ষে সহায়তা করে তারা অ্যান্টি-গোটো "ফ্যানবয়" :)


আপনাকে জানাতে দুঃখিত, তবে আপনার অবস্থার জন্য আপনার প্রভাষকই দোষী। যদি তিনি আপনাকে সমাবেশ শিখতে বাধ্য করেন, তবে আপনি জানেন যে 'গোটো' কেবল একটি লাফান (অবশ্যই আমি এটিকে # প্রশ্ন এই বিষয়টিকে এড়িয়ে যাচ্ছি)।
সেমরোয়ানিরগো

0

আমি এটিই করেছিলাম। এখনও একটি workaround।

foreach (var substring in substrings) {
  //To be used to break from 1st loop.
  int breaker=1;
  foreach (char c in substring) {
    if (char.IsLetter(c)) {
      Console.WriteLine(line.IndexOf(c));
      \\setting condition to break from 1st loop.
      breaker=9;
      break;
    }
  }
  if (breaker==9) {
    break;
  }
}


0

ডাবল লুপটি শেষ করার সবচেয়ে সহজ উপায়টি হ'ল সরাসরি লুপটি শেষ হবে

string TestStr = "The frog jumped over the hill";
char[] KillChar = {'w', 'l'};

for(int i = 0; i < TestStr.Length; i++)
{
    for(int E = 0; E < KillChar.Length; E++)
    {
        if(KillChar[E] == TestStr[i])
        {
            i = TestStr.Length; //Ends First Loop
            break; //Ends Second Loop
        }
    }
}

বিরতি ব্যবহার করে এটি কাজ করে না আপনি অভ্যন্তরীণ লুপটি শেষ করবেন। বাইরের লুপটি পুনরাবৃত্তি হতে থাকবে।
অ্যালেক্স লিও

0

লুপটিতে কাস্টম অবস্থার ব্যবহার করে লুপগুলি ভেঙে ফেলা যায়, পরিষ্কার কোড থাকতে পারে।

    static void Main(string[] args)
    {
        bool isBreak = false;
        for (int i = 0; ConditionLoop(isBreak, i, 500); i++)
        {
            Console.WriteLine($"External loop iteration {i}");
            for (int j = 0; ConditionLoop(isBreak, j, 500); j++)
            {
                Console.WriteLine($"Inner loop iteration {j}");

                // This code is only to produce the break.
                if (j > 3)
                {
                    isBreak = true;
                }                  
            }

            Console.WriteLine("The code after the inner loop will be executed when breaks");
        }

        Console.ReadKey();
    }

    private static bool ConditionLoop(bool isBreak, int i, int maxIterations) => i < maxIterations && !isBreak;   

এই কোডের সাহায্যে আমরা নিম্নলিখিত আউটপুটটি সজ্জিত করছি:

  • বাহ্যিক লুপ পুনরাবৃত্তি 0
  • অভ্যন্তরীণ লুপ পুনরাবৃত্তি 0
  • অভ্যন্তরীণ লুপ পুনরাবৃত্তি 1
  • অভ্যন্তরীণ লুপ পুনরাবৃত্তি 2
  • অভ্যন্তরীণ লুপ পুনরাবৃত্তি 3
  • অভ্যন্তরীণ লুপ পুনরাবৃত্তি 4
  • অভ্যন্তরীণ লুপের পরে কোডটি বিরতিতে কার্যকর করা হবে

0

অন্য একটি বিকল্প হ'ল একটি স্বতঃসিদ্ধ বেনামী ফাংশন । শীর্ষে বেনাম-পদ্ধতির উদাহরণের চেয়ে কোনও গোটো, কোনও লেবেল, কোনও নতুন ভেরিয়েবল, কোনও নতুন ফাংশন-নাম ব্যবহার করা হয়নি এবং এক লাইন ছোট orter

// self-invoked-anonymous-function
new Action(() =>
{
    for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            return; // exits self invoked lambda expression
        }
    }
})();
Console.WriteLine("Hi");

-3

কাস্টম ব্যতিক্রম ছুঁড়ে ফেলুন যা আউটটার লুপের বাইরে চলে যায়।

এটা তোলে জন্য কাজ করে for, foreachবা whileবা লুপ যে কোন ধরণের এবং যে কোনো ভাষা ব্যবহারের try catch exceptionব্লক

try 
{
   foreach (object o in list)
   {
      foreach (object another in otherList)
      {
         // ... some stuff here
         if (condition)
         {
            throw new CustomExcpetion();
         }
      }
   }
}
catch (CustomException)
{
   // log 
}

-4
         bool breakInnerLoop=false
        for(int i=0;i<=10;i++)
        {
          for(int J=0;i<=10;i++)
          {
              if(i<=j)
                {
                    breakInnerLoop=true;
                    break;
                }
          }
            if(breakInnerLoop)
            {
            continue
            }
        }

ডিভিলজয়েনের উত্তরের সাথে প্রয়োজনীয় পার্থক্য কী?
গার্ট আর্নল্ড

এটি কাজ করবে না, কারণ আপনি লুপের জন্য বাইরের "ব্রেকইননারলুপ" শর্তটি পরীক্ষা করেন না, তাই আপনি কেবল পরবর্তী লুপটিতে পুনরাবৃত্তি করেন, আপনি জে এবং জে লিখেছিলেন এবং একটি সেমিকোলন মিস করেছেন, এটি সংকলন করবে না।
সেবাস্তিয়ান

-4

যেহেতু আমি দেখতে পেয়েছি যে আপনি সেই উত্তরটি স্বীকার করেছেন যার মধ্যে সেই ব্যক্তিটি আপনাকে গোটো স্টেটমেন্ট বোঝায়, যেখানে আধুনিক প্রোগ্রামিংয়ে এবং বিশেষজ্ঞের মতামত অনুসারে একটি হত্যাকারী, আমরা একে প্রোগ্রামিংয়ে একটি হত্যাকারী বলেছিলাম যার কিছু নির্দিষ্ট কারণ রয়েছে, যা আমি এখানে এটি নিয়ে আলোচনা করব না which এই মুহুর্তে, তবে আপনার প্রশ্নের সমাধান খুব সহজ, আপনি এই ধরণের দৃশ্যে বুলিয়ান পতাকা ব্যবহার করতে পারেন যেমন আমি এটি আমার উদাহরণে প্রদর্শন করব:

            for (; j < 10; j++)
            {
                //solution
                bool breakme = false;
                for (int k = 1; k < 10; k++)
                {
                   //place the condition where you want to stop it
                    if ()
                    {
                        breakme = true;
                        break;
                    }
                }

                if(breakme)
                    break;
               }

সহজ এবং সরল। :)


বিরতি দেওয়ার পরামর্শ দেওয়ার আগে প্রশ্নটি পড়ুন। সুতরাং ডাউনভোটস।
সেমরোয়ানিরগো

1
এটি এখনই পড়ুন, তবে আমি যখন উত্তরটি পোস্ট করেছি তখন বুলেটিয়ান ব্যবহার না করার সম্পাদিত সংস্করণটি যুক্ত করা হয়নি কারণ আমি এই উত্তরটি পোস্ট করেছি .. তবে ডাউনভোটের জন্য ধন্যবাদ!
স্টিভ

1
এটি কোনও ব্যক্তিগত জিনিস নয়। দুর্ভাগ্যক্রমে, ভোটটি এখন লক হয়ে গেছে;) শীর্ষের সেরা উত্তরগুলি পাওয়ার জন্য এটি
এসওর

-6

আপনি breakকিওয়ার্ডটিও দেখেছেন ? ওও

এটি কেবল ছদ্ম-কোড, তবে আমার অর্থ কী তা আপনি দেখতে সক্ষম হবেন:

<?php
for(...) {
    while(...) {
        foreach(...) {
            break 3;
        }
    }
}

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

ম্যানুয়াল: http://php.net/break


13
পিএইচপি প্রশ্ন নয়।
জেরগা

-10

আমি মনে করি আপনি "বুলিয়ান জিনিস" না করতে না পারলে কেবল সমাধানটিই আসলে নিক্ষেপ করা। যা আপনার অবশ্যই করা উচিত নয় ..!

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