เป็นไปได้ไหมที่จะใช้break
ฟังก์ชั่นนี้เพื่อออกจากfor
ลูปซ้อนหลายอัน?
ถ้าเป็นเช่นนั้นคุณจะทำสิ่งนี้อย่างไร คุณสามารถควบคุมจำนวนการbreak
ออกจากลูปได้หรือไม่
เป็นไปได้ไหมที่จะใช้break
ฟังก์ชั่นนี้เพื่อออกจากfor
ลูปซ้อนหลายอัน?
ถ้าเป็นเช่นนั้นคุณจะทำสิ่งนี้อย่างไร คุณสามารถควบคุมจำนวนการbreak
ออกจากลูปได้หรือไม่
คำตอบ:
AFAIK, C ++ ไม่รองรับการตั้งชื่อลูปเช่น Java และภาษาอื่น ๆ คุณสามารถใช้ goto หรือสร้างค่าสถานะที่คุณใช้ ในตอนท้ายของแต่ละวงให้ตรวจสอบค่าสถานะ หากตั้งค่าเป็นจริงคุณสามารถแยกออกจากการทำซ้ำนั้น
goto
หากเป็นตัวเลือกที่ดีที่สุด
goto
: โปรแกรมเมอร์ที่ไม่ดีและโปรแกรมเมอร์ในทางปฏิบัติ อดีตเป็นคำอธิบายตนเอง หลังซึ่งคุณจะพอดีถ้าคุณเลือกที่จะใช้พวกเขาอย่างดีใช้แนวคิดที่เรียกว่า "ความชั่วร้าย" เมื่อมันเป็นความชั่วร้ายที่น้อยกว่า (สอง) อ่านสิ่งนี้เพื่อทำความเข้าใจแนวคิด C ++ บางอย่างที่คุณอาจจำเป็นต้องใช้เป็นครั้งคราว (แมโคร, goto's, preprocessor, อาร์เรย์): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
goto
แทบจะไม่เคยเป็นตัวเลือกที่ดีที่สุด ทำไมไม่ใส่ลูปเข้าไปในฟังก์ชั่นของตัวเอง ( inline
ถ้าคุณกังวลเรื่องความเร็ว) และreturn
จากนี้
break
ไม่ไม่ต้องเสียมันด้วย goto
นี่คือที่มั่นสุดท้ายที่เหลืออยู่สำหรับการใช้งานของ
เพียงเพิ่มคำตอบที่ชัดเจนโดยใช้ lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
แน่นอนรูปแบบนี้มีข้อ จำกัด บางอย่างและเห็นได้ชัดว่า C ++ 11 เท่านั้น แต่ฉันคิดว่ามันค่อนข้างมีประโยชน์
อีกวิธีหนึ่งในการแยกออกจากลูปซ้อนกันคือการแยกลูปทั้งสองออกเป็นฟังก์ชันแยกต่างหากและreturn
จากฟังก์ชันนั้นเมื่อคุณต้องการออก
แน่นอนว่าสิ่งนี้จะทำให้เกิดข้อโต้แย้งอื่น ๆ ว่าคุณควรชัดเจนreturn
จากฟังก์ชั่นที่ใดก็ตามที่นอกเหนือจากในตอนท้าย
continue_processing
) ที่ควบคุมการทำงานของบล็อกของโค้ดต่อไปในฟังก์ชัน
หยุดพักจะออกจากลูปที่อยู่ด้านในสุดเท่านั้น
คุณสามารถใช้gotoเพื่อแยกลูปออกเป็นจำนวนเท่าใดก็ได้
แน่นอนกลับไปข้างมักจะพิจารณาอันตราย
เหมาะสมที่จะใช้ฟังก์ชั่นหยุดพัก [... ]?
การใช้ตัวแบ่งและการข้ามไปอาจทำให้เหตุผลที่ยากขึ้นเกี่ยวกับความถูกต้องของโปรแกรม ดูที่นี่สำหรับการอภิปรายเกี่ยวกับเรื่องนี้: Dijkstra ไม่ได้บ้า
break
return
break
และreturn
มีความได้เปรียบมากกว่าgoto
ที่คุณไม่จำเป็นต้องตามหาฉลากเพื่อค้นหาว่าพวกเขาไปที่ไหน ใช่ภายใต้พวกเขาเป็นบางประเภทgoto
แต่มีข้อ จำกัด มาก goto
พวกเขาจะง่ายมากที่จะถอดรหัสโดยโปรแกรมเมอร์ของสมองรูปแบบจับคู่กว่าไม่ จำกัด ดังนั้น IMO จึงเหมาะสมกว่า
goto
มันเป็นเพียงการดีกว่าทนกว่า
แม้ว่าคำตอบนี้ถูกนำเสนอไปแล้ว แต่ฉันคิดว่าวิธีการที่ดีคือทำดังต่อไปนี้:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoop
มีการตรวจสอบทุกรอบ
goto
ทำให้คอร์สามารถอ่านได้และมีประสิทธิภาพมากขึ้น
แล้วเรื่องนี้ล่ะ
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
ตัวอย่างโค้ดที่ใช้goto
และเลเบลเพื่อแยกลูปซ้อนกัน:
for (;;)
for (;;)
goto theEnd;
theEnd:
วิธีที่ดีวิธีหนึ่งในการแบ่งลูปซ้อนหลาย ๆ อันให้ปรับโครงสร้างโค้ดของคุณเป็นฟังก์ชัน:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
ข้ามไปจะมีประโยชน์มากสำหรับการแบ่งลูปซ้อนกัน
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
break
คำสั่งยุติการดำเนินการของการปิดล้อมที่ใกล้ที่สุดdo
,for
,switch
หรือwhile
คำสั่งที่ปรากฏ การควบคุมผ่านไปยังคำสั่งที่ตามหลังคำสั่งที่ถูกยกเลิก
ฉันคิดว่า goto
ใช้ได้ในกรณีนี้:
เพื่อจำลอง a break
/continue
คุณต้องการ:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
สำหรับวงแรกคือ ดังนั้นi++
ก่อนที่จะข้ามไป
ภาษาอื่น ๆ เช่น PHP ยอมรับพารามิเตอร์สำหรับตัวแบ่ง (เช่น break 2;) เพื่อระบุจำนวนของระดับลูปที่ซ้อนกันที่คุณต้องการแยกออก แต่ C ++ ไม่ได้ คุณจะต้องทำมันออกมาโดยใช้บูลีนที่คุณตั้งค่าเป็นเท็จก่อนที่จะวนซ้ำตั้งค่าเป็นจริงในลูปถ้าคุณต้องการที่จะทำลายรวมทั้งตัวแบ่งตามเงื่อนไขหลังจากวนซ้อนกันตรวจสอบว่าบูลีนถูกตั้งค่าเป็นจริง และทำลายถ้าใช่
ฉันรู้ว่านี่คือโพสต์เก่า แต่ฉันขอแนะนำคำตอบที่สมเหตุสมผลและเรียบง่าย
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionj
j < conditionj
ทำลายลูปจำนวนเท่าใดก็ได้ด้วยbool
ตัวแปรเพียงตัวเดียวดูด้านล่าง:
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
ในรหัสนี้เราbreak;
ทุกคนลูป
ฉันไม่แน่ใจว่ามันคุ้มค่าหรือไม่ แต่คุณสามารถเลียนแบบลูปของ Java ที่มีมาโครง่ายๆ:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
ตัวอย่างการใช้งาน:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
ตัวอย่างอื่น:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
while (i<n) {
bool shouldBreakOuter = false;
for (int j=i + 1; j<n; ++j) {
if (someCondition) {
shouldBreakOuter = true;
}
}
if (shouldBreakOuter == true)
break;
}
คุณสามารถใช้ลอง ... จับ
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
หากคุณต้องแบ่งออกเป็นหลายลูปในครั้งเดียวก็มักจะเป็นข้อยกเว้นต่อไป
การแตกออกจาก for-loop นั้นค่อนข้างแปลกสำหรับฉันเนื่องจากความหมายของ for-loop นั้นโดยทั่วไปจะระบุว่ามันจะทำงานตามจำนวนที่ระบุ อย่างไรก็ตามมันก็ไม่ได้เลวร้ายในทุกกรณี หากคุณกำลังค้นหาบางอย่างในคอลเลกชันและต้องการทำลายหลังจากที่คุณพบมันมีประโยชน์ การแยกออกจากลูปซ้อนกันเป็นไปไม่ได้ใน C ++ มันเป็นภาษาอื่น ๆ ผ่านการใช้ตัวแบ่งที่มีป้ายกำกับ คุณสามารถใช้ป้ายกำกับและข้ามไปได้ แต่นั่นอาจทำให้คุณอิจฉาริษยาตอนกลางคืน .. ? ดูเหมือนว่าตัวเลือกที่ดีที่สุดแม้ว่า