การใช้ break in a for loop เป็นการปฏิบัติที่ไม่ดีหรือไม่? [ปิด]


124

การใช้breakคำสั่งภายในforลูปเป็นการปฏิบัติที่ไม่ดีหรือไม่?

สมมติว่าฉันกำลังค้นหาค่าในอาร์เรย์ เปรียบเทียบภายใน for loop และเมื่อพบค่าbreak;เพื่อออกจาก for loop

เป็นการปฏิบัติที่ไม่ดีหรือไม่? ฉันได้เห็นทางเลือกที่ใช้: กำหนดตัวแปรvFoundและตั้งค่าเป็นจริงเมื่อพบค่าและตรวจสอบvFoundในforเงื่อนไขคำสั่ง แต่จำเป็นต้องสร้างตัวแปรใหม่เพื่อจุดประสงค์นี้หรือไม่?

ฉันกำลังถามในบริบทของ C หรือ C ++ ปกติสำหรับลูป

PS: หลักเกณฑ์การเข้ารหัส MISRA ไม่แนะนำให้ใช้ตัวแบ่ง


28
อย่าbreakอยู่ในลีกเดียวกับgoto:)
BoltClock

2
เอ่อฉันไม่ได้จัดให้อยู่ในลีกเดียวกับไปที่ ... กฎของ MISRA ระบุการหยุดพักถ้าฉันจำไม่ผิด
kiki

1
เหตุผลเดียวที่ฉันคิดได้ว่าจะไม่ใช้ break inside a loop ก็คือเมื่อคุณยังต้องประมวลผลรายการเพิ่มเติมที่อาจเปลี่ยนแปลงผลลัพธ์ของสิ่งที่คุณกำลังทำอยู่ ...
Younes

4
กฎของ MISRA ได้รับการผ่อนปรน: misra.org.uk/forum/viewtopic.php?f=75&t=298
Johan Kotlinski

คำตอบ:


123

มีคำตอบมากมายที่นี่ แต่ฉันยังไม่เห็นสิ่งนี้:

"อันตราย" ส่วนใหญ่ที่เกี่ยวข้องกับการใช้breakหรือcontinueในการวนซ้ำจะถูกลบล้างหากคุณเขียนลูปที่เป็นระเบียบและอ่านได้ง่าย หากเนื้อหาของลูปของคุณมีความยาวหลายหน้าจอและมีบล็อกย่อยที่ซ้อนกันหลายบล็อกใช่คุณอาจลืมได้อย่างง่ายดายว่าโค้ดบางส่วนจะไม่ถูกเรียกใช้หลังจากหยุดพัก อย่างไรก็ตามหากลูปสั้นและตรงประเด็นจุดประสงค์ของคำสั่งแบ่งควรชัดเจน

หากลูปมีขนาดใหญ่เกินไปให้ใช้ฟังก์ชันที่มีชื่อดีอย่างน้อยหนึ่งฟังก์ชันเรียกภายในลูปแทน เหตุผลเดียวที่แท้จริงที่ควรหลีกเลี่ยงคือการประมวลผลคอขวด


11
ค่อนข้างจริง. แน่นอนว่าลูปนั้นใหญ่และซับซ้อนจนยากที่จะมองเห็นว่าเกิดอะไรขึ้นข้างในนั่นเป็นปัญหาไม่ว่าคุณจะหยุดพักหรือไม่
เจ

1
ปัญหาอีกประการหนึ่งคือการหยุดและดำเนินการต่อทำให้เกิดปัญหากับการปรับโครงสร้างใหม่ นี่อาจเป็นสัญญาณว่าเป็นการปฏิบัติที่ไม่ดี เจตนาของรหัสยังชัดเจนขึ้นเมื่อใช้คำสั่ง if
Ed Greaves

"การเรียกใช้ฟังก์ชันที่มีชื่อดี" เหล่านี้สามารถเป็นฟังก์ชันแลมบ์ดาที่กำหนดไว้ในเครื่องแทนที่จะเป็นฟังก์ชันส่วนตัวที่กำหนดจากภายนอกซึ่งจะไม่ถูกนำไปใช้ที่อื่น
DavidRR

135

ไม่แตกเป็นวิธีแก้ปัญหาที่ถูกต้อง

การเพิ่มตัวแปรบูลีนทำให้โค้ดอ่านยากขึ้นและเพิ่มแหล่งที่มาของข้อผิดพลาด


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

2
นั่นคือเหตุผลที่ฉันใช้gotoเพื่อแยกลูปที่ซ้อนกันระดับ 2+ - เพราะไม่มีbreak(level)
ПетърПетров

3
ฉันควรใส่รหัสลูปในฟังก์ชันและกลับมา วิธีนี้จะหลีกเลี่ยง goto และแบ่งรหัสของคุณเป็นชิ้นเล็ก ๆ
Dave Branton

53

คุณสามารถค้นหารหัสมืออาชีพทุกประเภทที่มีคำสั่ง 'break' อยู่ในนั้น ควรใช้สิ่งนี้ทุกครั้งที่จำเป็น ในกรณีของคุณตัวเลือกนี้ดีกว่าการสร้างตัวแปรแยกเฉพาะเพื่อจุดประสงค์ในการออกมาจากลูป


47

การใช้breakเช่นเดียวกับcontinueการforวนซ้ำทำได้ดีมาก

ช่วยลดความซับซ้อนของรหัสและปรับปรุงการอ่าน


ใช่ .. เป็นครั้งหนึ่งที่ฉันไม่ชอบความคิดนี้และเขียนโค้ดไว้รอบ ๆ แต่ใช้เวลาไม่นานก่อนที่ฉันจะตระหนักว่า ... "วิธีแก้ปัญหา" มักจะเป็นฝันร้ายในการซ่อมบำรุง ไม่ใช่ฝันร้าย แต่มีโอกาสผิดพลาดได้ง่ายกว่า
MetalMikester

24

ห่างไกลจากการปฏิบัติที่ไม่ดีหลาม (และภาษาอื่น ๆ ?) ขยายforวงโครงสร้างเพื่อให้เป็นส่วนหนึ่งของมันจะเพียง แต่จะดำเนินการถ้าห่วงไม่ได้ break

for n in range(5):
    for m in range(3):
        if m >= n:
            print('stop!')
            break
        print(m, end=' ')
    else:
        print('finished.')

เอาท์พุท:

stop!
0 stop!
0 1 stop!
0 1 2 finished.
0 1 2 finished.

รหัสเทียบเท่าที่ไม่มีbreakและมีประโยชน์else:

for n in range(5):
    aborted = False
    for m in range(3):
        if not aborted:
            if m >= n:
                print('stop!')
                aborted = True
            else:            
                print(m, end=' ')
    if not aborted:
        print('finished.')

2
ฉันชอบมันและบางครั้งก็อยากให้มันเป็นภาษาซีที่ดีด้วยซึ่งสามารถปรับให้เป็นภาษาซีในอนาคตได้โดยไม่มีความคลุมเครือ
supercat

"ภาษาเหมือนซี": P
nirvanaswap

15

ไม่มีอะไรผิดปกติในการใช้คำสั่ง break แต่ลูปที่ซ้อนกันอาจทำให้สับสนได้ เพื่อปรับปรุงความสามารถในการอ่านภาษาต่างๆ ( อย่างน้อยก็ Java ) สนับสนุนการทำลายป้ายกำกับซึ่งจะช่วยเพิ่มความสามารถในการอ่านได้มาก

int[] iArray = new int[]{0,1,2,3,4,5,6,7,8,9};
int[] jArray = new int[]{0,1,2,3,4,5,6,7,8,9};

// label for i loop
iLoop: for (int i = 0; i < iArray.length; i++) {

    // label for j loop
    jLoop: for (int j = 0; j < jArray.length; j++) {

        if(iArray[i] < jArray[j]){
            // break i and j loops
            break iLoop;
        } else if (iArray[i] > jArray[j]){  
            // breaks only j loop
            break jLoop;
        } else {
            // unclear which loop is ending
            // (breaks only the j loop)
            break;
        }
    }
}

ฉันจะบอกว่าคำสั่ง break (และ return) มักเพิ่มความซับซ้อนของวัฏจักรซึ่งทำให้ยากต่อการพิสูจน์ว่า code กำลังทำสิ่งที่ถูกต้องในทุกกรณี

หากคุณกำลังพิจารณาที่จะใช้ช่วงพักขณะที่ทำซ้ำตามลำดับสำหรับบางรายการคุณอาจต้องการพิจารณาโครงสร้างข้อมูลที่ใช้เก็บข้อมูลของคุณใหม่ การใช้บางอย่างเช่น Set หรือ Map อาจให้ผลลัพธ์ที่ดีกว่า


4
+1 สำหรับความซับซ้อนของวัฏจักร
sp00m

โปรแกรมเมอร์. NET อาจต้องการสำรวจการใช้ LINQ เป็นทางเลือกที่เป็นไปได้สำหรับforลูปที่ซับซ้อน
DavidRR

14

breakเป็นคำสั่งที่ยอมรับได้อย่างสมบูรณ์ในการใช้ (ดังนั้นต่อไป btw) ทุกอย่างเกี่ยวกับความสามารถในการอ่านโค้ด - ตราบใดที่คุณไม่มีลูปที่ซับซ้อนเกินไปก็ใช้ได้

มันไม่ได้เป็นอย่างที่พวกเขาลีกเช่นเดียวกับโกโตะ :)


ฉันได้เห็นมันเป็นที่ถกเถียงกันว่าคำสั่งหยุดพักเป็นอย่างมีประสิทธิภาพโกโตะ
glenatron

3
ปัญหาของ goto คือคุณสามารถชี้ได้ทุกที่ ทั้งแบ่งและดำเนินการต่อเพื่อรักษาความเป็นโมดูลาร์ของรหัส อาร์กิวเมนต์นั้นอยู่ในระดับเดียวกับการมีจุดออกเดียวสำหรับแต่ละฟังก์ชัน
Zachary Yates

1
ผมเคยได้ยินว่ามันเป็นที่ถกเถียงกันว่ามีจุดออกหลายฟังก์ชั่นเป็นอย่างมีประสิทธิภาพโกโตะ ; D
glenatron

2
@glenatron ปัญหาของ goto ไม่ใช่คำสั่ง goto แต่เป็นการแนะนำฉลากที่ goto ข้ามไปนั่นคือปัญหา เมื่อคุณอ่านคำสั่ง goto ไม่มีความไม่แน่นอนเกี่ยวกับโฟลว์การควบคุม เมื่อคุณอ่านฉลากมีความไม่แน่นอนมากมายเกี่ยวกับขั้นตอนการควบคุม (gotos ทั้งหมดที่ถ่ายโอนการควบคุมไปยังป้ายกำกับนี้อยู่ที่ไหน) คำสั่งแบ่งไม่แนะนำป้ายกำกับดังนั้นจึงไม่แนะนำภาวะแทรกซ้อนใหม่ ๆ
สตีเฟนซีสตีล

1
"แบ่ง" คือโกโตะพิเศษที่สามารถออกจากบล็อกได้เท่านั้น ปัญหาทางประวัติศาสตร์เกี่ยวกับ "goto" คือ (1) อาจเป็นได้และมักจะถูกใช้เพื่อสร้างบล็อกลูปที่ทับซ้อนกันในลักษณะที่ไม่สามารถทำได้ด้วยโครงสร้างการควบคุมที่เหมาะสม (2) วิธีทั่วไปในการสร้าง "if-then" ซึ่งโดยปกติจะเป็น "เท็จ" คือการแยกสาขาของกรณีจริงไปยังตำแหน่งที่ไม่เกี่ยวข้องในโค้ดจากนั้นจึงแยกสาขากลับ สิ่งนี้จะเสียค่าใช้จ่ายสองสาขาในกรณีที่หายากและเป็นศูนย์ในกรณีทั่วไป แต่ทำให้รหัสดูน่ากลัว
supercat

14

กฎทั่วไป: หากการปฏิบัติตามกฎทำให้คุณต้องทำสิ่งที่น่าอึดอัดและอ่านยากมากขึ้นจากนั้นฝ่าฝืนกฎก็ฝ่าฝืนกฎ

ในกรณีของการวนซ้ำจนกว่าคุณจะพบบางสิ่งคุณจะพบปัญหาในการแยกแยะพบกับไม่พบเมื่อคุณออกไปข้างนอก นั่นคือ:

for (int x=0;x<fooCount;++x)
{
  Foo foo=getFooSomehow(x);
  if (foo.bar==42)
    break;
}
// So when we get here, did we find one, or did we fall out the bottom?

โอเคคุณสามารถตั้งค่าสถานะหรือเริ่มต้นค่า "พบ" เป็นค่าว่าง แต่

นั่นเป็นเหตุผลที่โดยทั่วไปแล้วฉันชอบที่จะผลักดันการค้นหาให้เป็นฟังก์ชัน

Foo findFoo(int wantBar)
{
  for (int x=0;x<fooCount;++x)
  {
    Foo foo=getFooSomehow(x);
    if (foo.bar==wantBar)
      return foo;
  }
  // Not found
  return null;
}

นอกจากนี้ยังช่วยคลายรหัส ในบรรทัดหลัก "find" จะกลายเป็นคำสั่งเดียวและเมื่อเงื่อนไขซับซ้อนก็จะเขียนเพียงครั้งเดียว


1
สิ่งที่ฉันต้องการจะพูด บ่อยครั้งเมื่อฉันพบว่าตัวเองกำลังใช้breakงานอยู่ฉันพยายามหาวิธีการ refactor โค้ดให้เป็นฟังก์ชันเพื่อที่ฉันจะได้ใช้returnแทนได้
Rene Saarsoo

ฉันเห็นด้วยกับคุณ 100% ไม่มีอะไรผิดปกติกับการใช้ตัวแบ่ง อย่างไรก็ตามโดยทั่วไปบ่งชี้ว่ารหัสที่อยู่ในอาจจำเป็นต้องแยกออกมาเป็นฟังก์ชันที่จะแทนที่ตัวแบ่งด้วยการส่งคืน ควรถือเป็น 'กลิ่นรหัส' มากกว่าความผิดพลาดโดยสิ้นเชิง
vascowhite

คำตอบของคุณอาจแจ้งบางอย่างเพื่อสำรวจความสมควรของการใช้งบการกลับมาหลาย
DavidRR

13

มันขึ้นอยู่กับภาษา ในขณะที่คุณสามารถตรวจสอบตัวแปรบูลีนได้ที่นี่:

for (int i = 0; i < 100 && stayInLoop; i++) { ... }

เป็นไปไม่ได้ที่จะทำเมื่อวนซ้ำอาร์เรย์:

for element in bigList: ...

อย่างไรก็ตามbreakจะทำให้รหัสทั้งสองอ่านได้ง่ายขึ้น


7

ในตัวอย่างของคุณคุณไม่ทราบจำนวนการวนซ้ำสำหรับfor loop ทำไมไม่ใช้while loop แทนซึ่งทำให้จำนวนการวนซ้ำไม่แน่นอนในตอนเริ่มต้น

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


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

2
ในตัวอย่างที่ให้มา - การค้นหาคีย์ผ่านอาร์เรย์สำหรับลูปคือโครงสร้างสำนวนที่เหมาะสม คุณไม่ได้ใช้ while loop เพื่อเดินผ่านอาร์เรย์ คุณใช้สำหรับลูป (หรือสำหรับแต่ละลูปถ้ามี) คุณทำสิ่งนี้เพื่อเป็นการเอื้อเฟื้อต่อโปรแกรมเมอร์คนอื่น ๆ เนื่องจากพวกเขารับรู้โครงสร้าง "for (int i = 0; i <ra.length; i ++) {}" ทันทีในรูปแบบ "เดินผ่านอาร์เรย์" การเพิ่มช่วงพักให้กับโครงสร้างนี้คือ เพียงแค่คำสั่ง "เลิกเร็วถ้าคุณทำได้"
Chris Cudmore

7

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

  • ทรัพยากรที่ได้มาที่ด้านบนสุดของบล็อกอาจถูกปล่อยออกที่ด้านล่าง (ซึ่งเป็นจริงแม้กระทั่งสำหรับบล็อกที่อยู่ในforลูป) แต่ขั้นตอนการเผยแพร่นั้นอาจข้ามไปโดยไม่ได้ตั้งใจเมื่อการออก "ก่อนกำหนด" เกิดจากbreakคำสั่ง (ใน "สมัยใหม่" C ++, "RAII" ถูกใช้เพื่อจัดการกับสิ่งนี้ด้วยวิธีที่เชื่อถือได้และปลอดภัยโดยทั่วไปแล้ว object จะทำลายทรัพยากรฟรีได้อย่างน่าเชื่อถือไม่ว่าจะออกจากขอบเขตก็ตาม)

  • บางคนอาจเปลี่ยนแปลงการทดสอบตามเงื่อนไขในforคำสั่งโดยไม่สังเกตว่ามีเงื่อนไขการออกจากตำแหน่งอื่น ๆ

  • คำตอบของ ndim สังเกตว่าบางคนอาจหลีกเลี่ยงbreaks เพื่อรักษาเวลาการทำงานของลูปที่ค่อนข้างสม่ำเสมอ แต่คุณกำลังเปรียบเทียบbreakกับการใช้ตัวแปรควบคุมการออกจากต้นบูลีนโดยที่ไม่ได้ถือ

ทุก ๆ ครั้งที่ผู้คนสังเกตเห็นจุดบกพร่องดังกล่าวตระหนักว่าพวกเขาสามารถป้องกัน / บรรเทาได้ด้วยกฎ "ไม่หยุดพัก" นี้ ... แท้จริงแล้วมีกลยุทธ์ที่เกี่ยวข้องทั้งหมดสำหรับการเขียนโปรแกรมที่ "ปลอดภัยกว่า" ที่เรียกว่า "การเขียนโปรแกรมแบบมีโครงสร้าง" ซึ่งแต่ละฟังก์ชันควรมี จุดเข้าและออกเพียงจุดเดียว (เช่นไม่มี goto ไม่มีการกลับก่อนเวลา) มันอาจกำจัดจุดบกพร่องบางอย่าง แต่ก็แนะนำคนอื่นอย่างไม่ต้องสงสัย ทำไมพวกเขาถึงทำมัน?

  • พวกเขามีกรอบการพัฒนาที่สนับสนุนรูปแบบการเขียนโปรแกรม / โค้ดโดยเฉพาะและมีหลักฐานทางสถิติว่าสิ่งนี้ก่อให้เกิดประโยชน์สุทธิในกรอบที่ จำกัด นั้นหรือ
  • พวกเขาได้รับอิทธิพลจากแนวทางการเขียนโปรแกรมหรือประสบการณ์ภายในกรอบดังกล่าวหรือ
  • พวกเขาเป็นแค่คนโง่เผด็จการหรือ
  • ความเฉื่อยในอดีต + ใด ๆ ข้างต้น (เกี่ยวข้องกับเหตุผลที่สามารถใช้ได้กับ C มากกว่า C ++ สมัยใหม่)

ใช่แล้ว แต่แล้วอีกครั้งฉันเคยเห็นข้อบกพร่องในโค้ดโดยคนที่พยายามหลีกเลี่ยงทางศาสนา breakแต่ข้อบกพร่องแล้วอีกครั้งที่ผมเคยเห็นในรหัสโดยผู้ที่เคร่งครัดพยายามหลีกเลี่ยง พวกเขาหลีกเลี่ยงมัน แต่ล้มเหลวที่จะคิดผ่านเงื่อนไขที่เข้ามาแทนที่การหยุดพัก
Tomáš Zato - คืนสถานะ Monica

5

มันเป็นเรื่องที่ดีที่สุดที่ถูกต้องในการใช้งานbreak- ตามที่คนอื่น ๆ gotoได้ออกมาชี้ว่ามันไม่มีที่ไหนในลีกเช่นเดียวกับ

แม้ว่าคุณอาจต้องการใช้vFoundตัวแปรเมื่อคุณต้องการตรวจสอบนอกลูปว่าพบค่าในอาร์เรย์หรือไม่ นอกจากนี้จากมุมมองของการบำรุงรักษาการมีธงทั่วไปที่ส่งสัญญาณถึงเกณฑ์การออกอาจมีประโยชน์


5

ฉันทำการวิเคราะห์บางส่วนเกี่ยวกับ codebase ที่ฉันกำลังทำงานอยู่ (JavaScript 40,000 บรรทัด)

ฉันพบข้อความเพียง 22 รายการbreakในจำนวนนี้:

  • 19 ถูกใช้ภายใน switchงบ (เรามีคำสั่ง switch ทั้งหมด 3 รายการเท่านั้น!)
  • 2 ถูกใช้ภายในforลูป - รหัสที่ฉันจัดประเภททันทีว่าถูก refactored เป็นฟังก์ชันแยกต่างหากและแทนที่ด้วยreturnคำสั่ง
  • สำหรับวงbreakในรอบสุดท้ายwhile... ฉันวิ่งgit blameไปดูว่าใครเขียนอึนี้!

ตามสถิติของฉัน: หากbreakใช้ภายนอกswitchมันเป็นกลิ่นรหัส

ฉันยังค้นหาcontinueงบ ไม่พบเลย


4

ฉันไม่เห็นเหตุผลใด ๆ ว่าทำไมจึงเป็นการปฏิบัติที่ไม่ดีที่ระบุว่าคุณต้องการดำเนินการ STOP ให้เสร็จสิ้น ณ จุดนั้น


4

ในโลกฝังตัวมีโค้ดมากมายที่ใช้โครงสร้างต่อไปนี้:

    while(1)
    { 
         if (RCIF)
           gx();
         if (command_received == command_we_are_waiting_on)
           break;
         else if ((num_attempts > MAX_ATTEMPTS) || (TickGet() - BaseTick > MAX_TIMEOUT))
           return ERROR;
         num_attempts++;
    }
    if (call_some_bool_returning_function())
      return TRUE;
    else
      return FALSE;

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

ความคิดเห็นส่วนตัวของฉันคือไม่มีอะไรผิดปกติในการเขียนวนซ้ำในลักษณะนี้ตราบเท่าที่มีการดูแลที่เหมาะสมเพื่อป้องกันไม่ให้วนซ้ำไปเรื่อย ๆ


1
คุณช่วยอธิบายให้ละเอียดได้ไหม ดูเหมือนว่าฉันจะวนซ้ำไม่ได้ทำอะไรเลย ... เว้นแต่จะมีcontinueข้อความในตรรกะของแอปพลิเคชัน มีมั้ย?
Rene Saarsoo

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

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

"ถ้า (call_some_bool_returning_function ()) ส่งคืน TRUE มิฉะนั้นจะคืนค่า FALSE;" อาจเป็นเพียง "return call_some_bool_returning_function ()"
frankster

3

ขึ้นอยู่กับกรณีการใช้งานของคุณ มีแอพพลิเคชั่นที่รันไทม์ของ for loop ต้องคงที่ (เช่นเพื่อตอบสนองข้อ จำกัด ด้านเวลาหรือเพื่อซ่อนข้อมูลภายในจากการโจมตีตามเวลา

ในกรณีเหล่านี้การตั้งค่าสถานะจะสมเหตุสมผลและตรวจสอบค่าแฟล็กหลังจากทั้งหมดเท่านั้น forวนซ้ำวนซ้ำทั้งหมดทำงานจริงเท่านั้น แน่นอนว่าการวนซ้ำสำหรับการวนซ้ำทั้งหมดจำเป็นต้องเรียกใช้โค้ดที่ยังคงใช้เวลาประมาณเดียวกัน

หากคุณไม่สนใจเกี่ยวกับเวลาทำงาน ... ให้ใช้break;และcontinue;เพื่อให้โค้ดอ่านง่ายขึ้น


1
หากเวลาเป็นสิ่งสำคัญคุณอาจจะควรหยุดการทำงานบางอย่างและประหยัดทรัพยากรระบบมากกว่าปล่อยให้โปรแกรมทำการดำเนินการที่ไม่รู้ว่าไม่มีประโยชน์
Bgs

2

ในกฎMISRA 98 ที่ใช้กับ บริษัท ของฉันใน C dev จะไม่ใช้คำสั่ง break ...

แก้ไข: อนุญาตให้หยุดพักใน MISRA '04


2
ทำไมฉันถึงถามคำถามนี้! ฉันไม่พบเหตุผลที่ดีว่าทำไมจึงมีกฎดังกล่าวเป็นแนวทางการเข้ารหัส เช่นเดียวกับที่คนอื่น ๆ กล่าวว่าทำลาย; ดูดีขึ้น.
kiki

1
ฉันไม่รู้ว่าทำไมถึงห้าม (คนที่ฉลาดกว่าฉันคิดเรื่องนี้ ... ) แต่การทำลาย (และการคืนสินค้าหลายครั้ง) นั้นดีกว่าสำหรับการอ่าน (ในความคิดของฉัน แต่ความคิดเห็นของฉันไม่ใช่กฎขององค์กร ... )
Benoît

1
เอ่อกฎ MISRA อนุญาตให้ใช้คำสั่งแบ่ง: misra.org.uk/forum/viewtopic.php?f=75&t=298
luis.espinal

เราใช้กฎ MISRA 98 ... แน่นอนว่า MISRA 2004 เปลี่ยนกฎ
Benoît

0

Ofcourse break;คือทางออกในการหยุดลูป for loop หรือ foreach loop ฉันใช้มันใน php ใน foreach และสำหรับ loop และพบว่าใช้งานได้


0

ฉันไม่เห็นด้วย!

ทำไมคุณถึงเพิกเฉยต่อฟังก์ชันการทำงานในตัวของ for loop ที่จะสร้างขึ้นเอง คุณไม่จำเป็นต้องสร้างล้อใหม่

ฉันคิดว่ามันสมเหตุสมผลกว่าที่จะมีการตรวจสอบของคุณที่ด้านบนสุดของห่วงเช่นนั้น

for(int i = 0; i < myCollection.Length && myCollection[i].SomeValue != "Break Condition"; i++)
{
//loop body
}

หรือหากคุณต้องการประมวลผลแถวก่อน

for(int i = 0; i < myCollection.Length && (i == 0 ? true : myCollection[i-1].SomeValue != "Break Condition"); i++)
{
//loop body
}

ด้วยวิธีนี้คุณสามารถเขียนฟังก์ชันเพื่อดำเนินการทุกอย่างและสร้างโค้ดที่สะอาดขึ้นมาก

for(int i = 0; i < myCollection.Length && (i == 0 ? true : myCollection[i-1].SomeValue != "Break Condition"); i++)
{
    DoAllThatCrazyStuff(myCollection[i]);
}

หรือหากเงื่อนไขของคุณซับซ้อนคุณสามารถย้ายรหัสนั้นออกได้เช่นกัน!

for(int i = 0; i < myCollection.Length && BreakFunctionCheck(i, myCollection); i++)
{
    DoAllThatCrazyStuff(myCollection[i]);
}

"รหัสมืออาชีพ" ที่เต็มไปด้วยตัวแบ่งฟังดูไม่เหมือนรหัสมืออาชีพสำหรับฉัน ดูเหมือนขี้เกียจเขียนโค้ด;)


4
lazy coding IS professional code :)
Jason

เฉพาะในกรณีที่ไม่ปวดก้นเพื่อรักษา :)
Biff MaGriff

2
ฉันมักจะฝึก "GTFO ASAP" นั่นคือถ้าฉันสามารถออกจากโครงสร้างได้อย่างหมดจดฉันควรทำโดยเร็วที่สุดและใกล้เคียงกับเงื่อนไขที่ระบุทางออก
Chris Cudmore

ได้ผลเช่นกัน ฉันคิดว่าข้อโต้แย้งที่ฉันพยายามจะข้ามคือถ้าคุณใช้ for loop การใช้ฟังก์ชันในตัวเพื่อให้โค้ดของคุณอ่านได้และเป็นโมดูลไม่เจ็บ หากคุณจำเป็นต้องมีคำสั่งแบ่งภายในวงของคุณอย่างแท้จริงฉันจะนั่งคิดว่าทำไมต้องมีความซับซ้อนระดับนั้น
Biff MaGriff

1
ฮ่าฮ่า ลองพิจารณาความจริงที่ว่าคนส่วนใหญ่ที่ไม่สนับสนุนbreakให้เหตุผลว่าเป็นเพราะความสามารถในการอ่านโค้ด ตอนนี้ดูสภาพยาว 5 ไมล์ที่บ้าคลั่งในลูปด้านบนอีกครั้ง ...
Tomáš Zato - Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.