নেস্টেড লুপগুলি ভেঙে কিভাবে যায়?


98

যদি আমি কোনও breakবিবৃতি ব্যবহার করি তবে এটি কেবল অভ্যন্তরীণ লুপটি ভেঙে দেবে এবং বাইরের লুপটি ভাঙ্গতে আমার কিছু পতাকা ব্যবহার করা দরকার। তবে যদি অনেক নেস্টেড লুপ থাকে তবে কোডটি ভাল লাগবে না।

সমস্ত লুপগুলি ভাঙার অন্য কোনও উপায় নেই? (দয়া করে ব্যবহার করবেন না goto stmt।)

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // both of the loops need to break and control will go to stmt2
       }
   }

}

stmt2

4
লুপটি শুরু হওয়ার আগে আপনি ইনট আই এবং ইনট জে চেষ্টা করতে পারেন এবং তারপরে শর্তে তাদের 1001 তৈরি করে লুপটি পরেরটি পুনরাবৃত্তি করবে না।
খুররম ইজাজ

উত্তর:


46

ব্যবহার:

if (condition) {
    i = j = 1000;
    break;
}

50
কাজ করে, তবে কুরুচিপূর্ণ এবং সাধারণ নয়। কেউ যদি সীমাটি 2000-এ পরিবর্তন করেন (ধরুন কোডটি দীর্ঘতর, সুতরাং আপনি অবিলম্বে এটি লক্ষ্য করবেন না)?
ugoren

4
@ ইউগোরেন এটি তখন খুব সহজ। আপনি যদি const int count =1000 বিশ্বব্যাপী সূচনাতে একটি ব্যবহার করেন । বা #defineম্যাক্রো হিসাবে
লাক্সিথ

4
@ ইউগোরেন যেমন উল্লেখ করেছেন, এটি কোনও সাধারণ সমাধান নয়। যেহেতু এই প্রশ্নের জন্য এটি প্রথম গুগল হিট, তাই সাধারণ সমাধানটি নির্বাচন করা যদি ভাল হত। ভাল লোকেরা যাইহোক # 2 পরীক্ষা করে দেখতে অভ্যস্ত।
BeeOnRope

4
আমার ধারণা কেবলমাত্র i = 1000 দরকার?
পিটার উ

191

না, একটি দিয়ে মজা নষ্ট করবেন না break। এটির শেষ অবধি বৈধ ব্যবহার goto;)

এটি না হলে আপনি গভীর নেস্টেড লুপগুলি ভাঙ্গতে পতাকা ব্যবহার করতে পারেন।

নেস্টেড লুপটি ভেঙে ফেলার আরেকটি পদ্ধতি হ'ল উভয় লুপকে আলাদা ফাংশনে ফ্যাক্ট করা এবং আপনি যখন প্রস্থান করতে চান তখন সেই ফাংশন থেকে ফিরে আসুন।

সংক্ষেপিত - নেস্টেড লুপগুলি ভেঙে ফেলার জন্য:

  1. ব্যবহার goto
  2. পতাকা ব্যবহার করুন
  3. ফাংশন আউট আলাদা ফাংশন কল মধ্যে লুপ

এখানে xkcd সহ প্রতিহত করতে পারেনি :)

এখানে চিত্র বর্ণনা লিখুন

সূত্র

গোটোকে ক্ষতিকারক হিসাবে বিবেচনা করা হয় তবে মন্তব্যে অনেকেই পরামর্শ দেন যে এটি হওয়ার দরকার নেই। যদি বিবেচনা করে ব্যবহার করা হয় তবে এটি দুর্দান্ত সরঞ্জাম হতে পারে। মডারেটে ব্যবহৃত যে কোনও জিনিস মজাদার।


30
আপনি এখানে যেমন পাবেন ঠিক তেমন পরিষ্কারই আছে G প্রস্থান ভেরিয়েবলটি 1000 এ সেট করা আরও ক্লডজি।
correnos

4
আমি যুক্ত করতে চাই যে গোটোস স্পষ্টতই খারাপ নয়, সেগুলি কেবল মন্দ জন্য ব্যবহার করা যেতে পারে। আমি দেখতে পাচ্ছি যে এখানে বেশ কয়েকটি কেস রয়েছে, উদাহরণস্বরূপ এটি, যেখানে এগুলি সেরা সমাধান। "গোটোস ব্যবহার করবেন না" একটি ভাল শুরু, তবে আমি মনে করি দক্ষতার পরবর্তী ধাপটি আপনাকে "দীর্ঘ-পরিসরের গোটোস ব্যবহার করবেন না" অনুমতি দেয়।
Aatch

4
আমি এটির সাথে একমত হতে চাই: "একটি কার্যকারিতা তৈরির ফলে স্ট্যাক পয়েন্টারকে যোগ / বিয়োগের পরিমাণে ঘনিষ্ঠ পরিমাণে ফলাফল পাওয়া যায়"। যদি কোনও স্থানীয় (স্থিতিশীল) ফাংশন থাকে যা প্রোগ্রাম প্রবাহের কেবলমাত্র এক পর্যায়ে ডাকা হয় তবে যে কোনও অর্ধ-শালীন সংকলক এটিকে ইনলাইন করবে এবং ফলাফল কোডটি মূলত গোটোর মতোই হয় the এটি কোনও সংকলকের পক্ষে সম্ভবত সবচেয়ে সহজ অপ্টিমাইজেশন কেস।
DrV

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

4
+1 এবং বিবৃতি (এ যাবেন ডোনাল্ড ই Knuth এর স্ট্রাকচার্ড প্রোগ্রামিং wiki.c2.com/?StructuredProgrammingWithGoToStatements ) Dijkstra ব্যালেন্স একটি আকর্ষণীয় নিবন্ধ।
কিমিপ্যাপ্লান

41
bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
    for (int j = 0; (j < 1000) && !stop; j++)
    {
        if (condition)
            stop = true;
    }
}

সমাধান এখনও বিরতিতে উভয় ভেরিয়েবলকে বৃদ্ধি করে যা সমস্যার কারণ হতে পারে
TheSola10

8
"সেট করা = সত্য" সেট করতে পারেন কেউ; এবং তারপরে "ব্রেক;" তারপরে, ভিতরে "শেষে" শেষে "লুপের জন্য," যদি (স্টপ) বিরতি দেয়; "।
জেফ গ্রিগ

আমি মনে করি এটি সবচেয়ে মার্জিত অ- gotoসমাধান non এটা তোলে সীমা বুদ্ধিমান প্রয়োজন হয় না iএবং jশর্ত মধ্যে। আমি if (stop) break;অভ্যন্তরীণ লুপটি স্থাপনের ধারণাটি পছন্দ করি যা এটি breakসেট করার পরে নিজেই পারে stop
উইলিস ব্ল্যাকবার্ন

35

একটি উপায় হ'ল সমস্ত নেস্টেড লুপগুলিকে একটি ফাংশনে রাখা এবং সমস্ত লুপগুলি ভেঙে ফেলার প্রয়োজনের অভ্যন্তরের সবচেয়ে লুপ থেকে ফিরে আসা।

function() 
{    
  for(int i=0; i<1000; i++)
  {
   for(int j=0; j<1000;j++)
   {
      if (condition)
        return;
   }
  }    
}

4
আমার জন্য সেরা সমাধানটি মনে হচ্ছে
লুকা স্টেব

21

আমি মনে করি gotoসমস্যার সমাধান হবে

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; j++) {
        if (condition) {
            goto end;
        }
    }
}

end:
stmt2 

 

@chikuba আমি থেকে উত্তর পেয়েছিলাম cprogramming.com/tutorial/goto.html এবং আপনার উত্তর পোস্ট করা হয় যখন আমি একই জিনিস না না করছি কেন আমি আপনার পোস্ট দেখতে
Renjith কে এন

17

আপনার যদি বুলিয়ান ভেরিয়েবলের দরকার হয়, আপনি যদি এটি পড়তে চান তবে:

bool broke = false;
for(int i = 0; i < 1000; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
  if (broke)
    break;
}

আপনি যদি এটি কম পাঠযোগ্য হতে চান তবে আপনি বুলিয়ান মূল্যায়নে যোগদান করতে পারেন:

bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
}

চূড়ান্ত উপায় হিসাবে আপনি প্রাথমিক লুপটি অবৈধ করতে পারেন:

for(int i = 0; i < size; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      i = size;
      break;
    }
  }
}


4

সতর্কতা: এই উত্তরটি সত্যই একটি অস্পষ্ট নির্মাণ দেখায়।

আপনি যদি জিসিসি ব্যবহার করে থাকেন তবে এই লাইব্রেরিটি দেখুন । পিএইচপি-র মতো, breakআপনি প্রস্থান করতে চান এমন নেস্টেড লুপের সংখ্যা গ্রহণ করতে পারে। আপনি এই জাতীয় কিছু লিখতে পারেন:

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // break two nested enclosing loops
            break(2);
       }
   }
}

এবং হুডের নিচে এটি প্রকৃতপক্ষে ব্যবহার করছেgoto :)
জ্যাকোবাক

@ আইএক্স 3 আমি যদি ইনলাইন এসেম্বেলার এবং জ্যাম্প নির্দেশিকাটি সহায়তা করে তবে এটি ব্যবহার করতে পারি।
দাবলার

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


3

আপনার যদি i এবং j এর মান প্রয়োজন হয় তবে এটি অন্যের চেয়ে কম পারফরম্যান্স সহ কাজ করা উচিত

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}

নোট করুন যে শর্তটি যদি নির্ভর করে jতবে শর্তটির মান এইভাবে কাজ করার জন্য কোনও উপায়ে সংরক্ষণ করতে হবে।
সুপারবিসাইডম্যান

4
আপনি ঠিক বলেছেন তবে বিরতির পরে , এর মান পরিবর্তন হয় না এবং শর্তের মানও তাই হয়।
আলী ইরেন ইলিক

এটি একটি ভাঙ্গা সমাধান এবং সাধারণভাবে বৈধ নয়। হয় j এর লুপের বাইরে সংজ্ঞায়িত করা হয়নি বা অভ্যন্তরীণ লুপের প্রথম পুনরাবৃত্তির পরে বাইরের লুপটি সর্বদা বিরতিতে for (int i = 0; i < 1000; i++) { for (int j = 0; j < 1000; j++) { if (workComplete[i][j]) break; /* do work */ workComplete[i][j] = true; } if (workComplete[i][j]) break; ... }চলেছে ।
চই টি. রেক্স

0

দুটি ভিন্ন লুপের জন্য লুপের জন্য একটি লুপ এবং একটি ম্যানুয়াল লুপের মধ্যে কোডটি রিফ্যাক্টর করার জন্য একটি ভিন্ন পদ্ধতি। এইভাবে ম্যানুয়াল লুপের বিরতি বাইরের লুপের জন্য প্রযোজ্য। আমি এটি একবার গস-জর্ডান নির্মূলের ক্ষেত্রে ব্যবহার করেছি যার প্রক্রিয়াটির জন্য তিনটি নেস্টেড লুপ প্রয়োজন।

for (int i = 0; i < 1000; i++)
{
    int j = 0;

MANUAL_LOOP:;

    if (j < 1000)
    {
       if (condition)
       {
           break;
       }

       j++;
       goto MANUAL_LOOP;
    }
}

আপনি যদি যাচ্ছেন goto, কেন কেবল gotoলুপের বাইরে নেই?
উইলিস ব্ল্যাকবার্ন

0

আমি নোট করেছি যে প্রশ্নটি সহজভাবে, "সমস্ত লুপগুলি ভাঙার কোনও উপায় আছে কি?" আমি কোনও যোগ্যতা দেখতে পাচ্ছি না তবে এটি এমনটি হবে না goto, বিশেষত ওপি ভাল উপায়ের জন্য জিজ্ঞাসা করেনি । সুতরাং, কিভাবে আমরা longjmpভিতরের লুপ আউট? :-)

#include <stdio.h>
#include <setjmp.h>

int main(int argc, char* argv[]) {
  int counter = 0;
  jmp_buf look_ma_no_goto;
  if (!setjmp(look_ma_no_goto)) {
    for (int i = 0; i < 1000; i++) {
      for (int j = 0; j < 1000; j++) {
        if (i == 500 && j == 500) {
          longjmp(look_ma_no_goto, 1);
        }
        counter++;
      }
    }
  }
  printf("counter=%d\n", counter);
}

setjmpফাংশন দুইবার ফেরৎ। প্রথমবার, এটি 0 প্রদান করে এবং প্রোগ্রামটি লুপগুলির জন্য নেস্টেড কার্যকর করে। তারপরে যখন উভয় iএবং j500 হয়, এটি কার্যকর করে longjmp, যার ফলে setjmp1 টির সাথে আবার ফিরে আসে লুপটি এড়িয়ে যায়।

কেবল আপনাকে longjmpনেস্টেড লুপগুলি থেকে বের করে দেবে না , এটি নেস্টেড ফাংশনগুলির সাথেও কাজ করে!



-3
for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
       if(condition) {
          func(para1, para2...);
          return;
       }
    }
}

func(para1, para2...) {
    stmt2;
}

সুতরাং মূলত আপনি বলছেন যে এটির (1) অতিরিক্ত ফাংশন কল করা উচিত এবং তারপরে (2) conditionমিথ্যা হয়ে যাওয়ার পরে বাকি সময়টির জন্য স্পিন করা উচিত । ওহ, এবং দ্বিতীয় লুপ চিরকালের জন্য চলবে কারণ এটি ij
উফসের

-4
i = 0;

do
{
  for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here!
  {
     if (condition)
     {
       break;
     }
  }

  ++i;

} while ((i < 1000) && !condition);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.