คำว่า "while (จริง)" วนซ้ำกับ "break" ด้านในคืออะไร [ปิด]


24

สมมติว่าฉันมีวงใน C ++ หรือ C # ที่เป็นเช่นนี้:

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

สิ่งนี้เรียกว่า "infinite loop" แต่มันเป็นไปไม่ได้ในทางเทคนิคอนันต์ - breakมันจะหยุดทันทีที่ควบคุมการไหลผ่าน

คำสำหรับวงดังกล่าวคืออะไร - ที่มีคำสั่งการควบคุมแบบวนซ้ำ "ตลอดไป" และ "ตัวแบ่ง" ภายใน


22
ฉันไม่คิดว่าจะมีคำพิเศษ
ChrisF

2
มีการรับประกันใด ๆ หรือไม่ว่าการควบคุมจะไหลผ่านจุดหยุดพัก ในตัวอย่างนั้นจะเกิดอะไรขึ้นถ้าcondition()ส่งคืนค่าเท็จเสมอ ฉันจะบอกว่ามันเป็นวงไม่สิ้นสุดที่มีการแบ่งตามเงื่อนไข
JohnL

1
แม้ว่าจะไม่มี a breakการวนซ้ำก็ไม่สิ้นสุด ( kill, ctrl-alt-del, unplug ... ) เหตุใดจึงต้องกังวลกับรายละเอียดคำศัพท์?
mouviciel

5
"คำนี้คืออะไร" - "ปกติเรียกว่าอนันต์ลูป" นั่นคือคำตอบของคุณที่นั่น ชัดเจนว่าคุณไม่มีความสุขกับคำศัพท์ แต่นั่นก็ไม่ได้ทำให้ความจริงที่ว่าภาษา (เป็นธรรมชาติ) เป็นคำอธิบาย "คำศัพท์สำหรับ X" คือสิ่งที่ผู้คนใช้ไม่ใช่สิ่งที่ควรใช้
MSalters

5
คำถามนี้ดูเหมือนจะไม่อยู่ในหัวข้อเนื่องจากเป็นคำถาม "ชื่อสิ่งนั้น" "ตั้งชื่อสิ่งนั้น" เป็นคำถามที่ไม่ดีด้วยเหตุผลเดียวกับที่ "ระบุรายการทีวีที่คลุมเครือภาพยนตร์หรือหนังสือโดยตัวละครหรือเรื่องราว" เป็นคำถามที่ไม่ดี: คุณไม่สามารถ Google พวกเขาพวกเขาไม่ได้ใช้งานจริง แต่อย่างใด ไม่ช่วยคนอื่นและเปิดโอกาสให้พวกเขาถามคำถามขอบอื่น ๆ ดูblog.stackoverflow.com/2012/02/lets-play-the-guessing-game
gnat

คำตอบ:


24

การศึกษา CS ศาสตราจารย์นี้สอนเราว่ามีลูปก่อนตรวจสอบ ( while(cond) {}) หลังการตรวจสอบลูป ( do {} while(cond);) และลูปกลางตรวจสอบ (ฉันอาจแปลสิ่งนี้เป็นภาษาอังกฤษได้ไม่ดี แต่คุณได้ความคิด)

C และ C ++ ไม่มีหลัง (ISTR Ada มี BICBW) ดังนั้นโครงสร้างของคุณจะใช้สำหรับสิ่งนั้นใน C และ C ++


1
ใช่ Ada มีสิ่งนี้:loop ... exit when condition; ... end loop;
Keith Thompson

@ Keith: ขอบคุณสำหรับการยืนยัน! เกือบ 20 ปีแล้วที่ฉันได้ทำ Ada มาบ้างแล้ว
sbi

1
สำหรับสิ่งที่คุ้มค่าฉันเป็นโปรแกรมเมอร์มืออาชีพมานานกว่า 20 ปี (และเป็นผู้ทำงานอดิเรกนานกว่านั้น) และฉันไม่เคยได้ยินคำเหล่านั้นเลย
offby1

เกี่ยวกับการแปล - ฉันคิดว่า "ใน" มักเหมาะสมกว่าเมื่อใช้ "pre" และ "post" เช่น "preorder / postorder / inorder tree traversal"
โอ๊ก

1
คำที่ฉันโตด้วยคือ "ลูปมิด - ออก" ฉันทำงานในภาษาที่ต่างกันสองภาษาโดยมีการสนับสนุนลูปกลาง - ออก
mjfgates

13

หลักสูตรแรกมากในการบริการลูกค้าที่ Stanford ( Programming วิธีโดย Mehran Sahami ) หมายถึงนี้เป็นห่วงและครึ่งหนึ่ง และมันก็ไม่จำเป็นต้องฝึกเขียนโปรแกรมเสีย ลองพิจารณาตัวอย่างนี้ในการรวบรวมการป้อนข้อมูลของผู้ใช้ (นำมาจากศิลปะและวิทยาศาสตร์ของ Java โดย Eric Robertsโดยที่ Roberts เรียกว่าa-loop-and-a-half ):

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

จากนั้นสิ่งเดียวกันก็แก้ไขโดยใช้ลูปและแนวคิดครึ่งหนึ่งเพื่อหลีกเลี่ยงโค้ดที่ซ้ำกัน:

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

10

ขาดชื่ออย่างเป็นทางการผมเรียกมันว่าBroken ห่วง gotoกำกวมของคำนี้มีวัตถุประสงค์เนื่องจากการหยุดพักในช่วงกลางของวงเป็นบิตมลทินเกือบจะเหมือน


ฉันจะบอกว่าแย่ยิ่งกว่าการข้ามไป ฉันค่อนข้างจะเห็นการกระโดดข้ามมากกว่าเงื่อนไขที่สร้างขึ้นอย่างไม่แน่นอนในลูปแบบนั้น
Brian Knoblauch

14
@Brian คืออะไร เงื่อนไข 'จริง' ทำให้เห็นได้ชัดและลูปแบบนั้นเป็นเรื่องปกติ ตัวอย่างเช่นหากคุณต้องการเพิ่มทุกบรรทัดของไฟล์ลงในรายการคุณต้องลองอ่านบรรทัด (ทำอะไรบางอย่าง) หยุดถ้ามันล้มเหลว (ถ้าแบ่งเงื่อนไข) มิฉะนั้นเพิ่มลงในรายการและทำซ้ำ (ทำอะไรบางอย่าง อื่น).
Craig Gidney

7
ไม่มีอะไรผิดปกติกับการหยุดพักกลางวง หากคุณต้องการดำเนินการบางอย่างในแต่ละรอบของการเริ่มต้นคุณจะต้องทำซ้ำรหัสหรือสิ่งที่การดำเนินการเหล่านี้เป็นเงื่อนไข ตัวแปรทั้งสองมีข้อเสียอย่างชัดเจน gotoนอกจากนี้ยังมีแอปพลิเคชันที่ใช้ได้เช่นการจำลองการลอง ... ในที่สุดบล็อกใน C.
Malcolm

1
Malcolm: ปัญหาที่เป็นไปได้คือระหว่างการอ่านรหัสมันยากที่จะเห็นว่าเมื่อใดและทำไมลูปถูกออก ปัญหาเพิ่มเติมจะเกิดขึ้นเมื่อคุณซ้อนสองห่วงขึ้นไปและต้องการแยกวงรอบนอกออกจากเงื่อนไขที่พบในวงด้านใน
user281377

สมมติว่าคุณมีห่วงเหตุการณ์ขับรถเป็นโปรแกรม Xorg เช่น (ในนามแฝงรหัส :) คุณตามธรรมชาติจะต้องการที่จะตรวจสอบกุญแจภายในวง:while(XEventGet(&ev) != NULL){ ... } if(ev.key == XK_q) break;ทำสิ่งต่อไปนี้: while(XEventGet(&ev) != NULL && ev.key != XK_q){ ... }น่าเกลียดและยากต่อการอ่านมากกว่าการแบ่งช่วงกลาง นอกจากนี้จะเกิดอะไรขึ้นถ้าหากจำเป็นต้องทำบางสิ่งให้เป็นค่าก่อนที่จะสามารถตรวจสอบได้ คุณจะไม่จริงจังกับเรื่องทั้งหมดในกรณีฐานของลูปใช่มั้ย
Braden สุดยอด

8

ไม่มีชื่อที่ชัดเจน ฉันคิดว่าวงที่ไม่มีที่สิ้นสุดเป็นคำที่เหมาะสม ไม่มีลูปไม่มีที่สิ้นสุดอย่างแท้จริง แต่นี่มีศักยภาพที่จะไม่มีที่สิ้นสุดอย่างมีประสิทธิภาพเนื่องจากเป็นไปได้ว่าสาขาที่มีการแตกจะไม่เกิดขึ้น

หากคุณบอกใครบางคน "สร้างวงวนไม่สิ้นสุดและใช้ตัวแบ่งสำหรับเงื่อนไข X" และพวกเขาจะรู้ว่าคุณหมายถึงอะไร หากใครบางคนกำลังทบทวนโค้ดของคุณและบอกว่าไม่มีอะไรมากไปกว่า "ฉันไม่ชอบลูปที่ไม่มีขีด จำกัด ที่คุณเขียน" คุณจะรู้ว่าพวกเขากำลังพูดถึงอะไร (เว้นแต่คุณจะมีมากกว่าหนึ่งหลักสูตร)


1
มันไม่ได้เป็นวงไม่สิ้นสุด มันมีเงื่อนไขการเลิกจ้างที่กำหนดไว้อย่างดีเช่นเดียวกับการwhileวนรอบปกติและวิธีการที่คุณทำการพิสูจน์การเลิกนั้นก็เหมือนกันทุกประการ
Donal Fellows

8

มันวนซ้ำในขณะที่มีเงื่อนไขอยู่ผิดที่


2
ใช่มันควรจะเขียน: ในขณะที่ (keep_going) {doSomething (); ถ้า (เงื่อนไข) {keep_going = false; } else {doSomethingElse (); }}
Stephen Gross

10
ดังนั้น ... คุณกำลังบอกว่าถ้าคุณสอนหลักสูตรคอมพิวเตอร์และต้องการอธิบายสิ่งนี้คุณจะพูดว่า "และตอนนี้เราจะเรียนรู้เกี่ยวกับ * do-while วนซ้ำกับเงื่อนไขในสถานที่ที่ไม่ถูกต้อง "? ฟังดูเหมือนความคิดเห็นทางศาสนามากกว่าชื่อ
ไบรอัน Oakley

5
@StephenGross ข้อมูลโค้ดนั้นเป็นคำแนะนำที่น่ากลัว Refactor ที่จะนำสภาพความเป็นจริงในความหมายห่วงหรือเพียงแค่ใช้หรือbreak continueหลีกเลี่ยงค่าของ Sentinel ในค่าใช้จ่ายทั้งหมดมันเป็นเพียงอีกส่วนหนึ่งของรัฐที่ต้องติดตามจิตใจซึ่งปิดบังวัตถุประสงค์ของรหัส
Izkata

2
ค่า Sentinal ล่าช้าออกไป
Winston Ewert

2
-1 สำหรับการเป็นวีนนี่ทางออกเดียว
Donal Fellows

6

ฉันจะลงคะแนนให้กับ"การวนรอบแบบไม่มีเงื่อนไข"ซึ่งคล้ายกับ "การกระโดดแบบไม่มีเงื่อนไข" มันแสดงให้เห็นว่าสิ่งที่เกิดขึ้น (รหัสลูปไม่มีเงื่อนไข) โดยไม่โกหก (ต่างจาก "infinite loop")


1
แต่มันจะมีเงื่อนไขการเลิกจ้าง; นั่นif/ breakตรงกลางเป็นส่วนหนึ่งของรูปแบบ
Donal Fellows

5

คำสำหรับวงดังกล่าวคืออะไร - ที่มีคำสั่งการควบคุมแบบวนซ้ำ "ตลอดไป" และ "ตัวแบ่ง" ภายใน

มันเป็นวงที่ไม่มีที่สิ้นสุดพร้อมเงื่อนไขการพัก

ฉันเห็นด้วยกับกระสุนในกรณีที่คุณต้องการตั้งชื่อพิเศษคุณสามารถเรียกมันว่าInfinite Partial Loop


1
มันไม่มีที่สิ้นสุดเลย จุดที่ตรวจสอบสภาพการเลิกจ้างอยู่ในสถานที่ที่แตกต่างกัน
Donal Fellows

5

เมื่อวันที่ Rosetta รหัสรูปแบบนี้โดยเฉพาะอย่างยิ่งมีการอธิบายไว้ในฐานะที่เป็น“N บวกครึ่งหนึ่ง” ห่วง แม้ว่ามันจะไม่ใช่คำศัพท์ที่ฉันชอบ แต่ก็ไม่ได้แย่และเป็นรูปแบบที่ชัดเจนว่ามีประโยชน์สำหรับลูปบางประเภท (ทางเลือกคือการทำซ้ำรหัสก่อนเงื่อนไขซึ่งอาจเป็นเรื่องยุ่งยากในโปรแกรมจริงหรือเพื่อเพิ่มความลึกในการซ้อนของโค้ดหลังเงื่อนไขขณะที่เพิ่มตัวแปรเงื่อนไขลูปไม่ปรับปรุงความสามารถในการบำรุงรักษาหรือความเข้าใจโค้ด . เหตุผลเดียวที่ปฏิเสธการสร้างเช่นนี้คือถ้ามีคนยืนยันที่จะเขียนลูปเป็นbreakอิสระ)


4

ไม่มีระยะมาตรฐานคือ แต่ผมจะบอกว่ามันเป็นห่วงบางส่วน

การวนซ้ำนี้จะใช้เมื่อคุณต้องการทำลายหลังจากการดำเนินการบางส่วนของการวนซ้ำครั้งสุดท้าย (เช่นการประมวลผลบางส่วน) โดยจะใช้เมื่อคุณไม่พบสถานการณ์ที่เหมาะสมที่คุณอาจต้องการที่จะทำลายห่วงทั้ง

ในกรณีนี้คุณต้องการทำลายลูปหลังจากดำเนินการอย่างน้อยdoSomething()หนึ่งครั้งล่าสุด


2

ฉันต้องเห็นด้วยกับ sbi ที่นี่ - ฉันชอบเทอมการตรวจสอบลูปกลาง การสร้างแบบนี้เป็นที่นิยมมากขึ้นเมื่อการเขียนโปรแกรมแบบโครงสร้างเริ่มม้วนและหลายภาษามีการสนับสนุนทางไวยากรณ์สำหรับพวกเขา

ที่กล่าวว่าตอนนี้เป็นที่รู้กันอย่างกว้างขวางว่าwhileลูปมักจะมีความเข้าใจมากกว่าเพราะมันง่ายกว่าที่จะให้เหตุผลเกี่ยวกับค่าคงที่และพวกเขามักจะจัดการกับกรณีเปล่าที่ยุ่งยากได้ดีกว่า

ในกรณีเฉพาะของคุณห่วงของคุณเทียบเท่า

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

ดังนั้นฉันจะใช้เฉพาะbreakรุ่นหากมีส่วนร่วมdoSomethingหรือdoSomethingElseมีหลายงบและฉันไม่ควรเก็บไว้ในฟังก์ชั่นที่แยกต่างหากอย่างที่คุณทำ

ที่กล่าวว่าหากการวนซ้ำของคุณซับซ้อนมากขึ้นการทำซ้ำ (เริ่มตรวจสอบเพิ่ม) คุณควรพิจารณาการปรับโครงสร้างให้เป็นสิ่งที่เรียบง่ายกว่า


1

ฉันเดาว่าถ้าเราจะลองทำศัพท์สำหรับเรื่องนี้อาจจะ:

หนีไม่พ้นห่วง


-1 คำถามไม่ได้เกี่ยวกับการตั้งชื่อ แต่เป็นเรื่องเกี่ยวกับชื่อสามัญที่มีอยู่แล้ว นอกจากนี้ลูปทั้งหมดนั้น "สามารถหลบหลีก" ได้ดังนั้นจึงไม่ใช่ชื่อที่มีประสิทธิภาพโดยเฉพาะ
Bryan Oakley

@BryanOakley การวนซ้ำไม่สิ้นสุดตามนิยามไม่ควรเปราะบาง อาจไม่มีคำศัพท์นี้นอกเหนือจากการเขียนโปรแกรมที่ไม่ดี
LarsTech


0

ไม่เลวเลยในทุกกรณี ฉันพบว่าตัวเองเขียนลูปชนิดนี้ด้วย API บางประเภท ตัวอย่างเช่นพูดว่าคุณมีวัตถุลูปและต้องการตรวจสอบเงื่อนไขบางอย่างที่ค่อนข้างลึกในนั้นเช่น:

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

ทีนี้สมมติว่าเมธอด getXXX ทุกตัวสามารถส่งคืนค่าว่างได้ จากนั้นก็ยังคงเป็นไปได้ที่จะเขียนนิพจน์บูลีนแม้ว่าจะค่อนข้างซับซ้อนและอ่านไม่ได้ จากนั้นเราต้องทำซ้ำเกือบเหมือนกันเพื่อไปที่วัตถุตัวจัดการปัจจุบัน ในกรณีเช่นนี้ฉันพบว่าการเขียนwhile (true)ลูปด้วยตัวแบ่งและง่ายขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.