Thuật ngữ nào cho vòng lặp trong khi (đúng) có vòng lặp với bên trong? [đóng cửa]


24

Giả sử tôi có một vòng lặp trong C ++ hoặc C # giống như sau:

while( true ) {
    doSomething();
    if( condition() ) {
        break;
    }
    doSomethingElse();
}

Điều này thường được gọi là "vòng lặp vô hạn". Tuy nhiên, nó không phải là vô hạn về mặt kỹ thuật - nó sẽ dừng lại khi điều khiển chảy qua break.

Thuật ngữ cho vòng lặp như vậy - có câu lệnh điều khiển vòng lặp "vòng lặp mãi mãi" và "phá vỡ" bên trong là gì?


22
Tôi không nghĩ có một thuật ngữ đặc biệt.
ChrisF

2
Có bất kỳ đảm bảo rằng kiểm soát sẽ bao giờ chảy qua phá vỡ? Trong ví dụ đó, điều gì sẽ xảy ra nếu condition()luôn trả về false? Tôi muốn nói rằng đó là một vòng lặp vô hạn với các khoảng nghỉ có điều kiện.
JohnL

1
Ngay cả khi không có a break, vòng lặp không phải là vô hạn ( kill, ctrl-alt-del, rút ​​phích cắm ...). Vậy tại sao phải bận tâm với các chi tiết thuật ngữ?
mouviciel

5
"Thuật ngữ gì?" - "Đây thường được gọi là vòng lặp vô hạn". Đó là câu trả lời của bạn ngay tại đó. Bạn rõ ràng không hài lòng với thuật ngữ này, nhưng điều đó không làm mất đi thực tế rằng các ngôn ngữ (tự nhiên) là mô tả. "Thuật ngữ cho X" là bất cứ điều gì mọi người đang sử dụng, không phải là những gì họ nên sử dụng.
MSalters

5
Câu hỏi này dường như lạc đề vì đây là câu hỏi "tên điều đó". "Đặt tên cho điều đó" là những câu hỏi tồi vì cùng một lý do "xác định chương trình truyền hình, phim hoặc cuốn sách khó hiểu này bởi các nhân vật hoặc câu chuyện của nó" là những câu hỏi tồi: bạn không thể Google chúng, chúng không thực tế theo bất kỳ cách nào, chúng không giúp đỡ ai khác và cho phép họ mở ra cánh cửa cho việc hỏi các loại câu hỏi ngoài lề khác. Xem blog.stackoverflow.com/2012/02/lets-play-the-guessing-game
gnat

Câu trả lời:


24

Nghiên cứu CS, giáo sư này đã dạy chúng tôi rằng có các vòng kiểm tra trước ( while(cond) {}), vòng kiểm tra sau ( do {} while(cond);) và vòng kiểm tra giữa . (Tôi có thể đã dịch sai sang tiếng Anh, nhưng bạn hiểu ý.)

C và C ++ không có cái sau (ISTR Ada có nó, BICBW), do đó, cấu trúc của bạn được sử dụng cho điều đó trong C và C ++.


1
Vâng, Ada có điều này:loop ... exit when condition; ... end loop;
Keith Thompson

@Keith: Cảm ơn bạn đã xác nhận! Đã gần 20 năm kể từ khi tôi thực hiện một số Ada.
sbi

1
Đối với những gì nó có giá trị, tôi đã là một lập trình viên chuyên nghiệp trong hơn 20 năm (và một người có sở thích lâu hơn thế) và tôi chưa bao giờ nghe những điều khoản đó.
off1

Về bản dịch - Tôi nghĩ "in" thường phù hợp hơn khi "pre" và "post" được sử dụng, ví dụ "preorder / postorder / inorder cây traversal".
Sồi

1
Thuật ngữ tôi lớn lên là "vòng lặp giữa lối ra." Tôi đã làm việc trong một vài ngôn ngữ khác nhau với sự hỗ trợ rõ ràng cho các vòng lặp giữa lối ra.
mjfgates

13

Khóa học đầu tiên về CS tại Stanford ( Phương pháp lập trình của Mehran Sahami ) đề cập đến điều này như một vòng lặp và một nửa . Và nó không hẳn là thực hành lập trình xấu. Hãy xem xét ví dụ này về việc thu thập dữ liệu đầu vào của người dùng (được lấy từ The Art and Science of Java bởi Eric Roberts , nơi Roberts cũng gọi đó là một vòng lặp và một nửa ):

prompt user and read in the first value
while (value != sentinel) {
    process the data value
    prompt user and read in a new value
}

Và sau đó, điều tương tự đã được giải quyết bằng cách sử dụng vòng lặp và một nửa ý tưởng để tránh mã trùng lặp:

while (true) {
    prompt user and read in a value
    if (value == sentinel) break;
    process the data value
}

10

Thiếu một tên chính thức, tôi sẽ gọi nó là Broken Loop . Sự mơ hồ của thuật ngữ này được dự định, vì một sự phá vỡ ở giữa một vòng lặp là một chút ô uế, gần giống như a goto.


Tôi muốn nói, tệ hơn nhiều so với một goto. Tôi thà nhìn thấy một goto hơn là một điều kiện được xây dựng sai trong một vòng lặp như thế.
Brian Knoblauch

14
@Brian gì? Điều kiện 'đúng' làm cho nó rõ ràng và các vòng lặp như thế là thực sự phổ biến. Ví dụ: nếu bạn muốn thêm từng dòng của tệp vào danh sách, bạn phải thử đọc dòng (làm gì đó), dừng nếu thất bại (nếu ngắt điều kiện), nếu không hãy thêm nó vào danh sách và lặp lại (làm gì đó khác).
Craig Gidney

7
Không có gì sai khi phá vỡ ở giữa một vòng lặp. Nếu bạn cần thực hiện một số thao tác ở mỗi đầu chu kỳ, bạn sẽ phải sao chép mã hoặc nhét các thao tác này vào điều kiện. Hoặc là biến thể rõ ràng có nhược điểm. gotocũng có các ứng dụng hợp lệ, ví dụ: giả lập thử ... cuối cùng chặn trong C.
Malcolm

1
Malcolm: Vấn đề có thể xảy ra là trong quá trình đọc mã, khó thấy hơn khi nào và tại sao vòng lặp được thoát. Các vấn đề khác phát sinh khi bạn lồng hai hoặc nhiều vòng như vậy và muốn thoát ra khỏi vòng lặp bên ngoài dựa trên một điều kiện được tìm thấy trong vòng lặp bên trong.
user281377

Giả sử bạn có một vòng lặp sự kiện điều khiển một ứng dụng Xorg, như (bằng mã giả :) while(XEventGet(&ev) != NULL){ ... }, bạn sẽ tự nhiên muốn kiểm tra các khóa bên trong vòng lặp : if(ev.key == XK_q) break;. Làm như sau : while(XEventGet(&ev) != NULL && ev.key != XK_q){ ... }, xấu và khó đọc hơn là nghỉ giữa vòng. Thêm vào đó, nếu cái gì đó cần phải được thực hiện với giá trị trước khi nó có thể được kiểm tra thì sao? Bạn sẽ không nghiêm túc nhét tất cả những thứ đó vào trường hợp cơ sở của vòng lặp, phải không?
Braden hay nhất

8

Không có tên dứt khoát. Vòng lặp vô hạn là, tôi nghĩ, thuật ngữ thích hợp. Không có vòng lặp thực sự là vô hạn, nhưng điều này có tiềm năng là vô hạn một cách hiệu quả vì có thể nhánh chứa sự phá vỡ sẽ không bao giờ xảy ra.

Nếu bạn nói với ai đó "tạo một vòng lặp vô hạn và sử dụng dấu ngắt cho điều kiện X" và họ sẽ biết ý của bạn là gì. Nếu ai đó đang xem lại mã của bạn và không nói gì hơn "Tôi không thích vòng lặp vô hạn mà bạn đã viết", bạn sẽ biết họ đang nói về điều gì (tất nhiên trừ khi bạn có nhiều hơn một).


1
Nó không phải là một vòng lặp vô hạn; nó có một điều kiện chấm dứt được xác định rõ, giống như một whilevòng lặp thông thường và cách bạn thực hiện bằng chứng chấm dứt hoàn toàn giống nhau (tìm một số liệu giảm đơn điệu là một khởi đầu tuyệt vời).
Donal Fellows

8

Đó là một vòng lặp do-while với điều kiện ở sai vị trí.


2
Vâng, nó nên được viết: while (keep_ gửi) {doS Something (); if (condition) {keep_ gửi = false; } other {doS SomethingElse (); }}
Stephen Gross

10
vì vậy ... bạn đang nói rằng nếu bạn đang dạy một khóa học máy tính và muốn mô tả điều này, bạn sẽ nói "và bây giờ, chúng ta sẽ tìm hiểu về vòng lặp * do-while với điều kiện sai ở vị trí "? Nghe có vẻ giống như một ý kiến ​​tôn giáo hơn là một cái tên.
Bryan Oakley

5
@StephenGross Đoạn mã đó là một gợi ý khủng khiếp. Tái cấu trúc để đặt điều kiện thực tế trong định nghĩa vòng lặp, hoặc chỉ sử dụng breakhoặc continue. Tránh các giá trị canh gác bằng mọi giá, chúng chỉ là một phần trạng thái tùy ý để theo dõi về mặt tinh thần, điều đó che giấu mục đích của mã.
Izkata

2
Giá trị Sentinal là gotos chậm.
Winston Ewert

2
-1 vì là một weenie thoát đơn.
Donal Fellows

6

Tôi sẽ bỏ phiếu cho "vòng lặp vô điều kiện" , tương tự như "bước nhảy vô điều kiện". Nó minh họa chính xác những gì đang diễn ra (các vòng lặp mã vô điều kiện), không nói dối (không giống như "vòng lặp vô hạn").


1
Nhưng nó có một điều kiện chấm dứt; đó if/ breakở giữa là một phần của mô hình.
Donal Fellows

5

Thuật ngữ cho vòng lặp như vậy - có câu lệnh điều khiển vòng lặp "vòng lặp mãi mãi" và "phá vỡ" bên trong là gì?

Đó là một vòng lặp vô hạn với một điều kiện phá vỡ.

Tôi đồng ý với ammilind rằng nếu bạn muốn đặt cho nó một cái tên đặc biệt, bạn có thể gọi nó là Vòng lặp một phần vô hạn


1
Nó hoàn toàn không phải là vô hạn; điểm mà điều kiện chấm dứt được kiểm tra chỉ ở một nơi khác.
Donal Fellows

5

Trên Rosetta Code, mẫu đặc biệt này được mô tả là một vòng lặp N cộng với một nửa vòng lặp . Mặc dù nó không phải là thuật ngữ yêu thích của tôi, nhưng nó không khủng khiếp và rõ ràng là một mô hình hữu ích cho một số loại vòng. (Các lựa chọn thay thế là sao chép mã trước điều kiện - có khả năng khó khăn trong các chương trình thực - hoặc để tăng độ sâu lồng nhau của mã sau điều kiện trong khi thêm biến điều kiện vòng lặp; không cải thiện khả năng duy trì hoặc dễ hiểu của mã Lý do duy nhất để từ chối các cấu trúc như vậy là nếu một người khăng khăng viết các vòng lặp là không có giá trị break.)


4

Không có thuật ngữ tiêu chuẩn, nhưng tôi sẽ nói nó là vòng lặp một phần .

Vòng lặp này được sử dụng khi bạn muốn ngắt chỉ sau khi thực hiện một phần của vòng lặp lần cuối (tức là thực hiện một phần). Nó được sử dụng khi bạn không tìm thấy một tình huống phù hợp trong đó bạn có thể muốn phá vỡ toàn bộ vòng lặp .

Trong trường hợp này, bạn muốn phá vỡ vòng lặp sau ít nhất là thực hiện doSomething()lần cuối.


2

Tôi phải đồng ý với sbi ở đây - Tôi thích thuật ngữ vòng kiểm tra giữa . Kiểu cấu trúc này phổ biến hơn khi Lập trình có cấu trúc bắt đầu được triển khai và nhiều ngôn ngữ có hỗ trợ cú pháp cho chúng.

Điều đó nói rằng, hiện nay có kiến ​​thức phổ biến rằng whilecác vòng lặp thường dễ hiểu hơn, vì lý do dễ dàng hơn về bất biến và họ thường xử lý trường hợp trống rỗng khó khăn hơn.

Trong trường hợp cụ thể của bạn, vòng lặp của bạn chỉ tương đương với

for(; doSomething(), !condition(); doSomethingElse()){}

vì vậy tôi sẽ chỉ sử dụng breakphiên bản nếu có doSomethinghoặc doSomethingElseliên quan đến nhiều câu lệnh và tôi không muốn đặt chúng vào các chức năng riêng biệt như bạn đã làm.

Điều đó nói rằng, nếu vòng lặp của bạn phức tạp hơn thì việc lặp lại (bắt đầu, kiểm tra, tăng dần) thì bạn nên xem xét tái cấu trúc nó thành một cái gì đó đơn giản hơn.


1

Tôi đoán nếu chúng ta sẽ cố gắng tạo ra một thuật ngữ cho điều này, có thể:

Vòng lặp có thể tháo rời


-1. câu hỏi không phải là về việc tạo nên một cái tên, mà là về việc một tên chung đã tồn tại chưa. Thêm vào đó, tất cả các vòng lặp là "có thể thoát được" vì vậy nó không phải là một tên đặc biệt hiệu quả.
Bryan Oakley

@BryanOakley Một vòng lặp vô hạn, theo định nghĩa, không nên phá vỡ. Có lẽ không nên có một thuật ngữ cho việc này, ngoài việc lập trình xấu.
LarsTech


0

Nó không phải là quá xấu trong mọi trường hợp. Tôi thấy mình viết loại vòng lặp này với một số loại API nhất định. Ví dụ, giả sử rằng bạn có một đối tượng vòng lặp và cần kiểm tra một số điều kiện khá sâu trong đó, như vậy:

while (loop
    .getAExecutionModelFactory()
    .getActiveXexecutor()
    .getYCancelModelHandler()
    .getCurrentHandler()
    .isCancelled()) {
        // ... do something with the current Handler ....
        loop = ..... // prepare for next loop
}

Bây giờ giả sử mọi phương thức getXXX có thể có khả năng trả về null. Sau đó, vẫn có thể viết một biểu thức boolean, mặc dù một biểu thức khá phức tạp và không thể đọc được. Và sau đó chúng ta phải làm lại gần như giống nhau để có được đối tượng xử lý hiện tại. Trong những trường hợp như vậy, tôi thấy dễ dàng hơn để viết một while (true)vòng lặp với break và tiếp tục.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.