จะแยกวงออกจากสวิตช์ภายในได้อย่างไร?


113

ฉันกำลังเขียนโค้ดที่มีลักษณะดังนี้:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        break; // **HERE, I want to break out of the loop itself**
    }
}

มีวิธีใดโดยตรงที่จะทำเช่นนั้น?

ฉันรู้ว่าฉันสามารถใช้แฟล็กและแยกตัวออกจากลูปได้โดยใส่ตัวแบ่งเงื่อนไขไว้หลังสวิตช์ ฉันแค่อยากรู้ว่า C ++ มีโครงสร้างสำหรับสิ่งนี้หรือไม่


20
ทำไมคุณต้องมีการแบ่งเงื่อนไขหลังจากสวิตช์? เพียงแค่เปลี่ยน while ของคุณจาก while (true) เป็น while (flag) ...
Tal Pressman

7
@Dave_Jarvis ฉันคิดว่านี่เป็นเวอร์ชันที่เรียบง่ายที่เขาใส่ไว้ที่นี่เพื่อแสดงให้เห็นถึงสิ่งที่เขาพยายามทำ
Alterlife

6
หากคุณเป็นหนึ่งในโปรแกรมเมอร์เหล่านี้ที่สร้างฟังก์ชันที่มีความยาวหลายหน้าคุณจะพบว่าgotoน่าสนใจและบางครั้งก็เป็นวิธีเดียวที่สะอาดหมดจด หากคุณมักจะจัดระเบียบโค้ดของคุณให้เป็นฟังก์ชันเล็ก ๆ ซึ่งมีความยาวเพียงไม่กี่บรรทัดและทำทีละข้อคุณจะไม่พบปัญหานี้ (บังเอิญรหัสของคุณจะอ่านง่ายขึ้นด้วย)
sbi

13
หากรู้สึกอยากได้คำแนะนำในการเลิกบุหรี่เมื่อสิ่งที่คุณอยากรู้คือไปยังสถานีรถไฟใต้ดินที่ใกล้ที่สุด
Michael Krelin - แฮ็กเกอร์

7
@hacker: ถ้าคุณไม่เห็นสถานีรถไฟใต้ดินตรงหน้าคุณเนื่องจากควันทั้งหมดคำแนะนำนั้นอาจไม่เลวร้ายทั้งหมด :)
sbi

คำตอบ:


49

หลักฐาน

รหัสต่อไปนี้ควรถือเป็นรูปแบบที่ไม่ดีโดยไม่คำนึงถึงภาษาหรือฟังก์ชันที่ต้องการ:

while( true ) {
}

สนับสนุนอาร์กิวเมนต์

การwhile( true )วนซ้ำเป็นรูปแบบที่ไม่ดีเนื่องจาก:

  • ทำลายสัญญาโดยนัยของ while loop
    • ประกาศในขณะที่ห่วงอย่างชัดเจนควรระบุเพียงเงื่อนไขทางออก
  • หมายความว่ามันวนซ้ำตลอดไป
    • ต้องอ่านรหัสภายในลูปเพื่อทำความเข้าใจกับประโยคยุติ
    • ลูปที่ทำซ้ำตลอดไปจะป้องกันไม่ให้ผู้ใช้ยุติโปรแกรมจากภายในโปรแกรม
  • ไม่มีประสิทธิภาพ
    • มีเงื่อนไขการสิ้นสุดลูปหลายเงื่อนไขรวมถึงการตรวจสอบ "จริง"
  • มีแนวโน้มที่จะเกิดข้อบกพร่อง
    • ไม่สามารถระบุได้อย่างง่ายดายว่าจะวางโค้ดไว้ที่ใดซึ่งจะรันสำหรับการวนซ้ำแต่ละครั้ง
  • นำไปสู่รหัสที่ซับซ้อนโดยไม่จำเป็น
  • การวิเคราะห์ซอร์สโค้ดอัตโนมัติ
    • หากต้องการค้นหาจุดบกพร่องการวิเคราะห์ความซับซ้อนของโปรแกรมการตรวจสอบความปลอดภัยหรือหาลักษณะการทำงานของซอร์สโค้ดอื่น ๆ โดยอัตโนมัติโดยไม่มีการเรียกใช้โค้ดการระบุเงื่อนไขการทำลายเริ่มต้นช่วยให้อัลกอริทึมสามารถกำหนดค่าคงที่ที่เป็นประโยชน์ได้ซึ่งจะช่วยปรับปรุงเมตริกการวิเคราะห์ซอร์สโค้ดอัตโนมัติ
  • ลูปไม่มีที่สิ้นสุด
    • หากทุกคนมักใช้while(true)สำหรับลูปที่ไม่สิ้นสุดเราจะสูญเสียความสามารถในการสื่อสารอย่างรัดกุมเมื่อลูปไม่มีเงื่อนไขยุติ (เป็นเรื่องที่เกิดขึ้นแล้วดังนั้นประเด็นคือการสงสัย)

ทางเลือกสำหรับ "ไปที่"

รหัสต่อไปนี้เป็นรูปแบบที่ดีกว่า:

while( isValidState() ) {
  execute();
}

bool isValidState() {
  return msg->state != DONE;
}

ข้อดี

ไม่มีธง. gotoไม่ ไม่มีข้อยกเว้น. ง่ายต่อการเปลี่ยนแปลง อ่านง่าย แก้ไขได้ง่าย. นอกจากนี้รหัส:

  1. แยกความรู้เกี่ยวกับภาระงานของลูปออกจากลูปเอง
  2. ช่วยให้ผู้ที่ดูแลรหัสสามารถขยายฟังก์ชันการทำงานได้อย่างง่ายดาย
  3. อนุญาตให้กำหนดเงื่อนไขการยกเลิกได้หลายรายการในที่เดียว
  4. แยกส่วนคำสั่งยุติออกจากโค้ดเพื่อดำเนินการ
  5. ปลอดภัยกว่าสำหรับโรงไฟฟ้านิวเคลียร์ ;-)

จุดที่สองมีความสำคัญ โดยไม่ทราบว่าโค้ดทำงานอย่างไรหากมีคนขอให้ฉันสร้างลูปหลักให้เธรดอื่น ๆ (หรือกระบวนการ) มีเวลา CPU อยู่บ้างก็ควรคำนึงถึงสองวิธี:

ตัวเลือกที่ 1

แทรกการหยุดชั่วคราวได้ทันที:

while( isValidState() ) {
  execute();
  sleep();
}

ตัวเลือก # 2

แทนที่ดำเนินการ:

void execute() {
  super->execute();
  sleep();
}

รหัสนี้จะง่าย (จึงง่ายต่อการอ่าน) switchกว่าวงที่มีการฝังตัว isValidStateวิธีเดียวที่ควรตรวจสอบว่าวงที่ควรดำเนินการต่อ เวิร์กฮอร์สของเมธอดควรถูกสรุปลงในexecuteเมธอดซึ่งอนุญาตให้คลาสย่อยสามารถแทนที่พฤติกรรมเริ่มต้นได้ (งานที่ยากโดยใช้การฝังswitchและgoto)

ตัวอย่าง Python

เปรียบเทียบคำตอบต่อไปนี้ (สำหรับคำถาม Python) ที่โพสต์บน StackOverflow:

  1. วนลูปตลอดไป.
  2. ขอให้ผู้ใช้ป้อนตัวเลือก
  3. หากอินพุตของผู้ใช้คือ "รีสตาร์ท" ให้วนลูปต่อไปตลอดกาล
  4. มิฉะนั้นจะหยุดการวนซ้ำตลอดไป
  5. ปลาย
รหัส
while True: 
    choice = raw_input('What do you want? ')

    if choice == 'restart':
        continue
    else:
        break

print 'Break!' 

เมื่อเทียบกับ:

  1. เริ่มต้นตัวเลือกของผู้ใช้
  2. วนซ้ำในขณะที่ตัวเลือกของผู้ใช้คือคำว่า 'เริ่มต้นใหม่'
  3. ขอให้ผู้ใช้ป้อนตัวเลือก
  4. ปลาย
รหัส
choice = 'restart';

while choice == 'restart': 
    choice = raw_input('What do you want? ')

print 'Break!'

ซึ่งจะwhile Trueส่งผลให้เกิดรหัสที่ทำให้เข้าใจผิดและซับซ้อนเกินไป


45
ความคิดที่while(true)น่าจะเป็นอันตรายนั้นดูแปลกประหลาดสำหรับฉัน มีลูปที่ตรวจสอบก่อนดำเนินการมีสิ่งที่ตรวจสอบในภายหลังและมีสิ่งที่ตรวจสอบตรงกลาง ตั้งแต่หลังไม่ได้มีการสร้างประโยคใน C และ C ++ คุณจะต้องใช้หรือwhile(true) for(;;)หากคุณคิดว่าสิ่งนี้ผิดแสดงว่าคุณยังไม่ได้ไตร่ตรองมากพอกับการวนซ้ำประเภทต่างๆ
sbi

34
เหตุผลที่ฉันไม่เห็นด้วย: ในขณะที่ (จริง) และสำหรับ (;;;) ไม่สับสน (ต่างจาก do {} while (true)) เพราะพวกเขาระบุสิ่งที่พวกเขากำลังทำอยู่ตรงหน้า จริงๆแล้วการมองหาคำสั่ง "break" นั้นง่ายกว่าการแยกวิเคราะห์เงื่อนไขการวนซ้ำตามอำเภอใจและมองหาตำแหน่งที่กำหนดไว้และไม่ยากที่จะพิสูจน์ความถูกต้อง อาร์กิวเมนต์เกี่ยวกับตำแหน่งที่จะใส่โค้ดนั้นยากพอ ๆ กับการมีคำสั่งต่อและไม่ดีไปกว่าคำสั่ง if มากนัก อาร์กิวเมนต์ประสิทธิภาพเป็นเรื่องงี่เง่า
David Thornley

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

5
@ เดฟ: ฉันให้เหตุผลว่ามันเป็นวิธีเดียวที่จะได้ลูปที่ตรวจสอบเงื่อนไขตรงกลาง ตัวอย่างคลาสสิก: while(true) {string line; std::getline(is,line); if(!is) break; lines.push_back(line);}แน่นอนฉันสามารถเปลี่ยนสิ่งนี้เป็นลูปที่มีเงื่อนไขล่วงหน้าได้ (โดยใช้std::getlineเป็นเงื่อนไขการวนซ้ำ) แต่สิ่งนี้มีข้อเสียในตัวมันเอง ( lineจะต้องเป็นตัวแปรนอกขอบเขตของลูป) และถ้าฉันทำฉันจะต้องถามว่าทำไมเราถึงมีสามลูปต่อไป? เราสามารถเปลี่ยนทุกอย่างให้เป็นลูปที่ปรับสภาพล่วงหน้าได้เสมอ ใช้สิ่งที่เหมาะที่สุด ถ้าwhile(true)พอดีก็ใช้เลย
sbi

3
เพื่อเป็นการเอื้อเฟื้อผู้คนที่อ่านคำตอบนี้ฉันจะหลีกเลี่ยงการแสดงความคิดเห็นเกี่ยวกับคุณภาพของสิ่งที่ดีที่ก่อให้เกิดคำถามและยึดติดกับการตอบคำถามเอง คำถามคือรูปแบบต่อไปนี้ซึ่งฉันเชื่อว่าเป็นคุณลักษณะของหลายภาษา: คุณมีลูปซ้อนอยู่ภายในลูปอื่น คุณต้องการแยกวงนอกออกจากวงใน วิธีนี้ทำได้อย่างไร?
Alex Leibowitz

172

คุณสามารถใช้goto.

while ( ... ) {
   switch( ... ) {
     case ...:
         goto exit_loop;

   }
}
exit_loop: ;

12
เพียงแค่อย่าบ้าคลั่งกับคำหลักนั้น
Fragsworth

45
มันตลกฉันจะได้รับ downvoted gotoเพราะคนไม่ชอบ OP ที่กล่าวถึงอย่างชัดเจนโดยไม่ต้องใช้แฟล็ก คุณสามารถแนะนำวิธีที่ดีกว่าโดยพิจารณาจากข้อ จำกัด ของ OP ได้หรือไม่? :)
Mehrdad Afshari

18
โหวตขึ้นเพื่อชดเชยความเกลียดชัง goto ที่ไม่สนใจ ฉันเดาว่า Mehrdad รู้ว่าเขาจะเสียคะแนนสองสามข้อในการแนะนำวิธีแก้ปัญหาที่สมเหตุสมผลที่นี่
Michael Krelin - แฮ็กเกอร์

6
+1 ไม่มีวิธีใดดีไปกว่า imho แม้ว่าจะพิจารณาถึงข้อ จำกัด ของ OPs ก็ตาม ธงเป็นสิ่งที่น่าเกลียดทำลายตรรกะในวงรอบทั้งหมดและทำให้เข้าใจได้ยากขึ้น
Johannes Schaub - litb

11
ในตอนท้ายของวันโดยไม่มีโครงสร้าง goto ทุกภาษาจะล้มเหลว ภาษาระดับสูงทำให้สับสน แต่ถ้าคุณดูยากพอภายใต้ประทุนคุณจะพบว่าทุกลูปหรือเงื่อนไขลดลงเป็นกิ่งก้านที่มีเงื่อนไขและไม่มีเงื่อนไข เราหลอกตัวเองโดยใช้คีย์เวิร์ด for, while, until, switch, แต่ในที่สุดพวกเขาก็ใช้ GOTO (หรือ JMP) ไม่ทางใดก็ทางหนึ่ง คุณสามารถหลอกตัวเองประดิษฐ์วิธีที่ชาญฉลาดทุกประเภทเพื่อซ่อนมันหรือคุณสามารถซื่อสัตย์ในทางปฏิบัติและใช้ goto ตามความเหมาะสมและเท่าที่จำเป็น
ไนซ์

58

ทางเลือกอื่นคือการใช้คีย์เวิร์ดcontinueร่วมกับbreak:

for (;;) {
    switch(msg->state) {
    case MSGTYPE
        // code
        continue; // continue with loop
    case DONE:
        break;
    }
    break;
}

ใช้continueคำสั่งเพื่อจบเลเบลเคสแต่ละอันที่คุณต้องการให้ลูปดำเนินต่อไปและใช้breakคำสั่งเพื่อจบเลเบลเคสที่ควรยุติลูป

แน่นอนวิธีนี้ใช้ได้เฉพาะในกรณีที่ไม่มีรหัสเพิ่มเติมให้ดำเนินการหลังจากคำสั่งสวิตช์


9
แม้ว่าสิ่งนี้จะดูสง่างามมาก แต่ก็มีข้อเสียที่นักพัฒนาส่วนใหญ่ต้องมองมันเป็นเวลาหนึ่งนาทีก่อนเพื่อที่จะเข้าใจว่ามันทำงานอย่างไร / หรือไม่ :(
sbi

8
ประโยคสุดท้ายคือสิ่งที่ทำให้สิ่งนี้ไม่ดีมาก:(มิฉะนั้นการใช้งานที่สะอาดมาก
nawfal

เมื่อคุณคิดเกี่ยวกับเรื่องนี้ไม่มีรหัสคอมพิวเตอร์ที่ดี เราได้รับการฝึกฝนให้เข้าใจมันเท่านั้น ตัวอย่างเช่น xml ดูเหมือนขยะจนกว่าฉันจะได้เรียนรู้ ตอนนี้ขยะน้อยลง สำหรับ (int x = 0; x <10; ++ x, moveCursor (x, y)) ทำให้เกิดข้อผิดพลาดทางตรรกะในโปรแกรมของฉัน ฉันลืมไปว่าเงื่อนไขการอัปเดตเกิดขึ้นในตอนท้าย

22

วิธีที่เรียบร้อยในการทำเช่นนี้คือการนำสิ่งนี้ไปใช้ในฟังก์ชัน:

int yourfunc() {

    while(true) {

        switch(msg->state) {
        case MSGTYPE: // ... 
            break;
        // ... more stuff ...
        case DONE:
            return; 
        }

    }
}

ทางเลือก (แต่เป็น 'แนวทางปฏิบัติที่ไม่ดี'): ตามที่แนะนำไปแล้วว่าคุณสามารถใช้ goto หรือโยนข้อยกเว้นภายในสวิตช์


4
ควรใช้ข้อยกเว้นเพื่อโยนข้อยกเว้นไม่ใช่พฤติกรรมที่รู้จักกันดีของฟังก์ชัน
Clement Herreman

ฉันเห็นด้วยกับชีวิตหลังความตาย: ใส่ไว้ในฟังก์ชัน
dalle

14
การโยนข้อยกเว้นถือเป็นเรื่องชั่วร้ายจริงๆในกรณีนี้ มันหมายความว่า "ฉันต้องการใช้ goto แต่ฉันอ่านที่ไหนสักแห่งว่าฉันไม่ควรใช้มันดังนั้นฉันจะใช้ความคิดฟุ้งซ่านและแสร้งทำเป็นดูฉลาด"
Gorpik

ฉันยอมรับว่าการทิ้งข้อยกเว้นหรือการใช้ goto เป็นความคิดที่แย่มาก แต่เป็นตัวเลือกที่ใช้ได้ผลและได้ระบุไว้ในคำตอบของฉัน
Alterlife

2
การโยนข้อยกเว้นคือการแทนที่ COMEFROM สำหรับ GOTO อย่าทำ goto ทำงานได้ดีขึ้นมาก
David Thornley

14

AFAIK ไม่มี "double break" หรือโครงสร้างที่คล้ายกันใน C ++ สิ่งที่ใกล้เคียงที่สุดคือgoto- ซึ่งแม้ว่าจะมีความหมายแฝงที่ไม่ดีกับชื่อ แต่ก็มีอยู่ในภาษาด้วยเหตุผลตราบใดที่มีการใช้อย่างระมัดระวังและประหยัด แต่ก็เป็นตัวเลือกที่ใช้ได้


8

คุณสามารถใส่สวิตช์ของคุณเป็นฟังก์ชันแยกต่างหากเช่นนี้:

bool myswitchfunction()
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        return false; // **HERE, I want to break out of the loop itself**
    }
    return true;
}

while(myswitchfunction())
    ;

7

แม้ว่าคุณจะไม่ชอบ goto แต่อย่าใช้ข้อยกเว้นเพื่อออกจากลูป ตัวอย่างต่อไปนี้แสดงให้เห็นว่ามันน่าเกลียดขนาดไหน:

try {
  while ( ... ) {
    switch( ... ) {
      case ...:
        throw 777; // I'm afraid of goto
     }
  }
}
catch ( int )
{
}

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

แต่ผมคิดว่าการใช้เป็นตัวเลือกเดียวที่นี่เพราะของสตริงgoto while(true)คุณควรพิจารณาปรับโครงสร้างลูปของคุณใหม่ ฉันคิดว่าวิธีแก้ปัญหาต่อไปนี้:

bool end_loop = false;
while ( !end_loop ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        end_loop = true; break;
    }
}

หรือแม้กระทั่งสิ่งต่อไปนี้:

while ( msg->state != DONE ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
}

1
ใช่ แต่ฉันชอบข้อยกเว้นแม้แต่น้อย ;-)
quamrana

3
การใช้ข้อยกเว้นเพื่อเลียนแบบ goto นั้นแย่กว่าการใช้ goto จริงๆ! มันอาจจะช้าลงอย่างเห็นได้ชัด
John Carter

2
@ Downvoter: เป็นเพราะฉันบอกว่าคุณไม่ควรใช้ข้อยกเว้นหรือเพราะฉันแนะนำให้ปรับโครงสร้าง
Kirill V. Lyadvinsky

1
ไม่ใช่ผู้ลงคะแนน - แต่ ... คำตอบของคุณไม่ชัดเจนว่าคุณกำลังเสนอหรือประณามแนวคิดในการใช้ข้อยกเว้นเพื่อออกจากลูป บางทีประโยคแรกควรจะ: "แม้ว่าคุณจะไม่ชอบgotoไม่ได้ใช้ข้อยกเว้นที่จะออกจากวง:"?
Jonathan Leffler

1
@Jonathan Leffler ขอบคุณคุณแสดงตัวอย่างความคิดเห็นที่มีค่า อัปเดตคำตอบโดยคำนึงถึงความคิดเห็นของคุณ
Kirill V. Lyadvinsky

5

ไม่มีโครงสร้าง C ++ สำหรับการแตกออกจากลูปในกรณีนี้

ไม่ว่าจะใช้ธงที่จะขัดขวางห่วงหรือ (ถ้าเหมาะสม) returnสารสกัดจากรหัสของคุณให้เป็นฟังก์ชั่นและการใช้งาน



2

ทำไมไม่แก้ไขเงื่อนไขใน while loop ของคุณทำให้ปัญหาหายไป

while(msg->state != DONE)
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        // We can't get here, but for completeness we list it.
        break; // **HERE, I want to break out of the loop itself**
    }
}

2

ไม่ C ++ ไม่มีโครงสร้างสำหรับสิ่งนี้เนื่องจากคีย์เวิร์ด "break" ถูกสงวนไว้สำหรับการออกจากบล็อกสวิตช์ อีกวิธีหนึ่งคือ do.. while () ที่มีค่าสถานะทางออกก็เพียงพอแล้ว

do { 
    switch(option){
        case 1: ..; break;
        ...
        case n: .. ;break;
        default: flag = false; break;
    }
} while(flag);

1

ฉันคิด;

while(msg->state != mExit) 
{
    switch(msg->state) 
    {
      case MSGTYPE: // ...
         break;
      case DONE:
      //  .. 
      //  ..
      msg->state =mExit;
      break;
    }
}
if (msg->state ==mExit)
     msg->state =DONE;

0

วิธีที่ง่ายที่สุดคือใส่ IF ง่ายๆก่อนที่คุณจะทำ SWITCH และ IF จะทดสอบเงื่อนไขของคุณเพื่อออกจากลูป .......... ง่ายๆอย่างที่ทำได้


2
อืม ... คุณอาจจะง่ายกว่านี้ด้วยการใส่เงื่อนไขนั้นในการโต้แย้ง while ฉันหมายความว่ามันมีไว้เพื่อ! :)
Mark A. Donohoe

0

breakคำหลักใน C ++ เท่านั้นยุติในที่สุดที่ซ้อนกันย้ำการปิดล้อมหรือswitchคำสั่ง ดังนั้นคุณไม่สามารถแยกออกจากwhile (true)ลูปได้โดยตรงภายในswitchคำสั่ง อย่างไรก็ตามคุณสามารถใช้รหัสต่อไปนี้ซึ่งฉันคิดว่าเป็นรูปแบบที่ยอดเยี่ยมสำหรับปัญหาประเภทนี้:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

หากคุณต้องการทำบางสิ่งบางอย่างเมื่อmsg->stateเท่ากันDONE(เช่นเรียกใช้รูทีนการล้างข้อมูล) ให้วางโค้ดนั้นไว้หลังforลูปทันที เช่นถ้าคุณมี:

while (true) {
    switch (msg->state) {
    case MSGTYPE:
        //... 
        break;

    //...

    case DONE:
        do_cleanup();
        break;
    }

    if (msg->state == DONE)
        break;

    msg = next_message();
}

จากนั้นใช้แทน:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

assert(msg->state == DONE);
do_cleanup();

0

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

bool imLoopin = true;

while(imLoopin) {

    switch(msg->state) {

        case MSGTYPE: // ... 
            break;

        // ... more stuff ...

        case DONE:
            imLoopin = false;
            break;

    }

}

ฮ่า ๆ!! จริงๆ! นั่นคือทั้งหมดที่คุณต้องการ! หนึ่งตัวแปรพิเศษ!


0
while(MyCondition) {
switch(msg->state) {
case MSGTYPE: // ... 
    break;
// ... more stuff ...
case DONE:
   MyCondition=false; // just add this code and you will be out of loop.
    break; // **HERE, you want to break out of the loop itself**
}
}

0

ฉันพบปัญหาเดียวกันและแก้ไขโดยใช้ธง

bool flag = false;
while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        flag = true; // **HERE, I want to break out of the loop itself**
    }
    if(flag) break;
}

-2

ถ้าฉันจำไวยากรณ์ C ++ ได้ดีคุณสามารถเพิ่มป้ายกำกับในbreakคำสั่งได้เช่นเดียวกับสำหรับgoto. ดังนั้นสิ่งที่คุณต้องการจะเขียนได้อย่างง่ายดาย:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ...
        break;
    // ... more stuff ...
    case DONE:
        break outofloop; // **HERE, I want to break out of the loop itself**
    }
}

outofloop:
// rest of your code here

1
ขออภัยหน่วยความจำของคุณผิดพลาด มันจะเป็นคุณสมบัติที่ดีในบางโอกาสที่มันจะมีประโยชน์ (ฉันเคยเห็นข้อเสนอสำหรับจำนวนระดับที่จะทำลาย แต่สิ่งเหล่านั้นดูเหมือนกับฉันเหมือนข้อบกพร่องที่รอให้เกิดขึ้น)
David Thornley

นั่นต้องเป็น Java แล้ว ขอบคุณสำหรับคำตอบ. และแน่นอนคุณก็ถูกกับคนอื่น ๆ เช่นกัน
Andrei Vajna II

-3
  while(true)
  {
    switch(x)
    {
     case 1:
     {
      break;
     }
    break;
   case 2:
    //some code here
   break;
  default:
  //some code here
  }
}

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