2011-12-13 53 views
8

Ai đó có thể cho tôi biết cách phá vỡ vòng lặp chính khi tôi có vòng lặp lồng nhau không?
Ví dụ *:Phá vỡ vòng lặp lồng nhau

/*Main loop*/ 
for(int y = 0; y < 100; y+=10) 
{ 
    /*Sub loop*/ 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 60) 
     { 
      //Break the main loop 
     } 
    } 
} 

* Mã này không làm gì cả, nó chỉ là một ví dụ

tôi nên đặt gì vào vị trí của "Break vòng lặp chính" bình luận? Trong java có các nhãn mà tôi có thể phá vỡ (khi tôi đặt nhãn cho vòng lặp chính có tên là "MainLoop", tôi có thể viết "ngắt MainLoop;" và nó sẽ hợp lệ), nhưng tôi có thể làm gì ở đây?

Cảm ơn lời khuyên!

+1

nếu có thể, đặt điều này bên trong một phương pháp riêng biệt mà bạn có thể quay trở lại, điều đó sẽ làm ngắn mạch các vòng lặp. –

+8

GOTO! Này, chờ đã - các bạn đi đâu? Xin chào? –

Trả lời

7

Sử dụng một lá cờ để báo hiệu chấm dứt:

for(int y = 0; y < 100; y+=10) 
{ 
    bool flag = false; 
    for(int x = 0; x < 100; x += 10) 
    { 
     if (x == 56) 
     { 
      flag = true; 
      break; 
     } 
    } 

    if(flag) break; 
} 
+1

Thats một cách tiết để làm điều đó. Bạn chỉ có thể kiểm tra cờ trong vòng lặp 'for' có điều kiện. – Jon

+0

Điều tuyệt vời về điều này là nó rất dễ hiểu đối với các lập trình viên khác: không có yếu tố bất ngờ. –

+0

@Jon, tôi không nghĩ rằng đó là một phong cách sạch sẽ để có nhiều hơn một điều kiện bên trong một cho. – Tudor

10
  • Refactor do đó bạn không cần phải thoát khỏi vòng lặp lồng nhau theo cách này.
    Sử dụng return thường có thể bằng cách đặt các vòng vào một chức năng riêng biệt.
  • sử dụng goto.
  • Sử dụng một lá cờ (xấu xí)
+2

-1 cho 'goto' ... – IAbstract

+2

Không ai có thể sử dụng' goto' bằng ngôn ngữ cấp cao. – Jon

+4

IMO flag-break-checkflag-break thậm chí còn tệ hơn goto. Nhưng tất nhiên refactoring là sự lựa chọn ưa thích nếu có thể. – CodesInChaos

3

thường của nó tốt hơn để đưa điều này vào một chức năng riêng biệt và sau đó làm một 'trở lại'

void loop_de_loop() 
{ 
    for(int y = 0; y < 100; y+=10) 
    { 
     /*Sub loop*/ 
     for (int x = 0; x < 100; x += 10) 
     { 
      if(x == 56) 
      { 
       return; 
      } 
     } 
    } 
} 
+0

Trong vòng lặp lồng nhau thực tôi đang tính toán một số điều. Nếu tôi phải chuyển chúng sang một phương pháp thì nó sẽ thực sự xấu xí! – Bankin

+0

phụ thuộc vào cách bạn làm điều đó .... thường những điều này có được lộn xộn bởi vì mọi người có rất nhiều biến và đã không gói gọn chúng vào một cấu trúc.Lý tưởng nhất là bạn kết thúc với rất nhiều chức năng hoạt động trên cấu trúc. (OO được đơn giản hóa). –

4

Một số người sẽ bắn tôi cho thấy việc sử dụng các goto tuyên bố, nhưng phá vỡ ra nhiều vòng là một trong những nơi nó có thể rất hữu ích (và hiệu quả):

/*Main loop*/ 
for(int y = 0; y < 100; y+=10) 
{ 
    /*Sub loop*/ 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 56) 
     { 
      goto MainLoopDone; 
     } 
    } 
} 

MainLoopDone: 
// carry on here 
+0

GOTO là khủng khiếp – MethodMan

+4

Họ đang khủng khiếp khi được sử dụng bởi các lập trình viên trẻ và kết quả là mã spaghetti. Là một nhà phát triển, bạn nên sử dụng các công cụ có sẵn cho bạn, và goto là cách hiệu quả nhất để thoát ra khỏi một số vòng lồng nhau. –

+0

Tôi đồng ý với những điều trước về mã spaghetti, tôi luôn sử dụng ngắt hoặc trả lại – MethodMan

0
/*Main loop*/ 
for(int y = 0; y < 100; y+=10) 
{ 
    bool makeMeBreak = false; 

    /*Sub loop*/ 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 56) 
     { 

      //Break the main loop 
      makeMeBreak = true; 
      break; 
     } 
    } 
    if (makeMeBreak) break; 
} 
17

goto!

Tôi không hiểu meme liên tục này nói rằng goto được coi là "có hại". Khi được sử dụng đúng cách, nó rất mạnh mẽ, và đây là một trường hợp như vậy.

+0

Một ngày nọ, khi ai đó đưa cho bạn mã FORTRAN ba thập niên đã bị rải rác với các GOTO kém viết và bảo bạn sửa lỗi, và bạn phát hiện ra rằng nó là _impossible_ để cấu trúc lại, bạn sẽ hiểu. Các lập trình viên giỏi nhất có thể làm phép thuật với GOTO. Điều tồi tệ nhất có thể làm điều ác lớn. –

+1

Các lập trình viên giỏi nhất có thể sử dụng 'goto' mà không gây ra bất kỳ đau buồn nào, và tạo ra mã hiệu quả nhất trong tiến trình. –

+1

+1, phá vỡ vòng lặp lồng nhau là một trong số ít (chỉ?) Sử dụng được chấp nhận của goto imo. Nhiều, sạch hơn nhiều so với sử dụng một lá cờ. –

2

Tôi không biết nếu có cách nào thoát ra khỏi vòng lặp lồng nhau trong C#, nhưng cho phép tôi đề xuất giải pháp thay thế.

Bạn có thể ném vòng lặp chính vào một hàm và trả về hàm đó. Bạn có thể return false; để cho biết thời gian nghỉ sớm và return true; để cho biết vòng lặp đã đi qua, nếu điều đó quan trọng.

0

Không có câu trả lời chung chung nào tốt. 'Cách đúng' phụ thuộc vào vấn đề thực sự. Cách tốt nhất có thể là đặt vòng lặp ngoài trong một hàm và sau đó sử dụng return; để thoát khỏi nó. Nó có thể là x=100; y=100;. Nó có thể là done=true;. Heck, thậm chí có thể là goto (đùa).

2

Flags, như đề xuất trong các ý kiến, có lẽ là phương pháp tốt nhất:

boolean someFlag = true; 

for(int y = 0; i < 100 && someFlag; y += 10) { 
    for(int x = 0; x < 100 && somFlag; x += 10) { 
    if(x == 56) 
     someFlag = false; 
    } 
} 
+0

Nó chỉ ngắn gọn bởi vì không có mã sau vòng lặp bên trong và sau if. Với mã đó, bạn cần thêm hai ngắt và kiểm tra. – CodesInChaos

0

tôi không khuyến khích nhưng bạn có thể sử dụng goto. Xem this.

public class GotoTest1 
{ 
    static void Main() 
    { 
     int x = 200, y = 4; 
     int count = 0; 
     string[,] array = new string[x, y]; 

     // Initialize the array: 
     for (int i = 0; i < x; i++) 

      for (int j = 0; j < y; j++) 
       array[i, j] = (++count).ToString(); 

     // Read input: 
     Console.Write("Enter the number to search for: "); 

     // Input a string: 
     string myNumber = Console.ReadLine(); 

     // Search: 
     for (int i = 0; i < x; i++) 
     { 
      for (int j = 0; j < y; j++) 
      { 
       if (array[i, j].Equals(myNumber)) 
       { 
        goto Found; 
       } 
      } 
     } 

     Console.WriteLine("The number {0} was not found.", myNumber); 
     goto Finish; 

    Found: 
     Console.WriteLine("The number {0} is found.", myNumber); 

    Finish: 
     Console.WriteLine("End of search."); 


     // Keep the console open in debug mode. 
     Console.WriteLine("Press any key to exit."); 
     Console.ReadKey(); 
    } 
} 
/* 
Sample Input: 44 

Sample Output 
Enter the number to search for: 44 
The number 44 is found. 
End of search. 
*/ 

Không nên vì nó làm cho luồng khó hiểu hơn. Tùy chọn khác của khóa học là để thiết lập một số cờ trong vòng lặp bên trong và kiểm tra nó trong vòng lặp bên ngoài, tôi giảm giá đó là nó rõ ràng và giả sử bạn biết nó anyway .. :)

0

Vì, như bạn đã đề cập, có không có nhãn trên lệnh break, bạn có thể làm một cái gì đó như thế này:

/*Main loop*/ 
bool fFound; 
for(int y = 0; y < 100 && !fFound; y+=10) 
{ 
    /*Sub loop*/ 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 56) 
     { 
      //Break the main loop 
      fFound = true; 
      break; //Break inner loop 
     } 
    } 
} 
0

như những người khác đã nói, "đúng" câu trả lời phụ thuộc vào vấn đề bạn đang giải quyết. Nếu bạn có thể, phá vỡ nó thành những mảnh nhỏ hơn là con đường ưa thích. Một cái gì đó dọc theo mô hình này:

object MainLoop() 
{ 
    object result = null; 
    for(int y = 0; y < 100; y+=10) 
    { 
     result = SubLoop(y); 
     if (result != null) 
     { 
      break; 
     } 
    } 
    return result; 
} 

object SubLoop (int y) 
{ 
    object result = null; 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 56) 
     { 
      result = objectInstance; 
      break; 
     } 
    } 
    return result; 
} 

Theo tôi, đó là xấu xí đến mức độ khác nhau để có nhiều tuyên bố trở về từ một hàm duy nhất, sử dụng cờ thêm, hoặc (rùng mình) sử dụng của goto. Nhưng, đôi khi một trong số đó là cần thiết.

Chỉnh sửa: Điều này thể hiện bằng cách sử dụng phương thức này để trả về một đối tượng hữu ích, bạn sẽ có "Khách hàng" hoặc "IDataAccess" hoặc "bool" hoặc thứ gì đó không phải là "đối tượng". điều này thật.

0

Tôi đã sử dụng LINQ để thu thập các đối tượng thú vị trước rồi thực hiện các thao tác trên các kết quả của truy vấn LINQ. Qua đó loại bỏ các vòng lặp lồng nhau và thay thế bằng một vòng lặp.

Các vấn đề liên quan