2008-10-28 21 views
12

Nếu, như tôi, bạn rùng mình tại địa điểm của vòng lặp while (True), thì bạn cũng phải suy nghĩ thật lâu và cách tốt nhất để cấu trúc lại nó. Tôi đã nhìn thấy một số triển khai khác nhau, không có gì thực sự tốt hơn so với bất kỳ khác, chẳng hạn như sự kết hợp ủy nhiệm & hẹn giờ.Tái cấu trúc tốt nhất cho vòng lặp Trong khi (Đúng)

Vì vậy, cách tốt nhất bạn đã đưa ra hoặc nhìn thấy để cấu trúc lại vòng lặp Trong khi (True) đáng sợ là gì?

Chỉnh sửa: Như một số nhận xét đã đề cập, mục đích của tôi là đặt "vòng lặp vô hạn", chẳng hạn như chạy dịch vụ kiểu Windows nơi điều kiện dừng duy nhất là OnStop hoặc ngoại lệ gây tử vong.

+0

Tôi nên nói tốt hơn, và nghĩ về việc quay trở lại để làm điều đó, nhưng đó là một quá trình học tập liên tục, vì vậy tôi quyết định để lại câu hỏi như là một lời nhắc nhở cho bản thân mình. :) –

+0

Nếu bạn "sợ" trong khi (đúng), bạn phải viết các thuật toán rất đơn giản.Hầu hết các thuật toán tiên tiến yêu cầu các vòng lặp với nhiều điều kiện thoát. Cách tự nhiên nhất để làm điều này là có vòng lặp vô hạn bên ngoài và sau đó nhiều điều kiện thoát ra khỏi vòng lặp. Sử dụng các vòng lặp hoặc điều kiện trong khi hoạt động tốt nhất khi bạn chỉ có một điều kiện thoát. Mặc dù đó là trường hợp phổ biến nhất, nó hầu như không phải là tình hình phổ quát. –

Trả lời

21

Chúng ta có thực sự cần phải cấu trúc lại khi (đúng) vòng? Đôi khi nó là một tiêu chuẩn mã hóa và hầu hết các nhà phát triển đã quen với cấu trúc này. Nếu bạn phải suy nghĩ kỹ về cách cấu trúc lại mã này, bạn có chắc là nên tái cấu trúc nó không?

Goto từng là cừu đen theo tiêu chuẩn mã hóa. Tôi đã gặp các thuật toán trong đó goto làm cho mã dễ đọc hơn và ngắn hơn. Đôi khi nó không có giá trị để tái cấu trúc (hoặc tốt hơn để sử dụng goto).

Mặt khác, bạn có thể tránh trong khi (đúng) phần lớn thời gian.

22

Có gì đáng sợ về điều đó? Hãy thử tìm một điều kiện ngắt chung và cấu trúc lại nó làm đầu của vòng lặp. Nếu điều đó là không thể - tốt.

+0

Yup, yust ý tưởng của tôi ;-). –

+4

Hoặc refactor để nó là ở cuối và tận dụng lợi thế của "làm trong khi". – Torlack

+0

@Torlack - harhar! –

12

Thay thế đúng với điều kiện bạn định sử dụng để thoát khỏi vòng lặp.

Trong trường hợp của một dịch vụ hoặc nền chủ đề, bạn có thể sử dụng:

volatile bool m_shutdown = false; 
void Run() 
{ 
    while (!m_shutdown) 
    { ... } 
} 
+0

Đôi khi mọi người làm điều này cho các dịch vụ, nơi thực hiện có nghĩa là để tiếp tục vô thời hạn và chỉ bị hỏng OnStop hoặc ngoại lệ. Vì vậy, không có điều kiện. – Grank

+1

Tôi nghĩ rằng câu hỏi được nhắm mục tiêu nhiều hơn vào bán chuẩn của vòng lặp vô hạn khi bạn đang thực sự có ý định làm điều đó một số lần hữu hạn (bỏ qua những thứ như chủ đề vv). –

+0

Trong đó, có "BEGIN X WHILE Y REPEAT" nơi điều kiện nằm ở giữa vòng lặp. Kiểu cấu trúc vòng lặp này không dễ dàng chuyển đổi thành vòng lặp "while {}" hoặc "do {} while" truyền thống hơn. – Torlack

3

errr, trở thành một refactoring .....

  • Thay Infinite Loop với Infinite Đệ quy: -)

tốt, nếu bạn có một ngôn ngữ hỗ trợ Tail gọi ....

13

Khi tôi gặp một while (true) vòng lặp, mà nói với tôi hoặc

  1. điều kiện phá vỡ không dễ dàng kiểm tra ở phía trên (hoặc dưới) của vòng lặp,
    • có nhiều điều kiện nghỉ ngơi,
    • hoặc trình lập trình trước quá lười để xác định vòng lặp chính xác.

1 và 2 có nghĩa là bạn cũng có thể gắn bó với while (true). (Tôi sử dụng for(;;), nhưng đó là một điều phong cách theo ý kiến ​​của tôi.) Tôi với một poster khác, tại sao lại sợ điều này? Tôi dread tortored loops nhảy qua hoops để có được vòng lặp cán "đúng".

+0

Câu trả lời thường là 3! – DaveF

3

Nếu bạn muốn nó tiếp tục vô thời hạn cho đến khi phá thai toàn bộ luồng chương trình, tôi không thấy điều gì sai trái trong khi (đúng). Tôi đã gặp nó gần đây trong một dịch vụ thu thập dữ liệu .NET kết hợp trong khi (true) với thread.sleep để thức dậy mỗi phút và thăm dò ý kiến ​​dịch vụ dữ liệu của bên thứ ba cho các báo cáo mới. Tôi xem xét tái cấu trúc nó với một bộ đếm thời gian và một đại biểu, nhưng cuối cùng đã quyết định rằng đây là phương pháp đơn giản và dễ đọc nhất. 9 lần trong số 10, đó là một mùi mã rõ ràng, nhưng khi không có điều kiện thoát, tại sao mọi thứ trở nên khó khăn hơn?

7

Tình huống "chạy mãi mãi" đôi khi là một phần của máy trạng thái lớn hơn. Nhiều thiết bị được nhúng (với vòng lặp chạy vĩnh viễn) không thực sự chạy mãi mãi. Họ thường có một số chế độ hoạt động và sẽ trình tự trong số các chế độ đó.

Khi chúng tôi xây dựng bộ điều khiển bơm nhiệt, có chế độ tự kiểm tra (POST) chạy trong một thời gian ngắn. Sau đó, có một chế độ thu thập môi trường sơ bộ cho đến khi chúng tôi tìm ra tất cả các khu vực và bộ điều nhiệt và những gì không.

Một số kỹ sư đã tuyên bố rằng điều tiếp theo là vòng lặp "chạy vĩnh viễn". Nó không thực sự đơn giản như vậy. Nó thực sự là một số chế độ hoạt động mà lộn và trôi. Có sưởi ấm, và rã đông, và làm mát, và chạy không tải, và những thứ khác.

Tùy chọn của tôi là xử lý vòng lặp "mãi mãi" thực sự chỉ là một chế độ hoạt động - có thể có những người khác tại một số thời điểm trong tương lai.

someMode= True 
while someMode: 
    try: 
     ... do stuff ... 
    except SomeException, e: 
     log.exception(e) 
     # will keep running 
    except OtherException, e: 
     log.info("stopping now") 
     someMode= False 

Trong một số trường hợp, không có gì chúng tôi đã thấy cho đến nay bộ someMode-False. Nhưng tôi thích giả vờ rằng sẽ có một sự thay đổi chế độ trong một số phiên bản tương lai.

11

Tại sao lại là refactor? Và cái gì là "đáng sợ" về cấu trúc này? Nó được sử dụng rộng rãi và được hiểu rõ.

Nếu nó không bị hỏng, đừng sửa chữa.

1

Tôi không quan tâm khi vòng lặp vô hạn được chứa trong cửa sổ và chết với cửa sổ.

Hãy suy nghĩ về cuộc thăm dò Hasselhoff.

7
#define ever 1 
for (;ever;) 

?

Meh, chỉ để lại nó như thế nào nó là, while (true) có lẽ là rõ ràng như bạn đang đi để có được ..

+0

Tôi ghét việc lạm dụng các "vòng" như vậy. Có một ngữ nghĩa mà vòng lặp "for" được thiết kế, (về bản chất là từ ngữ nghĩa đến từ ngữ nghĩa) và tôi nghĩ chúng ta nên gắn bó với điều đó. Những gì bạn đang làm ở đây là buộc một ngữ nghĩa "trong khi" vào từ khóa "for". Ít nhất #define làm cho nó có thể chấp nhận được. –

+5

nếu chúng ta đi xấu xí, tại sao không "#define FOREVER trong khi (1)" hoặc một cái gì đó như thế :) –

53

sở thích của tôi sẽ là

start: 

    // code goes here 

goto start; 

Điều này thể hiện rõ ràng nhất ý định. Chúc may mắn vượt qua các tiêu chuẩn mã hóa của bạn. (Tự hỏi bao nhiêu nghiệp chướng này sẽ khiến tôi mất chi phí).

+0

Tôi đã bỏ phiếu mà chỉ vì nó đã cho tôi một tiếng cười tốt! –

+1

Tôi đã bình chọn nó, bởi vì đôi khi goto * là * chấp nhận được! –

+9

Tôi đã bỏ phiếu vì chương trình I trong Assembly –

-2
void whiletrue_sim(void) 
    { 
    //some code 
    whiletrue_sim(); 
    } 

Cảnh báo: Ngăn xếp của bạn có thể tràn, phụ thuộc vào ngôn ngữ, trình tối ưu hóa và các thứ khác.

+0

Trong khi khối mã này có thể trả lời câu hỏi, tốt nhất là bạn có thể cung cấp giải thích một chút về lý do tại sao nó thực hiện như vậy. – Rakete1111

+0

chỉ cần đọc mã. Tôi xấu với các từ và nếu bạn không hiểu mã đơn giản này, tôi không thể giải thích nó tốt hơn. Nó chỉ để ngăn xếp của bạn có thể tràn, phụ thuộc vào ngôn ngữ, trình tối ưu hóa hoặc cách trình thông dịch của bạn hoạt động. – 12431234123412341234123

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